💡이 포스팅은 김영한 님의 인프런 강의인 스프링 부트 - 핵심 원리와 활용을 수강하고 학습한 내용을 정리한 포스팅입니다.
김영한 님의 강의를 수강하며 정리한 GitHub Repository입니다.
이번 챕터에 대해 정리할 내용은 다음과 같습니다.
- Command Line Arguments vs Command Line Option Arguments
- Environment & PropertySource
- SystemEnvironmentPropertySource.checkPropertyName(String name)
- @Profile 마다 다른 설정 파일 읽기
- window system properties username 이슈
Command Line Arguments vs Command Line Option Arguments
강의에서 CommandLineRunner와 ApplicationRunner를 각각 설명하면서 CommandLine Arguments와 CommandLine Option Arguments라는 용어를 언급하셨는데, 이 둘의 차이에 대해 궁금해서 정리해 보았습니다.
쉽게 정리하면 CommandLine Arguments는 raw String으로 전달되는 인자를 뜻합니다.
String [] 형태로 전달되며, 인자로 testA, testA=testB를 전달하게 되면 ["testA", "testA=testB"]와 같이 = 이 있다고 해서 key=value 형태로 가져오는 것이 아닌 문자열 그 자체로 가져오게 됩니다.
반면 ApplicationRunner는 ApplicationArguments 객체로 인자가 전달되는데, ApplicationArguments의 구현체인 DefaultApplicationArguments의 내부에서 getOptionNames(), getOptionValues(), getNonOptionArgs()와 같은 메서드들을 확인할 수 있습니다.
즉, CommandLine Option Arguments는 ApplicationRunner를 사용할 때 등장하며 ApplicationArguments 객체에서 CommandLine Arguments와 CommandLine Option Arguments를 분리하는 것을 확인할 수 있습니다.
아래 SimpleCommandLinePropertySource를 살펴보면 아래와 같이 CommandLine Option Arguments에 대한 설명을 볼 수 있습니다.
CommandLine Option Arguments는 반드시 --optName[=optValue] 형태로 작성되어야 하며 =를 기준으로 양 옆에 띄어쓰기가 되어 있으면 안 된다고 합니다.
한 가지 의문점이 위에 Invalid examples of option arguments를 보면 마지막에 --foo=bar --foo=baz --foo=biz와 같이 사용하면 안 된다고 했는데, ApplicationArguments의 getOptionValues() 설명을 보면 --foo=bar --foo=baz --foo=biz와 같이 전달될 경우 value들을 list로 반환한다고 하고 실제 정상작동하는 것을 확인할 수 있습니다.
docs가 업데이트 되지 않은 것인지, 뭔가 다른 이유가 있는 것인지는 나중에 찾게 되면 수정해 놓도록 하겠습니다.
정리하면 --없이 전달되는 인자들은 CommandLine Arguments, --를 사용하여 전달되는 인자들은 CommandLine Option Arguments라고 할 수 있습니다.
testA: CommandLine Arguments
testA=testB: CommandLine Arguments
--testA: CommandLine Option Arguments
-- testA=testB: Command Line Option Arguments
마지막으로 CommandLineRunner와 ApplicationRunner를 사용하면 프로젝트 초기화 후 실행할 코드를 작성할 수 있다는 공통점이 있는데, 이와 관련해서는 토비 님의 유튜브 영상인 스프링 부트 앱에 초기화 코드를 넣는 방법 3 가지를 시청하고 학습한 내용을 정리한 포스팅이 있어 이 포스팅도 같이 참고하면 좋을 것 같습니다.
Environment & PropertySource
Spring에서는 각 설정 정보를 가져오는 방법들이 달라 개발자는 설정 정보를 어디서 가져와야 하는지 확인한 후 그에 맞는 코드를 작성해야 하는 단점이 있었습니다.
Spring Boot는 이런 단점을 위 이미지와 같이 Environment와 PropertySource라는 추상화를 통해 해결했습니다.
PropertySource라는 추상 클래스를 두고, 각 설정 정보를 가져오는 XxxPropertySource라는 구현체를 만듦으로써 해결합니다.
그리고 개발자는 Environment를 통해서 설정 정보를 신경 쓰지 않고 environment.getProperty(key)를 통해 여러 설정 정보들을 같은 방식으로 조회할 수 있게 됩니다.
조금 더 자세한 내용은 토비 님의 인프런 강의 포스팅에서도 정리해 두었으니 참고하시면 좋을 것 같습니다.
SystemEnvironmentPropertySource.checkPropertyName(String name)
SystemEnvironmentPropertySource 객체를 사용하면 프로퍼티 값의 여부를 확인할 수 있습니다.
설명을 살펴보면 프로퍼티를 확인할 때 .(dot) 또는 _(under bar) 그리고 대/소문자 별로 다 확인해서 하나라도 일치하는 프로퍼티가 있을 경우 해당 프로퍼티가 있다고 판단한다고 합니다.
1. 먼저 전달된 name이 프로퍼티에 있는지 확인합니다.
2. 없을 경우 name에서 .(dot)을 _(unber bar)으로 변경한 후 프로퍼티가 있는지 확인합니다.
3. 없을 경우 name에서 -(hypen)을 _(unber bar)으로 변경한 후 프로퍼티가 있는지 확인합니다.
4. 없을 경우 .(dot)을 _(unber bar)로 바꿨던 noDotName에서 -(hypen)을 _(under bar)으로 변경한 후 프로퍼티가 있는지 확인합니다.
5. 이마저도 없을 경우 프로퍼티가 없다고 판단하여 null을 반환합니다.
@Profile 마다 다른 설정 파일 읽기
개발 환경과 실제 운영 환경에서는 각각 다른 설정 정보를 가져야 하는 경우가 있습니다. 하지만 매번 개발/운영 배포에 따라 설정 정보를 변경하고 빌드하고 배포하는 과정이 번거롭고 제대로 관리가 되지 않기 때문에, 프로필을 사용하여 개발/운영 환경에 따라 다른 설정 정보를 읽어올 수 있도록 할 수 있습니다.
// 방법 1 - 프로필별로 파일 생성
application-{profile}.properties
ex)
application-dev.properties
application-prod.properties
// 방법 2 - 하나의 파일 안에서 프로필별로 설정 정보 작성
application.properties
ex)
application.properties 파일 내부
#--- 또는 !--- 로 구분
spring.config.activate.on-profile=dev
url=dev.db.com
username=dev_user
password=dev_pw
#---
spring.config.activate.on-profile=prod
url=prod.db.com
username=prod_user
password=prod_pw
application.yml 파일 내부
--- 로 구분
my:
datasource:
url: local.db.com
username: local_user
password: local_pw
etc:
max-connection: 1
timeout: 60s
options: LOCAL, CACHE
---
spring:
config:
activate:
on-profile: dev
my:
datasource:
url: dev.db.com
username: dev_user
password: dev_pw
etc:
max-connection: 10
timeout: 60s
options: DEV, CACHE
---
spring:
config:
activate:
on-profile: prod
my:
datasource:
url: prod.db.com
username: prod_user
password: prod_pw
etc:
max-connection: 50
timeout: 10s
options: PROD, CACHE
하나의 파일 내부에서 프로필 별로 설정 정보를 관리하거나 프로필 별로 각각 다른 설정 정보 파일을 관리하는 것은 딱히 정해진 것은 없으므로 회사 내부 컨벤션이나 룰 또는 개개인의 취향에 따라 사용하시면 됩니다.
window system properties username 이슈
강의에서 system properties를 확인하던 도중 영한님 영상에서와 달리 username property만 다르게 출력되었습니다.
//application-dev.properties
url=dev.db.com
username=dev_user
password=dev_pw
//application-prod.properties
url=prod.db.com
username=prod_user
password=prod_pw
이유를 확인해 보니 아래와 같이 윈도우에 환경변수가 USERNAME이 등록이 되어 있었습니다.
시스템 환경 변수가 application.properties보다 우선순위가 높아서 발생한 이슈였으므로, USERNAME 대신 다른 이름으로 property를 설정하고 테스트하면 됩니다.
property 적용 우선순위는 아래와 같으며 토비 님의 인프런 강의 포스팅에서도 정리해 두었으니 참고하시면 좋을 것 같습니다.
'Lecture > 김영한 - 스프링 부트 - 핵심 원리와 활용' 카테고리의 다른 글
스프링 부트 - 핵심 원리와 활용 - 액츄에이터 (0) | 2023.03.12 |
---|---|
스프링 부트 - 핵심 원리와 활용 - 외부설정과 프로필2 (0) | 2023.03.12 |
스프링 부트 - 핵심 원리와 활용 - 자동 구성(Auto Configuration) (4) | 2023.03.12 |
스프링 부트 - 핵심 원리와 활용 - 스프링 부트 스타터와 라이브러리 관리 (0) | 2023.03.12 |
스프링 부트 - 핵심 원리와 활용 - 스프링 부트와 내장 톰캣 (0) | 2023.03.12 |
댓글