Post

검증로직 분리하기

검증로직을 분리하는 이유와 서비스 계층이 가지고 있던 검증로직을 모듈로 분리하는 과정을 설명합니다.

updateEnhanceItem 메서드는 아이템 기록 도전정보를 받아서 새로운 기록으로 적합하다면 등록하고 성공응답을 반환하고, 기록으로 등록하기에 미달이라면 새로운 기록으로 등록하지 않고 실패응답을 반환하는 서비스 계층의 메서드입니다.

기존의 코드에서는 위의 이미지에 보이시는 것처럼 검증로직을 서비스 메서드 내에서 호출하여 다음과 같은 문제가 있었습니다.

  • 서비스 계층에서 데이터를 검증하는 책임을 가지고 있다.
  • 검증 로직 메서드가 private으로 선언되어 테스트하기 어렵다.
  • 테스트하기 어려운 코드(DB접근)와 함께 위치하여 테스트하기 어렵다.

현재 검증을 수행하는 validateEnhanceRequest 메서드는 서비스 계층에서 private 메서드로 정의되어 있습니다. 따라서 검증로직만 따로 테스트하기가 어렵습니다. 테스트를 위해서는 updateEnhanceItem 메서드에 잘못된 요청 DTO를 전달하는 방법을 사용해야하는데, 기존의 코드로는 검증에 실패해도 예외를 던지는 것이 아니라 실패 응답을 반환하고 있기 때문에 검증로직으로 실패한 것인지 판단하기도 어렵습니다. 무엇보다도 updateEnhanceItem 메서드를 호출하면 테스트하기 어려운 DB 접근 코드를 함께 사용한다는 점도 테스트하기 어렵게 만드는 원인이 됩니다.

다음과 같은 방법으로 해결하고자 합니다.

  • 도전 요청의 검증로직을 담은 클래스를 정의한다.
  • 검증을 처리하는 메서드를 public으로 공개한다.
  • 검증 세부 로직은 private 메서드로 정의한다.

도전 요청을 검증하는 로직은 애플리케이션 전체적으로 필요로 하는 것이 아니라 도메인을 위한 로직이라고 생각했기 때문에 도메인 계층에 정의하였다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Component
public class EnhanceItemValidator {

    public void validateRequest(final ItemEnhanceServiceRequest request) {
        validateSuccessCount(request.getSuccess());
        validateScore(request.getSuccess(), request.getScroll(), request.getUpgradable());
    }

    private void validateSuccessCount(final EnhanceSuccess success) {
        final int ten = success.getTenSuccessCount();
        final int sixty = success.getSixtySuccessCount();
        final int hundred = success.getHundredSuccessCount();
        
        final int total = ten + sixty + hundred;
        if (total > 10) {
            throw new EnhancedItemException(INVALID_ENHANCED_SUCCESS_REQUEST);
        }
    }

    private void validateScore(
        final EnhanceSuccess success, 
        final EnhanceScroll scroll, 
        final int upgradable
    ) {
        final int maximumScore = scroll.getMaximumScore(upgradable);
        final int actualScore = scroll.calculateScore(success);
        if (actualScore > maximumScore) {
            throw new EnhancedItemException(INVALID_ENHANCED_SCORE_REQUST);
        }
    }
}

서비스 계층에서 검증 클래스를 주입받아서 사용했으며, 실제로 사용하는 코드는 다음과 같다. 이제 검증로직을 테스트하고 싶으면 검증 클래스만 주입받아서 테스트하면된다.

This post is licensed under CC BY 4.0 by the author.