티스토리 뷰

Spring

[Spring] YAML , @Profile

hyuuny 2023. 4. 9. 23:40

YAML

  • 스프링은 설정 데이터를 사용할 때 application.properties 뿐만 아니라 application.yml이라는 형식도 지원한다.
  • YAML(YAML Ain't Markup Language)은 사람이 읽기 좋은 데이터 구조를 목표로 한다.
  • 확장자는 yaml, yml이다. 주로 yml을 사용한다.

application.properties

my.datasource.url=local.db.com
my.datasource.username=hyuuny
my.datasource.password=password
my.datasource.etc.max-connection=1
my.datasource.etc.timeout=3500ms
my.datasource.etc.options=CACHE,ADMIN

application.yml

my:
  datasource:
    url: local.db.com
    username: hyuuny
    password: password
    etc:
      max-connection: 1
      timeout: 3500ms
      options: CACHE,ADMIN
  • YAML의 가장 큰 특징은 사람이 읽기 좋게 계층 구조를 이룬다는 점이다.
  • YAML은 space(공백)로 계층 구조를 만든다. space는 1칸을 사용해도 되는데, 보통 2칸을 사용한다. 일관성있게 사용하지 않으면 읽기 어렵거나 구조가 깨질 수 있다.
  • 구분 기호로 :를 사용한다. 만약 값이 있다면 이렇게 key: value : 이후에 공백을 하나 넣고 값을 넣어주면 된다.

스프링은 YAML의 계층 구조를 properties처럼 평평하게 만들어서 읽어들인다.
즉, 위의 application.ymlapplication.properties처럼 만들어진다.


참고

  • application.properties, application.yml을 같이 사용하면 application.properties가 우선권을 가진다.
  • 둘이 함께 사용하는 것은 일관성이 없으므로 권장하지 않는다.
  • 대부분 실무에서는 설정 정보가 많아서 보기 편한 yml을 선호한다.

YML과 프로필

YML에도 프로필을 적용할 수 있다.

my:
  datasource:
    url: local.db.com
    username: hyuuny
    password: password
    etc:
      max-connection: 1
      timeout: 3500ms
      options: CACHE,ADMIN

---
spring:
  config:
    activate:
      on-profile: dev

my:
  datasource:
    url: dev.db.com
    username: dev_hyuuny
    password: password
    etc:
      max-connection: 10
      timeout: 60s
      options: DEV, CACHE

---
spring:
  config:
    activate:
      on-profile: prod

my:
  datasource:
    url: prod.db.com
    username: prod_hyuuny
    password: password
    etc:
      max-connection: 50
      timeout: 10s
      options: PROD, CACHE
  • yml--- dash(-) 3개를 사용해서 논리 파일을 구분한다.
  • spring.config.active.on-profile을 사용해서 프로필을 적용할 수 있다.
  • 나머지는 application.properties와 동일하다.

local 실행 결과

dev 실행 결과


@Profile

앞서 프로필과 외부 설정을 사용해서 각 환경마다 설정값을 다르게 적용하는 것을 확인했다. 이번에는 @Profile을 통해 각 개발 환경에 필요한 빈을 등록하는 방법에 대해 알아보자.


결제 기능을 붙여야 하는데, 로컬 개발 환경에서는 실제 결제가 발생하면 문제가 되니 가짜 결제 기능이 있는 스프링 빈을 등록하고, 운영 환경에서는 실제 결제 기능을 제공하는 스프링 빈을 등록한다고 가정한다.


PayClient

public interface PayClient {
    void pay(int money);
}
  • DI를 적극 활용하기 위해 인터페이스를 사용한다.

LocalPayClient

@Slf4j
public class LocalPayClient implements PayClient {

    @Override
    public void pay(int money) {
        log.info("로컬 결제 money={}", money);
    }
}
  • 로컬 개발 환경에서는 실제 결제를 하지 않는다.

ProdPayClient

@Slf4j
public class ProdPayClient implements PayClient {

    @Override
    public void pay(int money) {
        log.info("운영 결제 money={}", money);
    }
}
  • 운영 환경에서는 실제 결제를 시도한다.

OrderService

@RequiredArgsConstructor
@Service
public class OrderService {

    private final PayClient payClient;

    public void order(int money) {
        payClient.pay(money);
    }

}
  • PayClient를 사용하는 부분이다.
  • 상황에 따라서 LocalPayClient 또는 ProdPayClient를 주입받는다.

PayConfig

@Slf4j
@Configuration
public class PayConfig {

    @Profile("default")
    @Bean
    public LocalPayClient localPayClient() {
        log.info("LocalPayClient 빈 등록");
        return new LocalPayClient();
    }

    @Profile("prod")
    @Bean
    public ProdPayClient prodPayClient() {
        log.info("ProdPayClient 빈 등록");
        return new ProdPayClient();
    }

}
  • @Profile 애노테이션을 사용하면 해당 프로필이 활성화된 경우에만 빈을 등록한다.
    • default 프로필(기본값)이 활성화 되어 있으면 LocalPayClient를 빈으로 등록한다.
    • prod 프로필이 활성화 되어 있으면 ProdPayClient를 빈으로 등록한다.

OrderRunner

@RequiredArgsConstructor
@Component
public class OrderRunner implements ApplicationRunner {

    private final OrderService orderService;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        orderService.order(1000);
    }
}
  • ApplicationRunner 인터페이스를 사용하면 스프링은 빈 초기화가 모두 끝나고 애플리케이션 로딩이 완료되는 시점run(args) 메서드를 호출해준다.

default 실행 결과

  • 프로필 없이 실행하면 default 프로필이 사용된다.
  • default 프로필이 사용되면 LocalPayClient가 빈으로 등록되는 것을 확인할 수 있다.

prod 실행 결과

  • prod 프로필을 적용했다.
  • prod 프로필이 사용되면 ProdPayClient가 빈으로 등록되는 것을 확인할 수 있다.

@Profile

  • @interface Profile의 코드를 보면 @Conditional(ProfileCondition.class) 를 확인할 수 있다.
  • @Profile에 등록된 attributes를 가져와서 현재 활성화된 Profile과 일치하면 true, 아니면 false를 반환한다.
  • 스프링은 @Conditional 기능을 활용해서 개발자가 더 편리하게 사용할 수 있는 @Profile 기능을 제공한다.



Reference
김영한. 스프링 부트 - 핵심 원리와 활용. 인프런.

'Spring' 카테고리의 다른 글

[Spring] 메트릭 (metric)  (0) 2023.04.13
[Spring] actuator (액츄에이터)  (0) 2023.04.10
[Spring] 외부 설정 방법  (0) 2023.04.06
[Spring] 외부설정과 프로필 2  (0) 2023.04.03
[Spring] 외부설정과 프로필 1  (0) 2023.04.02
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함