애플리케이션의 각 계층에서 수행되는 입력값 검증의 범위와 책임

2026. 4. 6. 09:46·코드잇 스프린트/Spring 이론

1. Controller 계층

목적: 사용자 경험 보호, 빠른 피드백

검증 범위:

  • 필수 필드 존재 여부(null, empty)
  • 형식검증(이메일 형식, 날짜형식, 전화번호 패턴 ..)
  • 길이/범위 제함(글자수, 숫자 점위)

원칙: 이 계층의 검증은 신뢰할 수 없다. 클라이언트 검증은 언제든 우회 가능하므로, 보안을 위한 게이트로 삼으면 안된다.

// Controller: 형식과 필수값만 검증
@PostMapping("/users")
public ResponseEntity<?> createUser(@Valid @RequestBody CreateUserRequest request) {
    // @Valid: @NotNull, @Email, @Size 등 포맷 검증만 수행
    return userService.createUser(request);
}

@Valid: @NotNull, @Email, @Size등 포맷 검증만 수행한다.

 

2. Service 계층

목적: 비즈니스 규칙 수호, 도메인 불변식 보장

검증범위:

  • 비즈니스 규칙(ex: 만 19세 이상만 가입, 잔액 초과 출금 불가 ..)
  • *도메인 불변식(주문 상태 전이 유효성)
  • *교차 엔티티 일관성(A와 B가 동시에 존재해야하는 관계)
  • *권한/컨텍스트 기반 규칙

*도메인 불변식 : "불변식"이란 객체가 살아있는 동안 항상 참이어야 하는 규칙.

주문 상태 전이를 예로 들면: 주문생성 -> 결제완료 -> 배송중 -> 배송완료

                                                                                           -> 취소 가능/ 취소 불가

이 흐름을 절대 어겨서는 안된다. 배송완료된 주문을 갑자기 결제완료로 되돌리거나, 주문 생성에서 바로 배송완료로 건너뛰는건 불가능해야한다.


 

*교차 엔티티 일관성 : 

예) 팀 - 팀장의 관계

팀이 존재하면 -> 팀장 한명이 있어야한다.

팀장이 퇴사하면 -> 팀을 없애거나 팀장을 교체해야한다.

 

예2) Order - OrderItem 관계

주문은 반드시 1개 이상의 상품을 가져야한다.

마지막 상품을 지우면 주문 자체도 취소. 빈 주문은 존재할 수 없다.

-> 단순한 null 체크나 비즈니스 규칙이 아니라 "두 엔티티의 관계 자체가 깨지면 안된다"

 


*권한/컨텍스트 기반 규칙 : 같은 행위라도 누가 하느냐에 따라 달라짐.

동일한 요청이라도 호출자의 역할이나 상황에 따라 허용 여부가 달라지는 규칙.

 

예)

권한기반: 본인 글이거나 관리자만 삭제 가능.

컨텍스트 기반: 관리자도 공지상항은 슈퍼관리자만 삭제 가능.

 

예2) 같은 API라도 시간, 상태에 따라 달라지는 컨텍스트 규칙.

경매가 진행 중일 때만 입찰가능.

본인이 만든 경매에는 입찰 불가.

 

// Service: 비즈니스 규칙 검증
public void withdraw(Long accountId, Money amount) {
    Account account = accountRepository.findById(accountId);

    // 비즈니스 규칙: 잔액 부족, 계좌 상태, 일일 한도
    if (account.isLocked()) throw new AccountLockedException();
    if (account.getBalance().isLessThan(amount)) throw new InsufficientFundsException();
    if (account.getDailyWithdrawn().plus(amount).exceeds(DAILY_LIMIT))
        throw new DailyLimitExceededException();

    account.withdraw(amount);
}

 

3. Repository 계층

목적: 데이터 무결성 최후 방어선

검증범위:

  • DB제약조건(UNIQUE, NOT NULL, FK, CHECK)
  • *트랜잭션 격리 수준에 따른 동시성 보호
  • *외부 시스템 연동시 응답값 검증
