Skip to content

필사 모드: Spring Boot 설정 파일 구조와 폴더 구조 완전 가이드: application.yml 마스터하기

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

목차

1. [프로젝트 표준 폴더 구조](#1-프로젝트-표준-폴더-구조)

2. [레이어드 아키텍처 vs 도메인 중심 구조](#2-레이어드-아키텍처-vs-도메인-중심-구조)

3. [application.yml 계층 구조](#3-applicationyml-계층-구조)

4. [외부 설정 우선순위](#4-외부-설정-우선순위)

5. [@ConfigurationProperties 활용](#5-configurationproperties-활용)

6. [멀티 모듈 프로젝트 구조](#6-멀티-모듈-프로젝트-구조)

7. [Kubernetes ConfigMap/Secret 연동](#7-kubernetes-configmapsecret-연동)

8. [퀴즈](#8-퀴즈)

1. 프로젝트 표준 폴더 구조

Spring Boot 프로젝트는 Maven/Gradle 표준 디렉터리 레이아웃을 따릅니다. 일관된 구조는 팀 협업과 유지보수성을 크게 향상시킵니다.

my-project/

├── src/

│ ├── main/

│ │ ├── java/

│ │ │ └── com/example/app/

│ │ │ ├── AppApplication.java

│ │ │ ├── config/

│ │ │ │ ├── SecurityConfig.java

│ │ │ │ ├── WebMvcConfig.java

│ │ │ │ └── SwaggerConfig.java

│ │ │ ├── controller/

│ │ │ │ ├── UserController.java

│ │ │ │ └── ProductController.java

│ │ │ ├── service/

│ │ │ │ ├── UserService.java

│ │ │ │ └── UserServiceImpl.java

│ │ │ ├── repository/

│ │ │ │ └── UserRepository.java

│ │ │ ├── domain/

│ │ │ │ ├── User.java

│ │ │ │ └── dto/

│ │ │ │ ├── UserRequest.java

│ │ │ │ └── UserResponse.java

│ │ │ ├── exception/

│ │ │ │ ├── GlobalExceptionHandler.java

│ │ │ │ └── BusinessException.java

│ │ │ ├── security/

│ │ │ │ ├── JwtTokenProvider.java

│ │ │ │ └── JwtAuthFilter.java

│ │ │ └── util/

│ │ │ └── DateUtils.java

│ │ └── resources/

│ │ ├── application.yml

│ │ ├── application-dev.yml

│ │ ├── application-staging.yml

│ │ ├── application-prod.yml

│ │ ├── db/

│ │ │ └── migration/

│ │ │ ├── V1__create_users.sql

│ │ │ └── V2__add_user_index.sql

│ │ ├── static/

│ │ │ ├── css/

│ │ │ └── js/

│ │ ├── templates/

│ │ │ └── email/

│ │ │ └── welcome.html

│ │ └── messages/

│ │ ├── messages.properties

│ │ └── messages_ko.properties

└── test/

├── java/

│ └── com/example/app/

│ ├── controller/

│ ├── service/

│ └── repository/

└── resources/

├── application-test.yml

└── data.sql

각 패키지별 역할

| 패키지 | 역할 | 포함 클래스 |

| ---------- | ----------------------------------- | ----------------------------------- |

| config | Spring 설정 클래스 모음 | SecurityConfig, WebMvcConfig |

| controller | HTTP 요청 처리 (Presentation Layer) | @RestController 클래스 |

| service | 비즈니스 로직 (Business Layer) | @Service 클래스 |

| repository | 데이터 접근 (Data Layer) | @Repository, JpaRepository |

| domain | 도메인 모델 | @Entity, DTO, VO |

| exception | 예외 처리 | @ControllerAdvice, Custom Exception |

| security | 보안 관련 컴포넌트 | Filter, Provider, Handler |

| util | 공통 유틸리티 | Static helper 메서드 |

2. 레이어드 아키텍처 vs 도메인 중심 구조

전통적 레이어 구조 (기능별 패키지)

com/example/app/

├── controller/

│ ├── UserController.java

│ ├── OrderController.java

│ └── ProductController.java

├── service/

│ ├── UserService.java

│ ├── OrderService.java

│ └── ProductService.java

└── repository/

├── UserRepository.java

├── OrderRepository.java

└── ProductRepository.java

장점: 레이어별로 파일을 찾기 쉬움

단점: 도메인 단위로 변경 시 여러 패키지를 동시에 수정해야 함

도메인 중심 구조 (도메인별 패키지)

com/example/app/

├── user/

│ ├── UserController.java

│ ├── UserService.java

│ ├── UserRepository.java

│ ├── User.java

│ └── UserDto.java

├── order/

│ ├── OrderController.java

│ ├── OrderService.java

│ └── Order.java

└── product/

├── ProductController.java

└── Product.java

장점: 도메인별 응집도가 높고 독립 배포에 유리

단점: 같은 레이어의 파일을 한 번에 보기 어려움

헥사고날 아키텍처 폴더 구조

com/example/app/

└── user/

├── application/

│ ├── port/

│ │ ├── in/

│ │ │ └── CreateUserUseCase.java

│ │ └── out/

│ │ └── UserRepository.java

│ └── service/

│ └── CreateUserService.java

├── domain/

│ └── User.java

└── adapter/

├── in/

│ └── web/

│ └── UserController.java

└── out/

└── persistence/

└── UserJpaRepository.java

헥사고날 아키텍처는 외부 의존성(DB, 메시지 브로커 등)을 인터페이스로 격리하여 테스트 용이성과 교체 가능성을 높입니다.

3. application.yml 계층 구조

기본 구조와 Profile 분리

Spring Boot 2.4 이후에는 단일 파일에서 `---` 구분자로 여러 프로파일을 정의할 수 있습니다.

application.yml - 공통 설정

spring:

application:

name: my-service

jackson:

default-property-inclusion: non_null

time-zone: Asia/Seoul

logging:

level:

root: INFO

com.example: DEBUG

management:

endpoints:

web:

exposure:

include: health,info,metrics

dev 프로파일

spring:

config:

activate:

on-profile: dev

datasource:

url: jdbc:postgresql://localhost:5432/devdb

username: devuser

password: devpass

jpa:

hibernate:

ddl-auto: create-drop

show-sql: true

logging:

level:

org.hibernate.SQL: DEBUG

staging 프로파일

spring:

config:

activate:

on-profile: staging

datasource:

url: jdbc:postgresql://staging-db:5432/stagingdb

username: ${DB_USERNAME}

password: ${DB_PASSWORD}

jpa:

hibernate:

ddl-auto: validate

prod 프로파일

spring:

config:

activate:

on-profile: prod

datasource:

url: jdbc:postgresql://prod-db:5432/proddb

username: ${DB_USERNAME}

password: ${DB_PASSWORD}

jpa:

hibernate:

ddl-auto: validate

show-sql: false

logging:

level:

root: WARN

com.example: INFO

별도 파일로 Profile 분리 (권장 방식)

대규모 프로젝트에서는 파일을 분리하면 관리가 더 쉬워집니다.

resources/

├── application.yml # 공통 설정

├── application-dev.yml # 개발 환경

├── application-staging.yml # 스테이징 환경

└── application-prod.yml # 운영 환경

프로파일 활성화 방법:

커맨드라인으로 활성화

java -jar app.jar --spring.profiles.active=prod

환경변수로 활성화

export SPRING_PROFILES_ACTIVE=prod

4. 외부 설정 우선순위

Spring Boot는 다양한 소스에서 설정을 읽어오며, 우선순위가 높은 것이 낮은 것을 덮어씁니다.

우선순위 (높은 것이 낮은 것을 덮어씀)

1. 커맨드라인 인자 (`--server.port=9090`)

2. `SPRING_APPLICATION_JSON` 환경변수 (인라인 JSON)

3. `ServletConfig` 초기화 파라미터

4. `ServletContext` 초기화 파라미터

5. JNDI 속성 (`java:comp/env/`)

6. Java 시스템 프로퍼티 (`System.getProperties()`)

7. OS 환경변수

8. 무작위 값 프로퍼티 소스 (`random.\*)

9. 프로파일별 외부 application 파일 (`application-dev.yml` — JAR 외부)

10. 외부 application 파일 (`application.yml` — JAR 외부)

11. 프로파일별 내부 application 파일 (`application-dev.yml` — JAR 내부)

12. 내부 application 파일 (`application.yml` — JAR 내부)

13. `@PropertySource` 애노테이션

14. 기본값 (`SpringApplication.setDefaultProperties`)

환경변수를 이용한 설정 오버라이드

프로퍼티명의 점(.)은 밑줄(_)로, 대문자로 변환

export SERVER_PORT=9090

export SPRING_DATASOURCE_URL=jdbc:postgresql://prod-db:5432/mydb

export SPRING_DATASOURCE_USERNAME=produser

커맨드라인 인자 예시

java -jar app.jar \

--server.port=9090 \

--spring.profiles.active=prod \

--spring.datasource.url=jdbc:postgresql://prod-db:5432/mydb

5. @ConfigurationProperties 활용

`@ConfigurationProperties`는 관련 설정을 타입 안전한 방식으로 묶어 관리할 수 있게 해줍니다.

application.yml 설정

app:

api-key: my-secret-key

timeout: 30s

allowed-hosts:

- api.example.com

- admin.example.com

retry:

max-attempts: 3

delay: 1s

mail:

host: smtp.example.com

port: 587

from: no-reply@example.com

@ConfigurationProperties 클래스

@ConfigurationProperties(prefix = "app")

@Validated

@Getter

@Setter

public class AppProperties {

@NotNull

private String apiKey;

private Duration timeout = Duration.ofSeconds(30);

private List<String> allowedHosts = new ArrayList<>();

private Retry retry = new Retry();

private Mail mail = new Mail();

@Getter

@Setter

public static class Retry {

private int maxAttempts = 3;

private Duration delay = Duration.ofSeconds(1);

}

@Getter

@Setter

public static class Mail {

private String host;

private int port = 587;

private String from;

}

}

Bean 등록

@SpringBootApplication

@EnableConfigurationProperties(AppProperties.class)

public class AppApplication {

public static void main(String[] args) {

SpringApplication.run(AppApplication.class, args);

}

}

또는 클래스에 직접 `@Component` 추가:

@Component

@ConfigurationProperties(prefix = "app")

@Validated

public class AppProperties { ... }

IDE 자동완성 지원 (메타데이터 생성)

이 의존성을 추가하면 컴파일 시 `META-INF/spring-configuration-metadata.json`이 생성되어 IDE에서 application.yml 자동완성이 동작합니다.

6. 멀티 모듈 프로젝트 구조

대규모 프로젝트에서는 단일 모듈보다 멀티 모듈 구조가 코드 재사용과 경계 분리에 유리합니다.

Maven 멀티 모듈 구조

my-project/ # Parent POM

├── pom.xml # Parent POM

├── my-api/ # REST API 모듈

│ ├── pom.xml

│ └── src/main/java/

│ └── com/example/api/

├── my-domain/ # 도메인/비즈니스 로직 모듈

│ ├── pom.xml

│ └── src/main/java/

│ └── com/example/domain/

├── my-infrastructure/ # DB, 외부 API 연동 모듈

│ ├── pom.xml

│ └── src/main/java/

│ └── com/example/infra/

└── my-common/ # 공통 유틸리티 모듈

├── pom.xml

└── src/main/java/

└── com/example/common/

Parent pom.xml 예시

모듈 간 의존성 관리

my-api → my-domain → my-common

my-api → my-infrastructure → my-domain

순환 의존성이 발생하면 컴파일 오류가 발생합니다. 공통 인터페이스를 별도 모듈로 분리하여 순환을 방지합니다.

7. Kubernetes ConfigMap/Secret 연동

ConfigMap을 통한 설정 주입 (환경변수 방식)

kubernetes/configmap.yaml

apiVersion: v1

kind: ConfigMap

metadata:

name: my-app-config

data:

SPRING_PROFILES_ACTIVE: 'prod'

SERVER_PORT: '8080'

SPRING_DATASOURCE_URL: 'jdbc:postgresql://db-service:5432/mydb'

kubernetes/deployment.yaml

spec:

containers:

- name: my-app

envFrom:

- configMapRef:

name: my-app-config

- secretRef:

name: my-app-secret

Secret을 통한 민감 정보 주입

Secret 생성

kubectl create secret generic my-app-secret \

--from-literal=SPRING_DATASOURCE_USERNAME=produser \

--from-literal=SPRING_DATASOURCE_PASSWORD=secretpass \

--from-literal=JWT_SECRET=myJwtSecretKey

볼륨 마운트 방식 (파일로 주입)

ConfigMap을 파일로 마운트하면 application.yml 전체를 외부에서 관리할 수 있습니다.

kubernetes/deployment.yaml

spec:

volumes:

- name: config-volume

configMap:

name: my-app-config-files

containers:

- name: my-app

volumeMounts:

- name: config-volume

mountPath: /app/config

env:

- name: SPRING_CONFIG_LOCATION

value: 'classpath:/,file:/app/config/'

spring-cloud-kubernetes 연동

Spring Cloud Kubernetes를 사용하면 ConfigMap 변경 시 애플리케이션 재시작 없이 설정을 동적으로 갱신할 수 있습니다.

spring:

cloud:

kubernetes:

config:

enabled: true

name: my-app-config

namespace: default

reload:

enabled: true

mode: event

period: 15000

8. 퀴즈

**정답:** 운영 환경에서 애플리케이션을 재빌드하지 않고 설정을 변경할 수 있도록 하기 위해서입니다.

**설명:** Spring Boot의 외부 설정 우선순위 체계는 12-Factor App 원칙을 따릅니다. JAR 외부의 `application.yml`이나 환경변수, 커맨드라인 인자가 JAR 내부 설정보다 높은 우선순위를 가집니다. 이를 통해 같은 JAR 파일을 개발/스테이징/운영 환경에 그대로 배포하고, 설정만 환경별로 다르게 주입할 수 있습니다.

**정답:** 애플리케이션 시작 시 설정값의 유효성을 검사하여, 잘못된 설정으로 인한 런타임 오류를 사전에 방지하기 위해서입니다.

**설명:** `@Validated`와 JSR-303 Bean Validation 애노테이션(`@NotNull`, `@Min`, `@Max` 등)을 함께 사용하면, Spring Boot 애플리케이션 구동 시점에 설정값이 유효한지 검사합니다. 필수 설정이 누락되거나 값이 범위를 벗어나면 즉시 `BindValidationException`이 발생하여 빠른 피드백을 제공합니다.

**정답:** 공통 인터페이스나 공유 도메인 모델을 별도의 공통 모듈(common/shared 모듈)로 분리하고, 의존성 방향을 단방향으로 유지합니다.

**설명:** A 모듈이 B 모듈에 의존하고, B 모듈이 A 모듈에 의존하는 순환 의존성이 발생하면 컴파일이 불가능합니다. 두 모듈이 공통으로 필요한 인터페이스나 DTO를 별도의 `common` 모듈로 분리하면, A와 B가 모두 `common`에 의존하는 단방향 구조를 만들 수 있습니다.

**정답:** spring-cloud-kubernetes-client-config를 사용하고 `spring.cloud.kubernetes.reload.enabled=true`로 설정합니다.

**설명:** Spring Cloud Kubernetes는 ConfigMap의 변경을 감지하는 두 가지 모드를 제공합니다. `event` 모드는 Kubernetes API 이벤트를 감지하여 즉시 반응하고, `polling` 모드는 주기적으로 ConfigMap을 확인합니다. `@RefreshScope` 애노테이션이 붙은 Bean은 ConfigMap 변경 시 자동으로 재초기화됩니다.

**정답:** 해당 설정 블록이 특정 프로파일이 활성화되었을 때만 적용되도록 지정합니다.

**설명:** Spring Boot 2.4부터 단일 `application.yml` 파일에서 `---` 구분자로 여러 문서 블록을 나눌 수 있습니다. 각 블록에 `spring.config.activate.on-profile`을 지정하면 해당 프로파일이 활성화된 경우에만 그 블록의 설정이 적용됩니다. 이전 방식인 `spring.profiles`는 더 이상 권장하지 않으며 `spring.config.activate.on-profile`을 사용해야 합니다.

현재 단락 (1/347)

1. [프로젝트 표준 폴더 구조](#1-프로젝트-표준-폴더-구조)

작성 글자: 0원문 글자: 9,235작성 단락: 0/347