0. 목차

  1. 개요
  2. 문제점
  3. 첫 시도
  4. 첫 시도의 문제점
  5. 두 번째 시도
  6. 두 번째 시도의 문제점
  7. 최종 해결 방식
  8. 결론

1. 개요

이번 글에서는 유효성 검증 로직에서 변화를 최소화하면서 고도화하는 내용을 다룹니다. 기존 boolean 값만을 리턴하는 로직을 변경해 실패 상세 detail 메시지를 전달하는 것이 목표였습니다. 이를 달성하는 과정에서 시도한 여러가지 방법과 최종적으로 채택한 방식에 대해 소개합니다.

2. 문제점

기존 시스템에서는 다음과 같이 boolean 값을 체크하고 이에 대한 결과를 리턴했습니다.

public abstract class Payload {

    public boolean isInValid() {
        return !isValid();
    }

    public boolean isValid() {
        return satisfyRequired() && satisfyStringLimit() &&satisfyStringsLimit50() && satisfyEnumValidation() && allFieldsSatisfy(this::fieldIsSatisfactory);
    }

    protected boolean satisfyRequired() {
        return Arrays.stream(this.getClass().getDeclaredFields())
// 필드의 검증 로직 수행 결과 리턱
                });
    }

// ...
@Component
@Order(2)
public class SampleValidator implements Validator {
// ...private Optional<String> validatePayloadContent(ValidationContext context) {
        Payload payload = context.payload();
        if (payload == null || payload.isInValid()) {
            return Optional.of("Invalid payload: " + context.logEvent.payLoadSimpleName());
        }
        return Optional.empty();
    }

// ...

이러한 방식은 어떤 검증이 실패했는지에 대한 상세 정보를 제공할 수 없다는 단점이 있었습니다.

예를 들어 각각의 Payload는 다음과 같이 다양한 조건들을 애노테이션으로서 설정하고 있는데, 이에 대한 검증 중 하나라도 실패한다면 실패로 판단되지만, 구체적으로 어느 조건에서 실패했는지에 대해서는 내부 필드 값들을 직접 확인해 따져야만 했던 것입니다.

public class DataTransferPayload extends Payload{
    @Required
    @String25
    private String vId;
    @String50
    private String mId;

    public static class Response extends Payload{
        @Required
        @EnumValidation(enumClass = SampleStatus.class)
        private String status;

        private String data;
    }
}