외부 라이브러리 @bean 등록에 관하여..

인프런 강의 : 스프링 핵심 원리 강의를 듣던 중..

@PostConstruct, @PreDestroy 애노테이션의 특징

  • 최신 스프링에서 가장 권장하는 방법이다.
  • 애노테이션 하나만 붙이면 되므로 매우 편리하다.
  • 패키지를 잘 보면 javax.annotation.PostConstruct 이다. 스프링에 종속적인 기술이 아니라 JSR-250 라는 자바 표준이다. 따라서 스프링이 아닌 다른 컨테이너에서도 동작한다.
  • 컴포넌트 스캔과 잘 어울린다.
  • 유일한 단점은 외부 라이브러리에는 적용하지 못한다는 것이다. 외부 라이브러리를 초기화, 종료 해야 하면 @Bean의 기능을 사용하자.

여기서 마지막 줄

유일한 단점은 외부 라이브러리에서는 적용하지 못한다.

라는 말이 있었는데.. 사실 이 말이 제대로 와닿지 않았다.
외부 라이브러리를 등록한다는 게 어떤 건지..

그래서 검색해본 결과
https://jojoldu.tistory.com/27

 

@Bean vs @Component

Spring으로 개발을 하다보면 @Bean과 @Component를 언제 써야할지 헷갈릴때가 있다. 둘다 목적이 명확하지 않은 Bean을 생성할때 사용하는 어노테이션인데 왜 2개로 나누어져있나 궁금했었는데, 박재성

jojoldu.tistory.com

이동욱님 블로그에서 예시로 든 ObjectMapper를 보고 아~ 이런 라이브러리를 말하는 거구나 하고 와닿았다. ObjectMapper 안의 .class 파일 내부에 초기화 메소드나 소멸 메소드 위에 위의 어노테이션을 쓸 수 없으니 @Bean 에 선언하는 방법을 쓴다는 거였다.

https://www.inflearn.com/questions/264681

 

코드 수정을 할 수 없는 외부 라이브러리에는 왜 어노테이션을 사용하지 못할까 - 인프런 | 질문

안녕하십니까  이번 수업을 듣다가 코드를 고칠 수 없는 외부 라이브러리가 무엇일까해서 옛날에 했던 질문들을 보며 이해를 했습니다. 그래서 질문 내용처럼 왜 어노테이션을 사용하면 외부

www.inflearn.com

 


 

ObjectMapper 하니까 이전에 프로젝트에 추가한 ModelMapper 가 떠올랐다.
당시엔 bean 이나 이런 스프링에 대한 개념이 전혀 없어서.. ModelMapper를 추가하고자 여러 블로그를 검색하고..
하나를 복사해서 붙여넣었는데..
아무래도 그 당시에도 @Bean을 등록한다는 게 알지 못하는 영역이라 몰라서.. static Method로 등록했던 거 같다.

public class ModelMapperUtils {

    private static ModelMapper modelMapper = new ModelMapper();

    public static ModelMapper getModelMapper() {
        return modelMapper;
    }
}

근데 웃긴 건 이때는 진짜 bean에 대한 개념이 하나도 없어서 라이브러리 추가하고 modelMapper를 불러와서 써야하니깐

@Autowired
private ModelMapper modelMapper; 

이렇게 불러서 썼었다. 당연히 바로 에러. 그래서 어떻게 하지 하고 검색하다 class 생성하고 static method 만들어서
ModelMapperUtils.getModelMapper().map(source, destinationType) 이렇게 사용하고 있었다.

근데 다시금 소스를 찾아보니.. 이렇게 써도 되나 싶었음.
ModelMapperUtils 를 호출할 때 마다 새로 new 로 ModelMapper가 생성되기 때문에 성능이 떨어질 거 같단 생각이 들었음.

https://okky.kr/article/291799

 

OKKY | static 메소드를 사용하는 것과 스프링 빈을 이용하는 것은 차이가 많이 나나요?

