본문 바로가기

Spring/Spring

Spring boot 설정 파일 yaml 사용법 (설정 파일을 읽어서 bean으로 필요할 때 사용하는 방법)

반응형

Spring boot의 설정 파일 YAML을 사용하는 방법

대부분의 애플리케이션에서 설정과 관련된 변수들은 보통 파일에다가 쓰고 읽어오는 방식으로 프로그래밍한다.

외부에 설정파일을 넣을 수도 있고 내부적으로 프로젝트에 넣을 수도 있다.

해당 파일들은 포맷(.properties, .ini 등)도 다양하다.

스프링 부트에서도 설정에 대한 내용을 다양한 파일에 적고 읽어와 사용하는데 그 중에서 가장 적합하고 스프링 부트에서 권장하는 형식인 yaml에 대해서 간단히 설명하고 사용해본다.

왜 YAML 이어야 하는가?

-> 사람이 보기 편하다!

1
2
3
4
5
6
7
environments:
    dev:
        url: http://dev.example.com
        name: Developer Setup
    prod:
        url: http://another.example.com
        name: My Cool App


[YAML]

1
2
3
4
environments.dev.url=http://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=http://another.example.com
environments.prod.name=My Cool App


[Properties]

똑같은 설정이지만 yaml을 사용할 경우 위와 같이 들여쓰기(띄어쓰기)로 구분하여 사람이 보기가 편하다. 곧 관리가 편리하다.

또한 아래와 같이 리스트로 표현하고자 할 때는 "-" (대쉬) 하나로 쓸 수 있다.

1
2
3
4
my:
servers:
    - dev.example.com
    - another.example.com


뿐만 아니라 profile을 지정해서 환경에 따라 설정값을 다르게 가져갈 수 있는 장점이 있고, 하나의 파일에서 마치 여러개의 설정파일을 쓰는 듯하게 구분하여 사용할 수 있다. (아래처럼 "---"를 써서 구분)

1
2
3
4
5
6
7
8
9
10
11
12
server:
    address: 192.168.1.100
---
spring:
    profiles: development
server:
    address: 127.0.0.1
---
spring:
    profiles: production & eu-central
server:
    address: 192.168.1.120


여러모로 장점이 많아서 잘 쓰면 아주 유용하게 사용할 수 있다.

굳이 단점을 말하자면 문법(?)이 아주 약간 엄격한 것이 단점이다. 예를들면 하위 계층을 표현할 때 tab들여쓰기가 아닌 공백문자를 써야한다든가, :(콜론) 다음에 공백 한칸이 있어야한다든가하는 문제가 있다.

이런 문제는 몇 번 삽질해보면 금방 깨닫게 되고 사용법을 아래에서 간단히 익히면 해결될 문제다.


진짜로 yaml 사용(테스트) 해보기 

example 프로젝트를 만들어 보았다.

[프로젝트 구조]

프로젝트 구조는 위와 같이 구성하였다. 기존에 있던 application.properties는 지우고 classpath인 src/main/resources에 application.yml 파일을 생성했다.

참고로 .yml = .yaml 이다. 또한 스프링부트에서는 자동으로 classpath안에 있는 설정파일을 찾게 되어있다.

위 그림은 spring-boot-starter-parent의 pom.xml의 일부로, 보다시피 application이 접두사(prefix?)로 붙은 설정파일을 classpath이하의 어떤 디렉토리에 있든 .yml, .yaml, .properties 순서로 찾아서 읽는다.

1
2
3
4
env:
  servers:
    - dev.example.com
    - prod.example.com


[application.yml]

보다시피 env 밑에 servers가 있는데 그 안에 List형태로 두 개의 String값이 들어가 있다.

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
package com.example.demo.config;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
@Component
@ConfigurationProperties(prefix="env")
public class TestConfig {
    
    //getter, setter
    private List<String> servers = new ArrayList<String>();
 
    public List<String> getServers() {
        return this.servers;
    }
 
    public void setServers(List<String> servers) {
        this.servers = servers;
    }
}
 


[TestConfig.java]

스프링 부트가 설정파일에서 읽어온 값을 관리할 객체를 나타낸 것이다.

@ConfigurationProperties로 설정 파일에서 읽어온 값을 해당 클래스에 바인딩할 것이고 prefix 부분을 두어서 필요한 부분만 가져올 수도 있다.

따라서 prefix인 "env" 아래에 있는 servers라는 List만 가져올 것이므로 클래스에 있는 변수의 자료형도 List<String>으로 설정해서 가져왔다.

