You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
이렇게 하면 System.getenv("DB_URL")로 조회 시 각각 환경에 따라서 서로 다른 값을 읽게 된다.
하지만 OS 환경 변수는 이 프로그램 뿐만 아니라 다른 프로그램에서도 사용할 수 있다. 쉽게 이야기해서 전역 변수 같은 효과가 있다. 여러 프로그램에서 사용하는 것이 맞을 때도 있지만, 해당 애플리케이션을 사용하는 자바 프로그램 안에서만 사용되는 외부 설정값을 사용하고 싶을 때도 있다. 다음에는 특정 자바 프로그램 안에서 사용하는 외부 설정을 알아보자.
${\textsf{\color{orange}1.3. 외부 설정 - 자바 시스템 속성}}$
자바 시스템 속성(Java System properties)은 실행한 JVM 안에서 접근 가능한 외부 설정이다. 추가로 자바가 내부에서 미리 설정해두고 사용하는 속성들도 있다.
자바 시스템 속성은 다음과 같이 자바 프로그램을 실행할 때 사용한다.
예) java -Durl=dev -jar app.jar
-D VM 옵션을 통해서 key=value 형식을 주면 된다. 이 예제는 url=dev 속성이 추가된다.
참고로 이 방식은 코드 안에서 사용하는 것이기 때문에 외부로 설정을 분리하는 효과는 없다.
${\textsf{\color{orange}1.4. 외부 설정 - 커맨드 라인 인수}}$
커맨드 라인 인수(Command line arguments)는 애플리케이션 실행 시점에 외부 설정값을 main(args) 메서드의 args 파라미터로 전달하는 방법이다.
다음과 같이 사용한다.
예) java -jar app.jar dataA dataB
필요한 데이터를 마지막 위치에 스페이스로 구분해서 전달하면 된다. 이 경우 dataA, dataB 2개의 문자가 args에 전달된다.
CommandLineV1 - src/test 하위
/** * CommandLine 인수는 스페이스로 구분 * java -jar app.jar dataA dataB -> [dataA, dataB] 2개 * java -jar app.jar url=devdb -> [url=devdb] 1개 * url=devdb 이라는 단어를 개발자가 직접 파싱해야 함 **/@Slf4jpublicclassCommandLineV1 {
publicstaticvoidmain(String[] args) {
for (Stringarg : args) {
log.info("arg {}", arg);
}
}
}
IDE에서 실행시 커맨드 라인 인수 추가
여기에 dataA dataB 를 입력하고 실행하자.
커맨드 라인 인수는 공백(space)으로 구분한다.
참고
빨간색으로 칠한 Program arguments가 보이지 않는다면 바로 위에 있는 파란색 Modify options버튼을 눌러서 추가할 수 있다.
실행 결과
Jar 실행
jar로 빌드되어 있다면 실행시 다음과 같이 커맨드 라인 인수를 추가할 수 있다.
key=value 형식 입력
애플리케이션을 개발할 때는 보통 key=value 형식으로 데이터를 받는 것이 편리하다.
이번에는 커맨드 라인 인수를 다음과 같이 입력하고 실행해보자.
실행 결과
실행 결과를 보면 알겠지만 커맨드 라인 인수는 key=value 형식이 아니다. 단순히 문자를 여러게 입력 받는 형식인 것이다. 그래서 3가지 문자가 입력되었다.
url=devdb
username=dev_user
password=dev_pw
이것은 파싱되지 않은, 통 문자이다.
이 경우 개발자가 =을 기준으로 직접 데이터를 파싱해서 key=value 형식에 맞도록 분리해야 한다. 그리고 형식이 배열이기 때문에 루프를 돌면서 원하는 데이터를 찾아야 하는 번거로움도 발생한다.
실제 애플리케이션을 개발할 때는 주로 key=value 형식을 자주 사용하기 때문에 결국 파싱해서 Map 같은 형식으로 변환하도록 직접 개발해야 하는 번거로움이 있다.
${\textsf{\color{orange}1.5. 외부 설정 - 커맨드 라인 옵션 인수}}$
일반적인 커맨드 라인 인수
커맨드 라인에 전달하는 값은 형식이 없고, 단순히 띄어쓰기로 구분한다.
aaa bbb → [aaa, bbb] 값 2개
hello world → [hello, world] 값 2개
"hello world" → [hello world] (공백을 연결하려면 "를 사용하면 된다.) 값 1개
key=value → [key=value] 값 1개
커맨드 라인 옵션 인수(command line option arguments)
커맨드 라인 인수를 key=value 형식으로 구분하는 방법이 필요하다. 그래서 스프링에서는 커맨드 라인 인수를 key=value 형식으로 편리하게 사용할 수 있도록 스프링 만의 표준 방식을 정의했는데, 그것이 바로 커맨드 라인 옵션 인수이다.
스프링은 커맨드 라인에 -(dash) 2개(--)를 연결해서 시작하면 key=value 형식으로 정하고 이것을 커맨드 라인 옵션 인수라 한다.
--key=value 형식으로 사용한다.
--username=userA --username=userB 하나의 키에 여러 값도 지정할 수 있다.
스프링이 제공하는 ApplicationArguments 인터페이스와 DefaultApplicationArguments 구현체를 사용하면 커맨드 라인 옵션 인수를 규격대로 파싱해서 편리하게 사용할 수 있다.
실행
커맨드 라인 인수를 다음과 같이 입력하고 실행해보자
이해를 돕기 위해 --(dash)가 없는 mode=on이라는 옵션도 마지막에 추가했다.
${\textsf{\color{orange}1.6. 외부 설정 - 커맨드 라인 옵션 인수와 스프링 부트}}$
스프링 부트는 커맨드 라인을 포함해서 커맨드 라인 옵션 인수를 활용할 수 있는 ApplicationArguments를 스프링 빈으로 등록해둔다. 그리고 그 안에 입력한 커맨드 라인을 저장해둔다. 그래서 해당 빈을 주입 받으면 커맨드 라인으로 입력한 값을 어디서든 사용할 수 있다.
지금까지 살펴본, 커맨드 라인 옵션 인수, 자바 시스템 속성, OS 환경변수는 모두 외부 설정을 key=value 형식으로 사용할 수 있는 방법이다. 그런데 이 외부 설정값을 읽어서 사용하는 개발자 입장에서 단순하게 생각해보면, 모두 key=value 형식이고, 설정값을 외부로 뽑아둔 것이다. 그런데 어디에 있는 외부 설정값을 읽어야 하는지에 따라서 각각 읽는 방법이 다르다는 단점이 있다.
예를 들어서 OS 환경 변수에 두면 System.getenv(key) 를 사용해야 하고, 자바 시스템 속성을 사용하면 System.getProperty(key)를 사용해야 한다. 만약 OS에 환경 변수를 두었는데, 이후에 정책이 변경되어서 자바 시스템 속성에 환경 변수를 두기로 했다고 가정해보자. 그러면 해당 코드들을 모두 변경해야 한다.
외부 설정값이 어디에 위치하든 상관없이 일관성 있고, 편리하게 key=value 형식의 외부 설정값을 읽을 수 있으면 사용하는 개발자 입장에서 더 편리하고 또 외부 설정값을 설정하는 방법도 더 유연해질 수 있다. 예를 들어서 외부 설정 값을 OS 환경변수를 사용하다가 자바 시스템 속성으로 변경하는 경우에 소스코드를 다시 빌드하지 않고 그대로 사용할 수 있다.
스프링은 이 문제를 Environment와 PropertySource라는 추상화를 통해서 해결한다.
스프링의 외부 설정 통합
PropertySource
org.springframework.core.env.PropertySource
스프링은 PropertySource라는 추상 클래스를 제공하고, 각각의 외부 설정를 조회하는 XxxPropertySource 구현체를 만들어두었다.
ex)
CommandLinePropertySource
SystemEnvironmentPropertySource
스프링은 로딩 시점에 필요한 PropertySource들을 생성하고, Environment에서 사용할 수 있게 연결해둔다.
Environment
org.springframework.core.env.Environment
Environment 를 통해서 특정 외부 설정에 종속되지 않고, 일관성 있게 key=value 형식의 외부 설정에 접근할 수 있다.
environment.getProperty(key)를 통해서 값을 조회할 수 있다.
Environment는 내부에서 여러 과정을 거쳐서 PropertySource들에 접근한다.
같은 값이 있을 경우를 대비해서 스프링은 미리 우선순위를 정해두었다. (뒤에서 설명한다.)
모든 외부 설정은 이제 Environment 를 통해서 조회하면 된다.
설정 데이터(파일)
여기에 우리가 잘 아는 application.properties, application.yml도 PropertySource에 추가된다.
따라서, Environment를 통해서 접근할 수 있다.
커맨드 라인 옵션 인수, 자바 시스템 속성 모두 Environment를 통해서 동일한 방법으로 읽을 수 있는 것을 확인했다. 스프링은 Environment를 통해서 외부 설정을 읽는 방법을 추상화했다. 덕분에 자바 시스템 속성을 사용하다가 만약 커맨드 라인 옵션 인수를 사용하도록 읽는 방법이 변경되어도, 개발 소스 코드는 전혀 변경하지 않아도 된다.
우선순위
예를 들어서 커맨드 라인 옵션 인수와 자바 시스템 속성을 다음과 같이 중복해서 설정하면 어떻게 될까?
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
OS 환경 변수(OS environment variables)는 해당 OS를 사용하는 모든 프로그램에서 읽을 수 있는 설정값이다. 한마디로 다른 외부 설정과 비교해서 사용 범위가 가장 넓다.
조회 방법
setprintenvset 실행 결과
현재 OS에 설정된 OS 환경 변수 값들을 출력했다.
설정 방법: OS 환경 변수의 값을 설정하는 방법은 윈도우 환경 변수, MAC 환경 변수 등으로 검색해보자. 수 많은 예시를 확인할 수 있다.
애플리케이션에서 OS 환경 변수의 값을 읽어보자.
OsEnv- src/test 하위System.getenv()를 사용하면 전체 OS 환경 변수를Map으로 조회할 수 있다.System.getenv(key)를 사용하면 특정 OS 환경 변수의 값을String으로 조회할 수 있다.실행 결과
OS 환경 변수를 설정하고, 필요한 곳에서
System.getenv()를 사용하면 외부 설정을 사용할 수 있다. 이제 데이터베이스 접근 URL과 같은 정보를 OS 환경 변수에 설정해두고 읽어들이면 된다.System.getenv("DB_URL")로 조회 시 각각 환경에 따라서 서로 다른 값을 읽게 된다.하지만 OS 환경 변수는 이 프로그램 뿐만 아니라 다른 프로그램에서도 사용할 수 있다. 쉽게 이야기해서 전역 변수 같은 효과가 있다. 여러 프로그램에서 사용하는 것이 맞을 때도 있지만, 해당 애플리케이션을 사용하는 자바 프로그램 안에서만 사용되는 외부 설정값을 사용하고 싶을 때도 있다. 다음에는 특정 자바 프로그램 안에서 사용하는 외부 설정을 알아보자.
자바 시스템 속성(Java System properties)은 실행한 JVM 안에서 접근 가능한 외부 설정이다. 추가로 자바가 내부에서 미리 설정해두고 사용하는 속성들도 있다.
자바 시스템 속성은 다음과 같이 자바 프로그램을 실행할 때 사용한다.
java -Durl=dev -jar app.jar-DVM 옵션을 통해서key=value형식을 주면 된다. 이 예제는url=dev속성이 추가된다.-D옵션이-jar보다 앞에 있다.JavaSystemProperties - src/test 하위
System.getProperties()를 사용하면Map과 유사한(Map의 자식 타입)key=value형식의Properties를 받을 수 있다. 이것을 통해서 모든 자바 시스템 속성을 조회할 수 있다.System.getProperty(key)를 사용하면 속성값을 조회할 수 있다.실행 결과
때 이런 속성들을 사용하는데, 예를 들어서 file.encoding=UTF-8를 통해서 기본적인 파일 인코딩 정보 등으로 사용한다.
이번에는 사용자가 직접 정의하는 자바 시스템 속성을 추가해보자.
url, username, password 를 조회하는 코드를 추가하자
JavaSystemProperties - 추가
IDE에서 실행시 VM 옵션 추가
-Durl=devdb -Dusername=dev_user -Dpassword=dev_pw추가실행 결과
-D옵션을 통해 추가한 자바 시스템 속성들을 확인할 수 있다.Jar 실행
jar로 빌드되어 있다면 실행시 다음과 같이 자바 시스템 속성을 추가할 수 있다.자바 시스템 속성을 자바 코드로 설정하기
자바 시스템 속성은 앞서 본 것 처럼
-D옵션을 통해 실행 시점에 전달하는 것도 가능하고, 다음과 같이 자바 코드 내부에서 추가하는 것도 가능하다. 코드에서 추가하면 이후에 조회시에 값을 조회할 수 있다.System.setProperty(propertyName, "propertyValue")System.getProperty(propertyName)참고로 이 방식은 코드 안에서 사용하는 것이기 때문에 외부로 설정을 분리하는 효과는 없다.
커맨드 라인 인수(Command line arguments)는 애플리케이션 실행 시점에 외부 설정값을
main(args)메서드의args파라미터로 전달하는 방법이다.다음과 같이 사용한다.
java -jar app.jar dataA dataBdataA,dataB2개의 문자가args에 전달된다.CommandLineV1 - src/test 하위
IDE에서 실행시 커맨드 라인 인수 추가
dataA dataB를 입력하고 실행하자.실행 결과
Jar 실행
jar로 빌드되어 있다면 실행시 다음과 같이 커맨드 라인 인수를 추가할 수 있다.key=value 형식 입력
애플리케이션을 개발할 때는 보통
key=value형식으로 데이터를 받는 것이 편리하다.이번에는 커맨드 라인 인수를 다음과 같이 입력하고 실행해보자.
실행 결과
실행 결과를 보면 알겠지만 커맨드 라인 인수는
key=value형식이 아니다. 단순히 문자를 여러게 입력 받는 형식인 것이다. 그래서 3가지 문자가 입력되었다.url=devdbusername=dev_userpassword=dev_pw이것은 파싱되지 않은, 통 문자이다.
이 경우 개발자가
=을 기준으로 직접 데이터를 파싱해서key=value형식에 맞도록 분리해야 한다. 그리고 형식이 배열이기 때문에 루프를 돌면서 원하는 데이터를 찾아야 하는 번거로움도 발생한다.실제 애플리케이션을 개발할 때는 주로
key=value형식을 자주 사용하기 때문에 결국 파싱해서Map같은 형식으로 변환하도록 직접 개발해야 하는 번거로움이 있다.일반적인 커맨드 라인 인수
커맨드 라인에 전달하는 값은 형식이 없고, 단순히 띄어쓰기로 구분한다.
aaa bbb→[aaa, bbb]값 2개hello world→[hello, world]값 2개"hello world"→[hello world](공백을 연결하려면"를 사용하면 된다.) 값 1개key=value→[key=value]값 1개커맨드 라인 옵션 인수(command line option arguments)
커맨드 라인 인수를
key=value형식으로 구분하는 방법이 필요하다. 그래서 스프링에서는 커맨드 라인 인수를key=value형식으로 편리하게 사용할 수 있도록 스프링 만의 표준 방식을 정의했는데, 그것이 바로 커맨드 라인 옵션 인수이다.스프링은 커맨드 라인에
-(dash) 2개(--)를 연결해서 시작하면key=value형식으로 정하고 이것을 커맨드 라인 옵션 인수라 한다.--key=value형식으로 사용한다.--username=userA --username=userB하나의 키에 여러 값도 지정할 수 있다.스프링이 제공하는
ApplicationArguments인터페이스와DefaultApplicationArguments구현체를 사용하면 커맨드 라인 옵션 인수를 규격대로 파싱해서 편리하게 사용할 수 있다.실행
커맨드 라인 인수를 다음과 같이 입력하고 실행해보자
이해를 돕기 위해
--(dash)가 없는mode=on이라는 옵션도 마지막에 추가했다.스프링 부트는 커맨드 라인을 포함해서 커맨드 라인 옵션 인수를 활용할 수 있는
ApplicationArguments를 스프링 빈으로 등록해둔다. 그리고 그 안에 입력한 커맨드 라인을 저장해둔다. 그래서 해당 빈을 주입 받으면 커맨드 라인으로 입력한 값을 어디서든 사용할 수 있다.CommandLineBean- src/main 하위실행
커맨드 라인 인수를 다음과 같이 입력하고 실행해보자
다음을 실행한다.
ExternalApplication.main()실행 결과
실행 결과를 보면, 입력한 커맨드 라인 인수, 커맨드 라인 옵션 인수를 확인할 수 있다.
지금까지 살펴본, 커맨드 라인 옵션 인수, 자바 시스템 속성, OS 환경변수는 모두 외부 설정을
key=value형식으로 사용할 수 있는 방법이다. 그런데 이 외부 설정값을 읽어서 사용하는 개발자 입장에서 단순하게 생각해보면, 모두key=value형식이고, 설정값을 외부로 뽑아둔 것이다. 그런데 어디에 있는 외부 설정값을 읽어야 하는지에 따라서 각각 읽는 방법이 다르다는 단점이 있다.예를 들어서 OS 환경 변수에 두면 System.getenv(key) 를 사용해야 하고, 자바 시스템 속성을 사용하면 System.getProperty(key)를 사용해야 한다. 만약 OS에 환경 변수를 두었는데, 이후에 정책이 변경되어서 자바 시스템 속성에 환경 변수를 두기로 했다고 가정해보자. 그러면 해당 코드들을 모두 변경해야 한다.
외부 설정값이 어디에 위치하든 상관없이 일관성 있고, 편리하게
key=value형식의 외부 설정값을 읽을 수 있으면 사용하는 개발자 입장에서 더 편리하고 또 외부 설정값을 설정하는 방법도 더 유연해질 수 있다. 예를 들어서 외부 설정 값을 OS 환경변수를 사용하다가 자바 시스템 속성으로 변경하는 경우에 소스코드를 다시 빌드하지 않고 그대로 사용할 수 있다.스프링은 이 문제를
Environment와PropertySource라는 추상화를 통해서 해결한다.스프링의 외부 설정 통합
PropertySource
org.springframework.core.env.PropertySourcePropertySource라는 추상 클래스를 제공하고, 각각의 외부 설정를 조회하는XxxPropertySource구현체를 만들어두었다.CommandLinePropertySourceSystemEnvironmentPropertySourcePropertySource들을 생성하고,Environment에서 사용할 수 있게 연결해둔다.Environment
org.springframework.core.env.EnvironmentEnvironment를 통해서 특정 외부 설정에 종속되지 않고, 일관성 있게key=value형식의 외부 설정에 접근할 수 있다.environment.getProperty(key)를 통해서 값을 조회할 수 있다.Environment는 내부에서 여러 과정을 거쳐서PropertySource들에 접근한다.Environment를 통해서 조회하면 된다.설정 데이터(파일)
여기에 우리가 잘 아는
application.properties,application.yml도PropertySource에 추가된다.따라서,
Environment를 통해서 접근할 수 있다.--url=devdb --username=dev_user --password=dev_pw-Durl=devdb -Dusername=dev_user -Dpassword=dev_pwExternalApplication.main을 실행하자.실행 결과
정리
커맨드 라인 옵션 인수, 자바 시스템 속성 모두 Environment를 통해서 동일한 방법으로 읽을 수 있는 것을 확인했다. 스프링은 Environment를 통해서 외부 설정을 읽는 방법을 추상화했다. 덕분에 자바 시스템 속성을 사용하다가 만약 커맨드 라인 옵션 인수를 사용하도록 읽는 방법이 변경되어도, 개발 소스 코드는 전혀 변경하지 않아도 된다.
우선순위
예를 들어서 커맨드 라인 옵션 인수와 자바 시스템 속성을 다음과 같이 중복해서 설정하면 어떻게 될까?
--url=proddb --username=prod_user --password=prod_pw-Durl=devdb -Dusername=dev_user -Dpassword=dev_pw우선순위는 상식 선에서 딱 2가지만 기억하면 된다.
속성이 더 우선권을 가진다.)
다. 반면에 커맨드 라인 옵션 인수는
main의 arg를 통해서 들어오기 때문에 접근 범위가 더 좁다.)자바 시스템 속성과 커맨드 라인 옵션 인수의 경우 커맨드 라인 옵션 인수의 범위가 더 좁기 때문에 커맨드 라인 옵션 인수가 우선권을 가진다.
우선순위는 뒤에서 더 자세히 다루겠다.
Beta Was this translation helpful? Give feedback.
All reactions