사용자가 이미지를 업로드 하면 해당 파일을 서버에 저장하는 UploadThumbnailImageService 클래스를 구현했는데요. 안에는 setThumbnailImage() 메소드가 있습니다.  그리고, controller에서 해당 서비스 클래

okky.kr

그래서 검색해보니 .. 성능이 떨어지는 건 확실한 거 같다. 그게 유의미한 정도인지 까지는 모르겠지만..

기존 코드를

@Bean
public ModelMapper modelMapper() {
    return new ModelMapper();
}

이렇게 등록하고

result = ModelMapperUtils.getModelMapper().map(entity, DTO.class);

기존의 이런 코드를

@Autowired
private ModelMapper modelMapper;

...

result = modelMapper.map(entity, DTO.class);

이렇게 바꾸면 될 것 같다.

 


 

@Bean@Component 의 차이는 위 이동욱님 블로그에 잘 나와있는데, @Bean의 경우 직접 컨트롤이 불가능한 외부 라이브러리를 빈 주입할 때 쓴다. @Component는 Class 위에 선언 가능. (둘이 target이 다르다)
그러므로 ModelMapper@Bean을 사용해야 한다.

흠 저렇게 바꾸고 싶은데.. 그럼 의존성 주입을 다 새로 해야되서.. 안될듯.. 역시 이래서 처음 하는게 중요하다.

 


 

유의미한 차이가 있나..? 하고 인프런에 글을 올렸다. @bean 등록과 static method가 차이가 있는지.. 

https://www.inflearn.com/questions/309346

 

@Bean 등록과 static method 선언 시 성능 차이가 많이 날까요? - 인프런 | 질문 & 답변

안녕하세요 강의 잘 듣고 있습니다. 외부 라이브러리 bean 등록에 대해서 생각하다가.. 제가 일하다가 외부 라이브러리(ModelMapper)를 추가한 적이 있었는데요 그땐 bean에 대한 개념을 잘 모를때라 c

www.inflearn.com

 

결론적으론 유의미한 차이는 아니라고 하셨다. 

 

여기서 서포터즈 님께서 ModelMapper에 대한 성능에 대해 말씀해주셨는데.. 이건 익히 알던 내용이였다.

"ModelMapper는 건수가 많을 때 성능이 떨어지므로.. 쓰지 말자~ " 이러한 내용.

그래서 회사에 MapStruct 를 추가하려고 했으나.. 인텔리제이는 자동 컴파일이 되는데 이클립스는 컴파일을 항상 눌러줘야 되는 문제로.. (해결방안을 더 찾아보고 싶었지만.. 자꾸 내가 추가한 라이브러리로 오류가 발생하는 게 심적으로 고통이 커서..) MapStruct 라이브러리를 삭제하는 걸로 결론을 내렸다. 

https://www.inflearn.com/questions/15292

 

DTO 변환 시 우아한형제들은 어떻게 처리하시나요? - 인프런 | 질문 & 답변

샘플에서 DTO는 생략하셔서 아쉽습니다. DTO 변환으로 modelmapper나 mapstruct 정도 쓰는것같습니다.물론 mapper 없이도 하시는것 같던데요. 우아한형제들은 mapper에 대한 고견이 어떠신지 매우 궁금합니

www.inflearn.com

영한님 답변에서도 dto entity 변환 시 modelMapper 보단 수동으로 작업해서 컴파일시 오류를 잡아낼 수 있게 한다고 하셨는데 (우아한 형제들의 경우 당연히 mapstruct를 사용할 줄 알았는데.. 아니여서 놀랐다.) 이게 맞는 말인 거 같다. mapstruct 같은 경우도 다른 케이스 작업할 때 그거 옵션 생각해서 적는 게 더 오래 걸렸었음... 뭐 간단한 경우엔 modelMapper 사용하는게 편하겠지만 그외 특수 케이스는 그냥 수동으로 설정하는 것이 좋을 것 같다.