@Value 동작하지 않는 이유

DragonTiger·2023년 3월 21일
0

Issue

회사에서 암호화 관련 유틸을 만들고있던 과정에 발생한 일이다.

Aes256Utils 클래스를 리팩토링 하고있었다.

간단히 설명하자면,

  • AES는 고급 암호화 표준이며, 대칭키를 쓰는 블럭 암호이다.
  • 128비트 암호화 블록, 다양한 키의 길이 (128/192/256 비트)를 갖춘 대칭형 암호 알고리즘이다.
  • AES-128, AES-192, AES-256 (키의 길이 16byte, 24byte, 32byte)

본론으로 들어가서

아래 그림을 보면

나는 문제없이 동작할거라 예상했었지만 NPE가 발생하는것이였다.

생각해보니

@Value의 필드 주입시점을 잘 모르고 있었다.
@Value 어노테이션이 필드에 붙었다면
의존관계 주입 시점에 동작한다.

추측하건데 @Component 가 붙은 Aes256Utils 의 생성자 호출 시점은 스프링의 빈이 생성되는 시점일것이다.

참고로 스프링 빈의 생명주기는

  1. 스프링 컨테이너 생성
  2. 스프링 빈의 생성
  3. 의존관계 주입
  4. 초기화 콜백
  5. 사용
  6. 소멸전 콜백
  7. 스프링 종료

즉, 2번의 빈의 생성시점에 Aes256Utils 생성자가 호출되고 key 값은 null 이며,
2번이 지나간 후에야 key 값에 환경변수가 초기화된다.

그러므로 Aes256Utils 의 생성자에 key.getBytes() 는 null 이며 NPE 가 발생하는것이다.

Solution

자 빈의 생명주기로 인해 null 이 들어간다는걸 알았다.

해결법은 바로 코드로 알아보자

위의 코드로 리팩토링을 하였다.

자 그럼 위의 코드를 보면 생성자 매개변수에 @Value 어노테이션을 넣었다.

결론적으로

  1. Spring 이 빈 객체를 생성할 때 먼저 객체 생성에 사용할 생성자를 찾는다.
  2. 인수가 필요한 생성자가 발견되면 Spring은 컨테이너에서 해당 인수를 찾아 객체를 생성하기전에 주입한다.
  3. 생성자 매개변수 @Value 어노테이션이 달린 경우 Spring은 객체를 생성하기 전에 속성 파일에 지정된 값을 주입한다.

해서 빈생성시에 @Value 어노테이션의 값을 환경변수 값으로 초기화 할수있다.

정리하자면

@Value 필드 주입의 경우는 스프링 빈이 생성자로 빈 생성 후 의존관계 주입시에 필드값이 초기화가 되므로 스프링의 빈 생명주기로 인하여 null 값이 필연적으로 들어가게 된다.

스프링의 빈 생성자에서 환경변수의 값을 초기화 하려면 생성자 매개변수에 @Value 어노테이션을 붙이자.


End

profile
take the bull by the horns

0개의 댓글