스프링 핵심 기술-05.Environment 프로파일/프로퍼티


IoC 컨테이너 6부 : Environment 1부.프로파일

ApplicationContext는 빈팩토리의 기능만 하는 것은 아닙니다.

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
..
}

많은 클래스들을 상속받고 있는 걸 볼 수 있는데, 가진 기능들을 좀 더 구체적으로 정리할 예정입니다.

가장 먼저 Environment 부터 살펴보자.

  • EnvironmentCapable 이 제공하는 기능은 크게 2가지
    1. 프로파일 기능
    2. 프로퍼티
  • 프로파일과 프로퍼티를 다루는 인터페이스.
    • ApplicationContext extends EnvironmentCapable
    • getEnvironment()
  • 프로파일
    • 빈들의 그룹
    • Environment의 역할은 활성화할 프로파일 확인 및 설정
  • 프로파일 유즈케이스
    • 테스트 환경에서는 A라는 빈을 사용하고, 배포 환경에서는 B라는 빈을 쓰고 싶다.
    • 이 빈은 모니터링 용도니까 테스트할 때는 필요가 없고 배포할 때만 등록이 되면 좋겠다.

프로파일은..
우리가 많이 사용해 보았던 메이븐에도 프로파일 기능이 있고, 스프링 프로파일도 마찬가지이다.

@Environment
환경이란,
테스트 환경에서는 이런 빈들을 쓰고
배포 환경에서는 이런 빈들을 쓰겠다. 라고 설정하는 것이다.

특정한 환경에서는 이런 빈들을 등록해야 하는 경우 이런 요구사항들..(개발계, 운영계, 테스트계 등..)
ApplicationContext - EnvironmentCapable 인터페이스를 통해 사용이 가능하다.

프로파일(Profiles) 확인

@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    ApplicationContext ctx;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Environment environment = ctx.getEnvironment(); // EnvironmentCapable 
        System.out.println(Arrays.toString(environment.getActiveProfiles())); // 추가 설정 프로파일
        System.out.println(Arrays.toString(environment.getDefaultProfiles())); // 기본 디폴트 프로파일
    }
}

실행결과

[]
[default]

프로파일 정의하기

  1. 클래스에 정의
    • @Configuration @Profile(“test”)
    • @Component @Profile(“test”)
  2. 메소드에 정의
    • @Bean @Profile(“test”)

1.클래스에 정의

@Configuration 설정 클래스를 만들어서 설정

@Configuration
@Profile("test")
public class TestConfiguration {

    @Bean
    public TestRepository testRepository(){
        return new TestRepository();
    }
}

이렇게 설정 클래스 파일을 생성했는데.. 실행 결과는 에러가 발생한다.

Field testRepository in com.example.ioccontainer5.demo.AppRunner required a bean of type 'com.example.ioccontainer5.demo.TestRepository' that could not be found.

해당 프로파일이 없으면 찾을 수 없다고 에러가 발생한다.

이유가 뭐냐면, 아직 프로파일을 적용해 주지 않았기 때문이다.
test 프로파일을 적용해 주기 전까지는 TestRepository 빈을 찾을 수 없다.

인텔리제이 액티브 프로파일 설정에서 적용 프로파일을 지정해 줄 수 있다.

Active Profile

test 프로파일을 적용해 준 뒤에는 정상적으로 실행되는 걸 확인 가능하다.

@Component 개별 클래스에도 설정해 사용도 가능하다.

@Repository
@Profile("develope")
public class DevelopeRepository {

Active Profile2

추가로 이런 설정도 가능하다

@Repository @Profile(“!test”) public class DevelopeRepository { }

프로파일에 test가 없을 때에만 적용을 한다던가..

! : not
& : and
| : or

저렇게 실행하면 지금은 test, develope 프로파일이 둘 다 설정이 되어 있는 상태이니까, DevelopeRepository 은 사용하지 못한다.

이런 방식으로도 사용이 가능하고 클래스 뿐만 아니라 메서드에도 @Profile(“!develope”)를 붙여 활용 가능하다.
해당 메서드는 개발에서는 절대 돌면 안되는 메서드라던가..

프로파일을 설정하는 방법은 인텔리J를 활용해서 간단히 적용했지만,

yaml파일을 이용한다던가..

spring:
  profiles: test

application.properties를 파일을 이용해 설정도 가능하다.

application-{profile}.properties 형식

application-test.properties
application-develope.properties
application-prod.properties

IoC 컨테이너 6부 : Environment 2부.프로퍼티

EnvironmentCapable가 제공하는 두번째 기능이다.
Properties

  • 애플리케이션에 등록되는 프로퍼티(Key, value 쌍)에 접근할 수 있는 기능
  • 계층형으로 접근을 한다.

계층형이란? 우선순위가 있다는 말이다.
프로퍼티는(Key, value 쌍으로) 여러가지 소스, 여러가지 형태로 제공이 될 수 있는데..

  • OS에 있는 환경변수,
  • 자바 애플리케이션 실행할 때 넘겨주는 -d 옵션으로 넘겨주는 프로퍼티들
  • 서블릿 컨텍스트
  • 서블릿 컨피그 등 (서블릿 애플리케이션이라면 ) 등이 있다.

프로퍼티 사용법

그럼 프로퍼티를 어떻게 접근하고 사용하느냐?

properties value 내가 넘겨준 -d app.name 값

properties check 해당 코드로 확인되는 걸 볼 수 있다.

이런 방법 말고도 난 체계적으로 값을 전달하려고 한다면..

프로퍼티 파일을 만들고(resources)

app.about=jaeuk

값을 넣어놓은 다음

@SpringBootApplication
@PropertySource("classpath:/app.properties")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@PropertySource로 프로퍼티 파일을 읽고,

@Component
public class AppRunner implements ApplicationRunner {

    @Autowired
    ApplicationContext ctx;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        Environment environment = ctx.getEnvironment(); // EnvironmentCapable
        System.out.println(environment.getProperty("app.name")); // 프로퍼티 확인
        System.out.println(environment.getProperty("app.about")); // 직접 생성한 프로퍼티 파일 참조
    }
}

똑같이 사용이 가능하다.

추가적으로 스프링 부트에서는

@Value("${app.name}")
String appName;

이런 방식으로 더 간편하게 사용이 가능하다.
(사실 앞서 설명한 내용들을 기반으로 스프링 부트가 구현된 것)

그럼 프로퍼티를 가져오는 우선 순위는 어떻게 될까?
둘 다 똑같은 app.name이라는 key를 있다면 된다면?
두개 중에서는
vm 옵션으로 준 게 더 우선순위를 가진다.
= 내가 프로퍼티에 적어놓은 것이 아닌, vm옵션의 value를 가져온다.

  • StandardServletEnvironment의 우선순위
    • ServletConfig 매개변수
    • ServletContext 매개변수
    • JNDI (java:comp/env/)
    • JVM 시스템 프로퍼티 (-Dkey=”value”)
    • JVM 시스템 환경 변수 (운영 체제 환경 변수)

이 외에도 다양한 기능들은 추후 스프링부트 내용에서 더 자세히 정리 예정이다.




© 2019. by jaeuk