환전 요청 프로젝트

위승현·2024년 11월 28일
0

Spring

목록 보기
4/12

1. @PostConstruct의 위치는 어디에?

처음에 @PostConstruct를 사용해서 DB 내의 통화 데이터에
환율이 0 이하인 경우를 찾아내어 있다면 log로 error 메시지를 출력하는 기능을 구현할 때
새로운 클래스를 만들었다.

@Slf4j
@Component
@RequiredArgsConstructor
public class CurrencyRateValidator {
    private final CurrencyRepository currencyRepository;

    @PostConstruct
    public void validateCurrencyRate(){
        List<Currency> currencies = currencyRepository.findAll();

        currencies.forEach(currency -> {
            BigDecimal exchangeRate = currency.getExchangeRate();
            if (exchangeRate.compareTo(BigDecimal.ZERO) <= 0 ) {
                log.error("Currency exchange rate is less than zero");
            }
        });
    }
}

잘 구동되었고 넘어가려던 찰나
굳이 새로운 클래스를 만들어야하나? 라는 생각이 들었다.
구동될 때 검증되는 부분이니 단순히 생각해 common 패키지 내부에 이 클래스를 만들었었는데

코드를 자세히 보면 CurrencyRepository 를 사용하는 모습이 보인다.

내가 이해한 @PostConstruct의 동작 순서는

  1. 빈 생성: Spring 컨테이너가 빈을 생성한다.

  2. 의존성 주입: 생성된 빈에 필요한 의존성이 주입된다. (생성자, 필드 등등..)

  3. 초기화 메서드 호출: 모든 의존성이 주입된 후, @PostConstruct가 붙은 메서드가 호출된다.

  4. 빈 사용: 초기화가 완료된 후, 빈은 애플리케이션에서 사용될 수 있다.

이런 식으로 진행되는 것이었고
빈으로 등록하기 위해 @Component 를 사용하는 것이었는데
이것과 구조가 유사한 계층이 이미 존재했다.

바로 서비스 계층이었다.

이미 CurrencyService 계층에는 @Service 내부에 @Component 가 존재했고
CurrencyRepository 로 서비스 계층에서 이미 사용하고 있었기에
새로운 클래스를 만들기보다 서비스 클래스 내부에 @PostConstruct를 사용한 초기화 메서드를
위치시키는게 더 맞다는 판단이 들었다.

따라서 서비스 계층으로 해당 메서드를 옮겼고 잘 동작되는 모습도 보았다.

이 판단이 맞는 판단인지는 피드백 때 알아보아야겠다.


2. 난 패키지 구성을 바꿨을 뿐인데...

원래 왼쪽의 형태로 구성되어있던 프로젝트 구조를 조금 더 깔끔하게 만들어보고자
도메인 별로 쪼개어 내부에 service, repository, controller, dto, entity 패키지를
만들어서 쉽게 원하는 곳으로 찾아갈 수 있게 만들었다.

그리고 실행을 해봤는데...

갑자기 냅다 이런 오류가 발생하는 것이었다.

뭐지??
creating bean 에서 문제가 생기는데..
내가 만든 exchange 하위 패키지에 있는 모든 곳에서 bean 주입 관련 에러가 발생하는 듯 보였다.

수많은 웹서핑, ai의 도움을 받아도 전혀 해결할 수 없었고..
결국에 튜터님께 찾아가 자문을 구했다

이런 저런 폴더들을 뒤져보던 중

평소 맨 윗줄에서 파랗게 파일 명을 보여주는 에러만 즐겨보던 나에게
튜터님이 맨 아랫줄 에러를 한번 보죠. 라고 하셨고

Caused by: org.hibernate.query.SemanticException: Could not resolve 
class 'com.sparta.currency_user.exchange.ExchangeGroupResponseDto' 
named for instantiation [select new com.sparta. .. 이하 생략

이 줄을 보자마자 나는 바로 알아차릴 수 있었다...

바로 ExchangeRepository에서 사용하고 있는

@Query(
       "select new com.sparta.currency_user.exchange.dto.ExchangeGroupResponseDto(count(u), sum(u.amountInKrw))"
           + " from UserCurrency u where u.user.id = :id and u.status = :status")
   ExchangeGroupResponseDto findGroupExchangeRequestByUserId(Long id, UserCurrencyStatus status);

jpql에서 발생하는 문제였다..
나는 jpql을 사용해서 entity가 아닌 dto로 바로 변환을 받는 기술을 사용하고 있었고
당연히 패키지 구조를 바꿨기에 select new 뒤에 오는 DTO 경로도 바꿔줬어야했다.

파일을 옮길 때 대부분은 인텔리제이에서 알아서 리팩터링을 해주니
내가 직접 적은 sql문에 영향을 끼칠거라고 생각조차 못한 것이었다..!!!

바로 패키지 경로를 고치니 모든 것이 해결되었고
이를 통해 한가지의 교훈을 얻을 수 있었다.

  1. 에러메시지는 전부 꼼꼼하게 읽어보자..!!!
profile
개발일기

0개의 댓글

관련 채용 정보