또한 @Component로 설정해서 bean객체로 등록할 수 있게 했다.

bean객체로 등록하게되면 알다시피 스프링 부트 어디에든(?) bean객체를 주입받아 설정 값들을 사용할 수 있게 된다.

(* 참고로 스프링부트에서는 @SpringBootApplication가 쓰인 메인클래스가 있는 최상위 패키지 이하의 패키지에서 등록된 모든 Component를 스캔한다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.example.demo;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
import com.example.demo.config.TestConfig;
 
@RestController
public class TestController {
    
    @Autowired
    TestConfig testConfig;
    
    @RequestMapping("/")
    public String test() {
        return testConfig.getServers().get(0+ " / " + testConfig.getServers().get(1); 
    }
}


[TestController.java]

테스트를 위해 RestController를 만들었다.

또한 아까 등록한 bean객체를 주입받기 위해 @Autowired를 사용했고 루트경로(localhost:8080)로 들어왔을 때 해당 값을 리턴해서 테스트 해보았다.

[결과] -> 잘 나왔다.


변형된 사용법

무난하게 사용하는 방법은 위에서 설명한 것과 같고 이제는 조금 변형된 yaml파일의 경우에 설정 값을 가져오는 방법을 알아보려고한다.

1. application.yml이 아닌 다른 파일을 사용할 경우

특별한 경우가 아니면 application.yml 혹은 applicationXXX.yml 이런식으로 사용하면 자동으로 찾아진다.

그러나 abc.yml 같이 이름을 다르게 지정하고 싶고 경로도 다르게 하고 싶으면 아래와 같이 쓰면된다.

1
@ConfigurationProperties(locations="classpath:abc.yml", prefix="env")


스프링부트 1.4버전 이후부터는 'locations' property가 deprecated되었다. 심지어 @PropertySource 어노테이션으로 가져오려고 해도 yml을 지원하지 않는 문제가 있다... (@PropertySource는 스프링에서도 권장하지 않는 방법임.)

대신 application.yml에 spring.config.location과 spring.config.name을 이용해서 경로와 파일이름이 다른 yml파일을 적용시킬 수 있다.

2. 여러 자료구조를 사용할 경우

바인딩이 자연스럽게 된다.

1
2
3
4
5
env:
  servers: helloworld
  obj:
    number: 10
    sec: 10s


[applicatoin.yml]

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
package com.example.demo.config;
 
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
 
@Component
@ConfigurationProperties(prefix="env")
public class TestConfig {
    
    private String servers;
    private Sample obj;
    
    public String getServers() {
        return servers;
    }
    public void setServers(String servers) {
        this.servers = servers;
    }
    public Sample getObj() {
        return obj;
    }
    public void setObj(Sample obj) {
        this.obj = obj;
    }
    
}
cs

[TestConfig.java]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.demo.config;
 
import java.time.Duration;
 
public class Sample {
    private int number;
    private Duration sec;
    
    public int getNumber() {
        return number;
    }
    public void setNumber(int number) {
        this.number = number;
    }
    public Duration getSec() {
        return sec;
    }
    public void setSec(Duration sec) {
        this.sec = sec;
    }
    
}
 


[Sample.java]

[결과]

역시 잘 들어가 있다.


3. profile로 환경에 따른 설정파일 세팅하기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
spring:
  profiles:
    active: local # 기본 환경 선택
 
# local 환경
---
spring:
  profiles: local
  datasource:
    data: classpath:data-h2.sql # 시작할때 실행시킬 script
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: create-drop
  h2:
    console:
      enabled: true
 
# 운영 환경
---
spring:
  profiles: set1
server:
  port: 8081


<출처 : http://jojoldu.tistory.com/269>

위와 같이 spring.profiles.active: local로 하면 profiles가 :local인 설정이 적용되고 set1으로하면 set1인 설정이 적용된다.

default 환경을 설정해둘 수 있고 active되는 것마다 바꾸면 되니 개발하고 배포할 때 아주 편리하게 할 수 있다.


4. 여러 파일을 하나의 yml파일로 관리하기

이것은 3번처럼 그냥 ---으로 나누면 다른 파일에서 불러온 것처럼 쓸 수 있다. (고로 생략..)


* 참고사항

- 꼭 String이 아니어도 binding이 유연하게 적용된다.

- yaml을 작성할 때는 kebab case(중간에 -를 쓰는것)를 사용하는 것을 권장한다. ex) jeong-pro.server.ip: ...

반응형