@Value 애너테이션의 기능과 사용법

현주·2023년 5월 16일
0

프로젝트에서 application.yml 파일의 값을 읽어올 수 있도록 @Value 애너테이션을 사용하였다.

아래는 예시로 프로젝트에서 toss payments를 이용하기 위해 적었던 코드이다.

📌 TossPayments 연동에 대한 자세한 내용은 아래 포스팅을 참고해주세요.
<💳 토스페이먼츠 연동하기 (1) _결제 흐름>

  • application.yml

  • TossPaymentConfig

appliaction.yml 파일에 설정 값들을 적어두고,

TossPaymentConfig에서 @Value 애너테이션으로 해당 설정 값을 가져오는 것을 볼 수 있다.

이렇게 설정 값을 분리해두고 필요할 때마다 설정 값을 직접 적는 것이 아닌,

@Value 애너테이션으로 불러오는 것이 좋다.


✔ 설정 값 분리의 필요성

개발을 진행하다 보면 데이터베이스 연결 정보나 외부 API 주소 등과 같은 메타 정보들을 관리해야 하는데,

해당 메타정보들을 클래스 파일에 직접 넣을 수도 있지만,

아래와 같은 이유로 properties 파일이나 yaml, yml 파일로 분리해서 관리할 것이 권장된다.

1. 환경에 따라 유연하게 값을 설정할 수 있음

➜ 일반적으로 로컬 환경이나 알파/스테이지 환경 그리고 운영 환경에 따라 서로 다른 데이터베이스 서버를 가지고 있음
만약 환경에 따라 다른 값을 자바 코드만으로 설정해주려면 상당히 번거롭고 중복되는 코드가 상당히 많아지기 때문에
설정값은 별도의 파일(properties 또는 yaml/yml)로 분리하고, 자바 코드에서는 환경 정보에 맞는 설정값을 불러오도록 하는 것이 유용

2. 초기값을 설정할 수 있음

➜ 이를 통해 설정한 값이 불러지지 않은 경우에 대비가 가능하고 테스트 작성을 용이하게 할 수 있음
( 테스트 작성에 유연하고 안전하게 개발 가능 )

3. 불필요한 컴파일을 줄일 수 있음

➜ 만약 프로퍼티를 분리하지 않는다면 클래스들 안에 설정 값을 직접 작성되어 있을 것임
이 경우, 값이 수정된다면 소스코드가 변하는 것이므로 다시 컴파일을 해주어야 함

➜ 설정 파일을 분리하고 @Value로 참조하게 한다면, 불필요한 컴파일없이 주입되는 값을 변경 가능


✏️ @Value 애너테이션

  • properties 또는 yaml, yml 파일의 설정 값을 가져오기 위한 애너테이션

✔ 사용법

1. PropertyPlaceHolderConfigurer를 통한 수동 변환

  • ${} 안에 설정 파일에 작성된 설정 값을 넣어주면,
    Spring이 PropertyPlaceHolderConfigurer를 통해 초기화 작업 중에 해당 값을 실제 값으로 치환하는 방법

  • 오타가 있으면 에러 검증이 불가능

Ex. 아래와 같이 작성한다면,
application.yml파일에서 payment.toss.success_url 변수의 실제 값을 찾아 치환함

✔️ PropertyPlaceHolderConfigurer

  • 빈 팩토리 후처리기
  • 매번 빈 오브젝트가 만들어진 직후에 오브젝트의 내용이나 오브젝트 자체를 변경하는 빈 후처리기와 달리
    빈 설정 메타정보가 모두 준비됐을 때 빈 메타정보 자체를 조작하기 위해 사용

But, 이 방법의 경우는

대체할 위치를 치환자로 지정해두고, 별도의 후처리기가 값을 변경해주기를 기대하기 때문에 수동적

그래서 초기 메타정보에는 ${payment.toss.success_url}와 같은 문자열이 등록되어있고,

그러다가 Spring 컨테이너가 설정 파일에서 대체할 적절한 키값을 찾지 못하면 해당 문자열이 그대로 남아있게 됨

그래서 치환자의 값이 변경되지 않더라도 예외가 발생하지 않으므로 SpEL을 통한 능동 변환을 권장한다고 함

물론 Spring의 버전이 높아지면서 이러한 문제를 개선한 PropertyPlaceHolderConfigurer가 등장하고
적절한 값을 찾지 못하면 에러가 발생하도록 수정되었지만,

❗ 그래도 수동적인 방법보다는 빈에서 값을 꺼내는 SpEL이 권장된다고 함


2. SpEL을 통한 능동 변환

  • #{} 안에 다른 빈 오브젝트에 직접 접근할 수 있는 표현식을 넣어 원하는 설정 값을 능동적으로 가져오는 방법

  • 설정 값의 대체 위치를 설정해두고 빈 팩토리 후처리기가 바꿔주기를 기다리는 수동적 방법과 달리,
    다른 빈 오브젝트에 직접 접근할 수 있는 표현식을 이용해 원하는 설정 값을 능동적으로 가져옴

  • 1번의 수동적 방법과 달리, 오타가 있어도 에러 검증이 가능

Ex. 아래와 같이 작성한다면,
environment라는 이름의 빈으로부터 해당 키에 해당하는 값을 직접 읽어오게 됨

@Value("#{environment['payment.toss.success_url']}")
private String successUrl;

✔️ SpEL (Spring Expression Language)

  • Spring 3.0에서 처음 소개된 Spring 전용 표현식 언어
  • 이를 통해 다른 빈 오브젝트나 프로퍼티에 손쉽게 접근 가능
  • 일반 프로그래밍 언어 수전에 가까운 강력한 표현식 기능을 지원
    ➜ 다른 빈의 프로퍼티에 접근 가능할 뿐만 아니라 메소드 호출도 가능하고 다양한 연산도 지원하며 클래스 정보에도 접근 가능, 심지어 생성자를 호출해서 객체를 생성할 수도 있음

✔️ 오타를 포함한 수동 변환 vs 능동 변환

1. PropertyPlaceHolderConfigurer를 통한 수동 변환

@Value("${jwt.secret}")
private String secret;

위의 정보를 작성하려고 할 때,

@Value("${jwt.secrett}") // 오타
private String secret;

위와 같이 오타가 난다면 해당 값을 찾지 못해 치환 불가

2. SpEL을 통한 능동 변환

@Value("#{environment['jwt.secrett'] == null " + 
					"? '기본 시크릿 정보'" +
					": environment['jwt.secrett']}")
private String secret;

위와 같이 작성한다면, 만약 설정 파일에서 해당 내용을 찾지 못해도

기본 시크릿 정보는 찾을 수 있기에 에러에서 더 안전하고 테스트에 용이

💬 도움이 된 사이트

0개의 댓글