-- DB는 최후의 안전망으로서 제약을 유지
ALTER TABLE users
    ADD CONSTRAINT uq_email UNIQUE (email),
    ADD CONSTRAINT chk_age CHECK (age >= 19);

 

*트랜잭션 격리 수준에 따른 동시성 보호

"동시에 여러 요청이 들어왔을때 데이터가 꼬이지 않게 보호하는 것"

1. 비관적 락(Pessimistic Lock)으로 해결: 내가 읽는 순간 다른 트랜잭션은 이 행에 손대지 마.

2. 낙관적 락(Optimistic Lock)으로 해결: 충돌이 드물거라 가정하고, 저장할때 버전 확인

 

*외부 시스템 연동시 응답값 검증

외부 API는 내코드가 아니므로, 응답을 믿지 말고 반드시 검증해야한다.

 

 

중복검증의 트레이드 오프

중복 검증을 완전히 없애는것이 항상 옳지는 않다. 의도적 중복과 우발적 중복을 구분해야한다.

구분 의도적 중복 우발적 중복
목적 계층별 방어, 보안 강화 코드 복붙, 설계 부재
예시 이메일 형식을 Controller·DB 모두 검증 동일한 비즈니스 규칙을 Controller·Service 양쪽에 작성
유지보수 각 계층이 독립적으로 역할 수행 규칙 변경 시 여러 곳 수정 필요

 

원칙1. 비즈니스 규칙은 Service에만.

비즈니스 규칙이 Controller에 있으면 API가 바뀔 때마다 규칙도 흩어진다.

 

원칙2. DB제약은 절대 제거 X

 

원칙3. 검증 로직을 도메인 객체로 응집.

public class Email {
    private final String value;

    public Email(String value) {
        if (value == null || !value.matches("^[\\w.]+@[\\w.]+\\.[a-z]{2,}$"))
            throw new InvalidEmailException(value);
        this.value = value;
    }
}

// Service, Controller 어디서 생성해도 동일한 규칙 적용
Email email = new Email(request.getEmail());



'코드잇 스프린트 > Spring 이론' 카테고리의 다른 글

Spring Security에서 왜 Member 대신 UserDetails를 사용하나?  (0) 2026.05.12
트랜잭션 ACID중 격리성(Isolation)이 보장되지 않을때 문제  (0) 2026.04.01
JPA에서 발생하는 N+1 문제의 발생 원인과 해결 방안(EAGER 는 JOIN이 아니다.)  (1) 2026.03.26
웹 API가 SOAP에서 REST로 전환된 이유  (0) 2026.02.27
Spring Bean이란?  (2) 2026.01.26
'코드잇 스프린트/Spring 이론' 카테고리의 다른 글
  • Spring Security에서 왜 Member 대신 UserDetails를 사용하나?
  • 트랜잭션 ACID중 격리성(Isolation)이 보장되지 않을때 문제
  • JPA에서 발생하는 N+1 문제의 발생 원인과 해결 방안(EAGER 는 JOIN이 아니다.)
  • 웹 API가 SOAP에서 REST로 전환된 이유
과컴
과컴
벡엔드 개발자 최소기준 맞추겠습니다.
  • 과컴
    곽의 프로그램
    과컴
  • 전체
    오늘
    어제
    • 분류 전체보기 (76)
      • 위클리페이퍼 (6)
      • 파이썬 (4)
      • 코드잇 스프린트 (48)
        • Spring 이론 (7)
        • Java이론 (11)
        • 실습 (23)
      • 백엔드 개발자 최소기준 (1)
      • 코딩테스트 (5)
        • 알고리즘 (0)
        • SQL (1)
      • Git (5)
      • 스프링부트 핵심가이드 (1)
      • 트러블 슈팅 (2)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    파이썬기초
    혼공파
    문자열
    파이썬입문
    백준1075번
    백준2576
    파이썬
    백준브론즈
    백준1152
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
과컴
애플리케이션의 각 계층에서 수행되는 입력값 검증의 범위와 책임
상단으로

티스토리툴바