1. 외부설정이란

    1. 애플리케이션이 작동하기 위해 참조하는 변수
    2. 예시로 개발, 운영 환경에서 DB URL을 다르게 가져가는 경우 참조하는 파일을 외부설정파일이라고 칭함
  2. 이전의 외부설정 방식

    Untitled

    1. 위 예제는 외부설정을 다르게 가져가야 하는 경우, 내부 코드를 수정하고 빌드를 수행하는 방식
    2. 위 예제에서는 개발용 DB URL은 dev.db.com, **운영용 DB URL은 prod.db.com**으로 관리하는 경우임
    3. 하지만 위 예제는 좋은 방식이 아님
  3. 개선된 외부설정 방식

    Untitled

    1. 이전 외부설정 방식의 단점
      1. 이전의 외부설정 방식은 환경에 따라 빌드를 다르게 하기 때문에 각각 운영에 대해 보장 불가능
      2. 특정 용도로 빌드된 파일은 해당 환경에서만 사용가능하므로 유연성이 떨어짐
    2. 위와 같은 이유로 이미지처럼 빌드는 같은 설정을 하지않은 코드에 대해 실행하고 참조할 수 있는 외부설정 파일을 각각 용도에 맞게 작성하는 방식으로 사용
  4. 외부설정의 일반적인 방법

    1. OS 환경 변수
      1. OS에서 지원하는 외부 설정
      2. 해당 OS를 사용하는 모든 프로세스에서 사용
      3. 예시로 JAVA_HOME 등의 변수
    2. 자바 시스템 속성
      1. 자바에서 지원하는 외부 설정
      2. 해당 JVM에서 참조 가능(다른 애플리케이션이라도 같은 JVM에서 사용하면 참조가 가능함)
      3. 예시로 인텔리제이에서 VM옵션에서 입력 가능
      4. -Dusername=chobolevel
    3. 자바 커맨드 라인 인수
      1. 커맨드 라인에서 전달하는 외부 설정
      2. 애플리케이션 실행시 main() 메서드의 args 파라미터를 통해 받을 수 있음
      3. 인텔리제에서는 프로그램 인수를 통해 입력 가능
      4. --username=chobolevel
    4. 외부 파일(설정 데이터)
      1. 애플리케이션에서 외부 파일을 직접 읽어서 사용(application.properties, application.yml 등)
      2. 애플리케이션에서 특정 위치의 파일을 읽도록 설정(예: data/hello.txt)
      3. 그리고 각 서버마다 해당 파일안에 다른 설정 정보를 남겨둠
        1. 개발 서버 hello.txt: url=dev.db.com
        2. 운영 서버 hello.txt: url=prod.db.com
  5. OS 환경 변수

    1. 모든 애플리케이션에서 조회 가능한 변수

    2. 다른 외부설정에 비해 사용 범위가 가장 넓음

    3. 윈도우에서는 set 명령어로 조회 가능(cmd) → 예) set JAVA_HOME

    4. 자바 애플리케이션에서의 조회

      Untitled

      1. System.getenv() 통해 Map형식으로 조회가 가능함
      2. System.getenv() 메서드에 String 형식으로 특정 key값을 넘겨주면 특정 환경변수 조회 가능
  6. 자바 시스템 속성

    1. 실행된 JVM에서 접근 가능한 외부 설정

    2. 추가적으로 자바가 미리 설정해두고 사용하는 변수도 존재함

    3. 자바 시스템 속성 지정 방법

      1. java -Durl=dev -jar app.jar
      2. -D 옵션을 통해서 key=value 형식으로 사용, 예제는 url=dev를 지정
      3. 위 예제처럼 -jar 보다 앞에서 명령어를 입력해야함
      4. 인텔리제이에서는 VM옵션으로 지정 가능
    4. 자바 애플리케이션에서의 조회

      Untitled

      1. **System.getProperties()**를 통해 Map 형식으로 조회
      2. key는 Object형식으로 조회가 이루어짐
      3. **getProperty()**메서드에 String 형태로 key값을 넘겨주면 조회 가능
  7. 커맨드 라인 인수

    1. 애플리케이션 실행 시점에 외부 설정값을 **main()**메서드의 args 파라미터로 전달하는 방식

    2. 커맨드 라인 인수 지정 방법

      1. java -jar app.jar dataA dataB
      2. 필요한 데이터를 마지막 위치에 공백으로 구분해서 전달
      3. 앞선 자바 시스템 속성과 달리 가장 뒤에 넘겨주는 것이 중요하며 key=value 형식으로는 전달되지 않음
      4. 인텔리제이에서는 프로그램 인수를 통해 전달 가능
      5. 띄어쓰기를 사용해야 하는 변수는 “”를 통해 묶어서 전달
    3. 자바 애플리케이션에서의 조회

      String 배열의 args 파라미터를 조회 가능

      String 배열의 args 파라미터를 조회 가능

  8. 커맨드 라인 옵션 인수

    1. 앞선 커맨드 라인 인수가 key=value형식으로 조회/등록 되지 않는 단점을 극복한 외부설정 방식

    2. 커맨드 라인 옵션 인수 지정 방법

      1. -(dash)를 2개 연결하고 key=value형식으로 전달
      2. 같은 key에 여러개 전달 가능
      3. java -jar app.jar --username=chobolevel --username=chobo
    3. 자바 애플리케이션에서의 조회

      Untitled

      1. 자바에서 제공하는 ApplicationArguments 인터페이스를 구현한 DefaultApplicationArguments를 통해 조회 가능
      2. 해당 객체는 빈으로 등록되어 있기 때문에 ApplicationArguments타입으로 빈을 주입받아 사용 가능
      3. **getOptionNames()**를 통해 외부설정 key값을 set형태로 조회
      4. **getOptionValues()**를 톻해 String 타입 key를 전달하면 List형태로 조회
      5. List형식으로 조회되는 이유는 같은 key에 여러값 지정 가능
  9. 외부 설정 통합

    Untitled

    1. 스프링에서는 앞선 다양한 외부 설정을 지원하지만 각각 다른 방식으로 조회하는 불편함이 존재

    2. 스프링에서는 이를 위해 PropertySource라는 추상 클래스를 제공하고 각 외부설정에 따라 xxxPropertySource 구현체를 만들어둠

    3. 이러한 구현체를 Environment에서 사용할 수 있게 연결해둠

    4. Environment

      Untitled

      1. 외부 설정에 따라 조회방식을 다르게 하지 않고 key=value 형식으로 조회 가능함
      2. **getProperty(key)**를 통해 조회 가능
      3. 내부적으로는 여러 과정을 거쳐 xxxPropertySource 들에 접근
      4. 우리가 잘 아는 application.properties, yml 등도 접근 가능
  10. 외부 설정 파일

    Untitled

    1. 앞선 OS 환경 변수, 자바 시스템 속성 등은 사용하는 값이 늘어나면 사용하기 불편해짐
    2. 이에 대한 대안은 파일을 따로 작성하여 관리하여 로딩시점에 해당 파일을 읽도록 함 대표적으로 application.properties 파일이 있음
    3. 스프링 부트에서는 외부의 application.properties를 읽기 위해서는 해당 jar파일이 있는 경로에 함께 있으면 추가적인 작업없이 읽기 가능
  11. 내부 설정 파일

    Untitled

    1. 설정 파일을 외부에서 관리하면 각 빌드파일과 함께 설정 파일을 관리해야 하기 때문에 번거로운 작업이 많아짐
    2. 이를 해결하기 위해 프로젝트 내부에서 관리하는 방법이 있음(jar 파일안에 설정 파일을 포함하는 방식)
    3. 위 예제에서는 개발용 설정 파일, 운영용 설정 파일을 모두 프로젝트에 포함하여 빌드하는 방법
    4. 설정하는 프로필에 따라 개발용/운영용 설정 파일의 내용이 적용됨
  12. 프로필

    1. spring.profiles.active 외부설정에 넣으면 해당 프로필에는 해당 설정을 사용한다고 판단(OS변수, 자바 시스템 속성, 커맨드 라인 인수 등으로 설정 가능)
    2. 설정된 프로필에 따라 application-{profile}.properties 형식으로 저장된 파일중 일치하는 프로필의 설정 파일을 읽도록 함
    3. spring.profiles.active=dev dev라는 프로필 활성으로 application-dev.properties 파일을 읽어들임
  13. 내부 설정 파일 병합

    Untitled

    1. 각 프로필별로 파일을 따로 관리하게 되면 한눈에 관리하기 힘든 단점이 있음
    2. 이를 보완하기 위해 스프링에서는 물리적인 하나의 파일에서 논리적으로 구분하는 방법을 제공함
    3. properties파일의 경우 **#---, !---**를 통해 구분하고 yml파일의 경우 **---**로 구분
    4. 활성화 프로필은 **spring.config.activate.on-profile**변수를 통해 구분
    5. 🚨주의🚨할 점은 논리적으로 구분하는 부분의 앞뒤로는 주석을 적으면 안되며 공백도 주의해야함
    6. 따로 프로필을 지정하지 않는 경우 **spring.config.activate.on-profile**을 지정하지 않은 설정을 기본값으로 인식함
    7. 만약 모든 설정이 profile을 가지고 있고 실행 환경에서 프로필을 설정하지 않는다면 설정 변수는 모두 null을 표시
    8. 기본적으로 위에서 아래로 파일을 읽기 때문에 예제에서 **url**을 조회하면 마지막에 작성한 hello.db.com이 조회됨
  14. 전체 설정 파일의 우선순위

    1. 자주 사용하는 우선순위
      1. 설정 데이터(application.properties, yml)
      2. OS 환경 변수
      3. 자바 시스템 속성
      4. 커맨드 라인 옵션 인수
      5. @TestPropertySource(테스트에서 사용)
    2. 설정 데이터 우선 순위
    3. 우선순위 이해 방법