Home Input값의 검증은 어디서 이루어져야 할까?
Post
Cancel

Input값의 검증은 어디서 이루어져야 할까?

미션을 진행하면서 나는 입력 값에 대한 검증을 View에서도 해보고, 각 도메인 객체에서 해보기도 했다.

이렇게 여러 곳에 검증을 둬보며 검증의 역할을 어디에 두어야 하는 지에 대해 고민한 결과를 기록해보려 한다.

  • View에서 검증
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class InputView {  
  
	private InputValidator inputValidator;  
	  
	public InputView() {  
		this.inputValidator = new InputValidator();  
	}  
	  
	public String inputCarName() {  
		System.out.println(CAR_NAME_INPUT_MSG.getMsg());  
		String carName = Console.readLine();  
		inputValidator.validateInputCarName(carName);  
		return carName;  
	}  
	  
	public Integer inputTryCount() {  
		System.out.println(TRY_COUNT_INPUT_MSG.getMsg());  
		String tryCount = Console.readLine();  
		inputValidator.validateInputTryCount(tryCount);  
		return Integer.parseInt(tryCount);  
	}  
}
  • 도메인 객체 내부에서 검증
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
public class BonusNumber {  
	private static final Pattern bonusNumberRegex = Pattern.compile("\\d+");  
	  
	private final int number;  
	  
	private BonusNumber(String bonusNumber, WinningNumbers winningNumbers) {  
		validate(bonusNumber, winningNumbers);  
		this.number = parseBonusNum(bonusNumber);  
	}  
	  
	public static BonusNumber create(String bonusNumber, WinningNumbers winningNumbers) {  
		return new BonusNumber(bonusNumber, winningNumbers);  
	}  
	  
	private void validate(String bonusNumber, WinningNumbers winningNumbers) {  
		validateFormat(bonusNumber);  
		LottoValidator.validateRangeOfNumber(parseBonusNum(bonusNumber));  
		validateDuplicateNumber(bonusNumber, winningNumbers);  
	}  
	  
	private void validateFormat(String bonusNumber) {  
		Matcher matcher = bonusNumberRegex.matcher(bonusNumber);  
		boolean isInvalidFormat = !matcher.matches();  
		  
		if (isInvalidFormat) {  
			throw new BonusNumberFormatException();  
		}  
	}  

	/... 
}

각 경우의 장점과 고려해야 할 부분

View에서 검증을 했을 경우

장점

  • 관심사를 분리할 수 있다.
    • View는 어떻게 보면 사용자와의 상호작용과 출력 로직을 처리하는 역할을 한다. 입력에 대한 검증은 사용자와의 상호작용에서의 책임이라고 볼 수 있다.
  • 사용자 피드백에 즉각적이다.

고려 사항

검증을 View에서 했을 경우 프로그램의 크기가 커진다면 검증 로직이 View와 밀접하게 연결되어 강한 결합이 생겨 문제가 발생할 수 있다.

코드 중복의 문제가 발생하거나, 테스트가 어려워진다거나 하는 문제가 발생한다.

도메인 객체 내부에서 검증을 했을 경우

장점

  • 캡슐화 및 일관성에 장점이 있다.
    • 도메인 객체에 검증 로직을 캡슐화함으로써 객체가 항상 유효한 상태에 있도록 보장할 수 있다.
  • 재사용성
    • 도메인 객체에 캡슐화된 검증 로직은 애플리케이션의 다양한 부분에서 재사용이 가능할 수 있다.

고려 사항

도메인 객체 내부에서 검증을 했을 경우, 입력값의 검증임에도 도메인 객체를 생성하거나 사용하려고 시도하는 경우에만 오류가 명백해진다. 물론 미션에 사용한 코드에서는 즉각적으로 사용자에게 Exception이 발생하지만, 커다란 애플리케이션 코드에서는 예상치 못하게 사용자에게 문제를 전달할 수 없을 수 있다.

결론

내 생각에는 각각 장단점이 있어 정답은 없는 것 같다.

한 가지 검증 방법을 택하는 대신 두 가지 방법을 섞어서 사용할 수 있을 것 같다.

예를 들어 정규표현식을 사용하여 입력값 포맷에 대해 검증을 받는 부분은 사용자의 입력에 따른 즉각적인 피드백을 받을 수 있도록 View에서 담당하고,

정상적인 포맷으로 입력된 입력 값에 대한 구체적이고 복잡한 검증 로직은 도메인 객체에서 담당하는 방식이다.

이렇게 한다면 두 가지 경우의 장점을 살려 검증을 해낼 수 있을 것이라고 생각한다. 물론 정답은 없다고 생각한다. 더 나은 선택은 애플리케이션 요구사항에 따라 매번 달라질 수 있을 것이다.

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