Backend

lombok.Value vs org.springframework.beans.factory.annotation.Value

사과만쥬 2024. 7. 8. 10:00

내용 설명에 있어서 틀린 부분이 있을 수 있습니다.

 

김영한 스프링 MVC 2편 마지막 섹션인 파일 업로드 편을 듣던 중, 아래와 같은 오류가 발생했다.

 

해당 섹션은 파일 업로드를 직접 구현해보는 ServletUploadControllerV1.java, ServletUploadControllerV2.java 파일과 스프링에서 제공하는 기능들을 이용하는 SpringUploadController.java 파일로 구성되어 있다.

이전의 2가지 과정 중에서는 오류 없이 잘 넘어갔는데, 새로 작업하는 SpringUploadController.java 파일에서는 계속 file.dir을 가져오지 못하는 오류가 발생하였다.

 

원인을 보니 import 오류였다. 이전 파일에서는 오류가 전혀 나지 않았는데 새로운 파일에서만 오류가 떠서 이전 파일과 비교 후 import를 고쳐주었다.

 

위의 부분을 아래와 같이 변경해주니 오류가 해결되었다.

 

 

 

(org.springframework.beans.factory.annotation.Value를 아래부터는 간단하게 springframework.Value라고 칭하겠다.)

왼쪽이 lombok.Value이다.

 

 

두 Value를 분석하기 위해 위와 같이 코드를 비교해 보았다.

 

두 Value에서 가장 먼저 눈에 띄는 차이점은 @Documented의 유무였다.

@Documented는 lombok에서는 없었고 spring framework 에서는 존재했다.

검색을 해보니, 

 

javadoc으로 api 문서를 만들 때 어노테이션에 대한 설명도 포함하도록 지정해주는 것입니다. 

 

라고 한다. 이 설명만으로는 부족해서 공식 문서를 검색해보니

 

작은 초록색 글씨는 아래를 봐 주세요.

 

이런 설명이 나왔었다. 

 

If the annotation @Documented is present on the declaration of an annotation interface A, then any @A annotation on an element is considered part of the element's public contract. In more detail, when an annotation interface A is annotated with Documented, the presence and value of A annotations are a part of the public contract of the elements A annotates. Conversely, if an annotation interface B is not annotated with Documented, the presence and value of B annotations are not part of the public contract of the elements B annotates. Concretely, if an annotation interface is annotated with Documented, by default a tool like javadoc will display annotations of that interface in its output while annotations of annotation interfaces without Documented will not be displayed.

 

 

영어에 대해서 해석을 한다면, 

 

@Documented가 interface A에 대한 정의가 있다면, @A 주석은 요소의 공개 계약의 일부로 간주된다는 뜻이다. 

이와 반대로 Documented가 되지 않은 interface B의 경우, @B 주석은 요소의 공개 계약의 일부로 간주되지 않는다.

더 명확하게 이야기 한다면, B가 annotation을 보여주지 않는 것과 반대로 A의 경우 기본적으로 javadoc같은 도구가 interface의 annotation을 보여줄 것이다.

 

 

대략 이런 뜻인데, 좀 더 간결하게 정리하면

 

  • @Documented가 붙은 어노테이션은 문서화되며, 해당 어노테이션이 적용된 요소의 공개 계약의 일부로 간주된다.
  • @Documented가 붙지 않은 어노테이션은 문서화되지 않으며, 공개 계약의 일부로 간주되지 않는다.

 

이렇다고 볼 수 있다.

 

 

이런 측면에서 lombok의 Value와 springframework의 Value를 좀 정리해보면,

 

  • lombok.Value의 경우에는 문서화되지 않기 때문에 외부의 새로운 값을 주입받기 보다는, 지금 존재하는 값을 final 클래스로 만드는 쪽이나 DTO로 변환해서 사용할 수 있다.
  • springframework.Value의 경우에는 공개 계약으로 문서화되기 때문에, application.properties나 application.yml 파일에서 설정한 파일이나 환경 변수, 시스템 프로퍼티 등의 값을 필드에 주입할 때 주로 사용된다.

 

말만으로는 이해하기 어려울 것 같아서, 예시 코드를 각 Value마다 하나씩 가지고 왔다.

import lombok.Value;

@Value
public class Person {
    private String name;
    private int age;
}

 

 

import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Slf4j
@Controller
@RequestMapping("/spring")
public class SpringUploadController {

    @Value("${file.dir}")
    private String fileDir;
}

 

 

오늘 공부하는데 필요하던 Value의 경우에도 application.properties에서 설정한 file.dir을 가져와서 작업해야 하는 것이라서 springframework.Value의 값을 사용하는 것이 맞았다.

 

 

 

 

스프링 프레임워크가 백엔드에서 간편하게 제공해주는 기능이 많은 건 분명한 사실이지만, Value같이 원래도 사용 빈도가 높은 영어 단어들이 있는 경우에는 무엇이 import될지 모르기 때문에 매번 주의해서 사용해 줘야 하는 불편함이 있다. 이걸 인텔리제이가 100% 다 잡아주지 못하기 때문에 더더욱.

(매번 화내는 ;을 빼먹는 것과 같은 컴파일 에러는 바로 잡아주니 괜찮은데, 오타라든가 저런 import 실수는 정말 잘 보고 작업해야 하는 것이 맞다.)