LogoSEO Jing
  • All Posts
  • SEO Jing
  • okayJing
  • KD Team
  • CLab CoreTeam
  • Study

Contact Me

© 2026 SEOJing. All rights reserved.

백엔드스터디Spring BootJavaAPI검증에러 처리AI 코드 읽기

백엔드 스터디 Day 3: 검증과 에러 응답을 읽는 법

2026년 6월 2일·20분 읽기

예상 읽기 시간: 20~30분

오늘의 목표

Day 1에서는 Spring Boot 프로젝트의 큰 지도를 잡았습니다. Day 2에서는 프론트엔드와 백엔드가 맞춰야 하는 API 계약, 즉 URL, HTTP Method, 요청 DTO, 응답 DTO를 읽었습니다.

오늘은 그 API 계약이 틀렸을 때 백엔드가 어떻게 반응해야 하는지 봅니다.

사용자가 빈 제목으로 글을 작성하거나, 잘못된 이메일을 입력하거나, 존재하지 않는 게시글을 열거나, 권한 없는 방에 접근할 때 백엔드는 그냥 "실패"만 말하면 부족합니다. 프론트엔드는 사용자가 무엇을 고쳐야 하는지 보여 줘야 하고, 개발자는 어떤 요청이 왜 실패했는지 추적할 수 있어야 합니다.

그래서 오늘의 핵심 질문은 이것입니다.

AI가 만든 백엔드가 잘못된 입력과 실패 상황을 예측 가능한 모양으로 돌려주는가?

오늘 글을 읽고 나면 아래 질문에 답할 수 있어야 합니다.

  • 입력 검증은 왜 Controller 근처에서 시작되는가?
  • @Valid, @NotBlank, @Size, @Email 같은 어노테이션은 무엇을 보장하는가?
  • 검증 실패와 비즈니스 실패는 어떻게 다른가?
  • 400, 401, 403, 404, 409, 500 같은 HTTP 상태 코드는 어떻게 읽는가?
  • @ControllerAdvice와 @ExceptionHandler는 왜 필요한가?
  • AI가 만든 에러 처리 코드에서 무엇을 확인해야 하는가?

1. 검증은 "나쁜 사용자"를 의심하는 기능이 아니다

입력 검증이라고 하면 처음에는 보안 기능처럼 느껴질 수 있습니다. 물론 보안과도 관련이 있습니다. 하지만 더 넓게 보면 검증은 서비스가 자기 규칙을 지키기 위한 입구입니다.

예를 들어 게시글 작성 화면을 생각해 봅시다.

json
{
  "title": "",
  "content": "오늘 공부한 내용",
  "categoryId": 3
}

제목이 비어 있습니다. 이 요청을 그대로 저장하면 DB에는 제목 없는 게시글이 생깁니다. 화면에서는 목록이 이상하게 보일 수 있고, 검색이나 공유 링크에서도 문제가 생길 수 있습니다.

이때 백엔드가 해야 할 일은 단순합니다.

포스트 목록

/study/backend
파일 8개, 폴더 0개
백엔드 스터디 Day 1: 스프링 프로젝트를 읽기 위한 최소 지도백엔드 스터디 Day 2: API 계약과 DTO를 읽는 법백엔드 스터디 Day 3: 검증과 에러 응답을 읽는 법백엔드 스터디 Day 4: Entity와 Repository로 DB 흐름 읽기백엔드 스터디 Day 5: Service와 트랜잭션으로 비즈니스 흐름 읽기백엔드 스터디 Day 6: 로그인과 권한 흐름을 코드에서 읽기백엔드 스터디 Day 7: 테스트 코드로 AI 백엔드 검증하기백엔드 스터디 Day 8: 배포와 운영 환경 읽기
text
이 요청은 우리 서비스 규칙에 맞지 않는다.
저장하지 않는다.
프론트엔드가 사용자에게 보여 줄 수 있는 설명을 돌려준다.

검증은 사용자를 혼내기 위한 기능이 아닙니다. 잘못된 데이터가 서비스 안쪽으로 들어오지 못하게 막고, 사용자가 고칠 수 있는 방식으로 알려 주는 기능입니다.

AI가 만든 백엔드 코드를 볼 때도 이렇게 생각하면 됩니다.

  • 이 API는 어떤 입력을 받아야 하는가?
  • 필수 값과 선택 값이 나뉘어 있는가?
  • 문자열 길이, 숫자 범위, 이메일 형식 같은 기본 규칙이 표현되어 있는가?
  • 실패했을 때 프론트엔드가 어떤 필드가 문제인지 알 수 있는가?

2. 검증은 보통 요청 DTO에 붙는다

Day 2에서 DTO는 API 입출력 전용 데이터 모양이라고 했습니다. 검증 규칙도 보통 요청 DTO에 붙습니다.

java
public record CreatePostRequest(
    @NotBlank(message = "제목은 필수입니다.")
    @Size(max = 100, message = "제목은 100자 이하여야 합니다.")
    String title,

    @NotBlank(message = "본문은 필수입니다.")
    String content,

    @NotNull(message = "카테고리는 필수입니다.")
    Long categoryId
) {
}

여기서 문법을 전부 외울 필요는 없습니다. 읽을 때는 이렇게 보면 됩니다.

text
CreatePostRequest는 게시글 작성 요청의 모양이다.
title은 비어 있으면 안 되고 100자 이하여야 한다.
content는 비어 있으면 안 된다.
categoryId는 null이면 안 된다.

AI가 만든 코드에서 이런 어노테이션이 없으면 무조건 틀렸다고 말할 수는 없습니다. 하지만 의심할 수는 있습니다.

특히 아래 요청 DTO에는 검증 규칙이 없는지 확인하는 습관을 들이면 좋습니다.

  • 회원가입 요청
  • 로그인 요청
  • 게시글/댓글 작성 요청
  • 결제/주문 요청
  • 파일 업로드 요청
  • 권한 변경 요청
  • 프로필 수정 요청

사용자가 직접 입력하는 값이거나 서비스 상태를 바꾸는 요청이라면 검증 규칙이 필요할 가능성이 높습니다.


3. @Valid는 "이 DTO의 검증 규칙을 실행해라"라는 신호다

DTO에 검증 어노테이션을 붙였다고 해서 항상 자동으로 실행되는 것은 아닙니다. Controller에서 그 DTO를 받을 때 보통 @Valid를 붙입니다.

java
@PostMapping("/api/posts")
public PostResponse createPost(@Valid @RequestBody CreatePostRequest request) {
    return postService.createPost(request);
}

읽는 법은 이렇습니다.

text
POST /api/posts 요청이 오면 JSON 바디를 CreatePostRequest로 바꾼다.
그리고 CreatePostRequest에 붙어 있는 검증 규칙을 먼저 검사한다.
통과하면 postService.createPost로 넘긴다.

여기서 중요한 점은 순서입니다.

검증이 실패하면 보통 Service까지 가지 않습니다. 즉, 제목이 비어 있는 요청은 게시글 저장 로직으로 들어가기 전에 Controller 입구에서 막힙니다.

AI가 만든 코드를 리뷰할 때는 Controller와 DTO를 같이 봐야 합니다.

  • DTO에는 검증 어노테이션이 있는가?
  • Controller 파라미터에는 @Valid가 붙어 있는가?
  • @RequestBody가 붙어 있어 JSON 바디를 읽는 구조인가?
  • 검증 실패 응답을 전역에서 처리하고 있는가?

DTO만 보고 "검증이 있네"라고 끝내면 안 됩니다. Controller에서 실행 신호가 빠졌을 수도 있습니다.


4. 검증 실패와 비즈니스 실패는 다르다

백엔드 실패를 모두 하나로 보면 에러 처리가 복잡하게 느껴집니다. 먼저 두 종류를 나누면 훨씬 읽기 쉬워집니다.

검증 실패

요청 모양 자체가 잘못된 경우입니다.

text
제목이 비어 있음
이메일 형식이 아님
비밀번호가 너무 짧음
페이지 번호가 음수임
필수 값이 없음

이런 실패는 대체로 Controller 입구에서 잡힙니다. HTTP 상태 코드는 보통 400 Bad Request입니다.

비즈니스 실패

요청 모양은 맞지만, 서비스 규칙상 처리할 수 없는 경우입니다.

text
존재하지 않는 게시글 ID
이미 사용 중인 이메일
삭제 권한이 없는 댓글
재고보다 많은 주문 수량
이미 마감된 모집글 신청

이런 실패는 Service에서 판단하는 경우가 많습니다. HTTP 상태 코드는 상황에 따라 다릅니다.

  • 없는 리소스: 404 Not Found
  • 중복/충돌: 409 Conflict
  • 인증 안 됨: 401 Unauthorized
  • 권한 없음: 403 Forbidden

AI가 만든 코드를 볼 때는 실패 위치를 이렇게 추적하면 됩니다.

text
입력 모양 문제인가? -> DTO/Controller 검증
서비스 규칙 문제인가? -> Service 예외
DB 저장 중 문제인가? -> Repository/DB 예외, 보통 직접 노출하면 안 됨

이 구분이 되어 있으면 긴 코드에서도 어디를 봐야 하는지 덜 흔들립니다.


5. HTTP 상태 코드는 프론트엔드에게 주는 첫 번째 힌트다

프론트엔드는 에러 응답을 받았을 때 상태 코드를 먼저 봅니다. 상태 코드는 사람이 읽는 문장보다 더 빠르게 "어떤 종류의 실패인지" 알려 줍니다.

자주 보는 상태 코드를 낮은 단계로 정리하면 이렇습니다.

상태 코드의미프론트엔드 관점
400요청 자체가 잘못됨입력값을 고치라고 안내
401로그인/토큰이 없음 또는 만료로그인 화면으로 보내거나 재로그인 요청
403로그인은 했지만 권한이 없음접근 불가 안내

AI가 만든 백엔드에서 모든 실패를 500으로 돌려주면 위험합니다. 프론트엔드는 사용자가 입력을 고쳐야 하는지, 다시 로그인해야 하는지, 없는 페이지로 간 것인지 알 수 없습니다.

반대로 모든 실패를 400으로 돌려주는 것도 좋지 않습니다. 존재하지 않는 게시글과 잘못된 이메일 형식은 같은 문제가 아닙니다.

리뷰할 때는 이런 질문을 던지면 됩니다.

  • 잘못된 입력은 400인가?
  • 없는 데이터는 404인가?
  • 중복 생성은 409인가?
  • 인증/권한 문제는 401과 403을 구분하는가?
  • 예상하지 못한 서버 오류의 내부 메시지를 그대로 사용자에게 보내지 않는가?

6. 에러 응답도 DTO처럼 계약이다

성공 응답만 API 계약이 아닙니다. 에러 응답도 계약입니다.

나쁜 예를 먼저 봅시다.

json
"error"

또는 이런 응답도 프론트엔드 입장에서는 애매합니다.

json
{
  "message": "잘못된 요청입니다."
}

무엇이 잘못되었는지, 어떤 필드를 고쳐야 하는지, 개발자가 로그와 연결할 수 있는 정보가 있는지 알기 어렵습니다.

조금 더 읽기 좋은 에러 응답은 이런 모양입니다.

json
{
  "code": "VALIDATION_ERROR",
  "message": "입력값을 확인해 주세요.",
  "fields": [
    {
      "field": "title",
      "message": "제목은 필수입니다."
    },
    {
      "field": "categoryId",
      "message": "카테고리는 필수입니다."
    }
  ]
}

이 응답을 프론트엔드는 이렇게 사용할 수 있습니다.

text
title 필드 아래에 "제목은 필수입니다." 표시
categoryId 선택 영역 아래에 "카테고리는 필수입니다." 표시
상단에는 "입력값을 확인해 주세요." 표시

즉, 에러 응답은 사용자 경험과 직접 연결됩니다.

AI가 만든 코드에서 에러 응답 DTO를 찾을 때는 보통 이런 이름을 찾으면 됩니다.

  • ErrorResponse
  • ApiErrorResponse
  • ErrorDto
  • FieldErrorResponse
  • ProblemDetail

Spring Boot 3에서는 ProblemDetail을 쓰는 코드도 볼 수 있습니다. 이름이 무엇이든 핵심은 같습니다.

text
에러 응답의 모양이 일관적인가?
프론트엔드가 필드별 메시지를 읽을 수 있는가?
내부 예외 메시지나 stack trace를 그대로 내보내지 않는가?

7. @ControllerAdvice는 에러 처리의 중앙 안내 데스크다

여러 Controller가 있으면 에러 처리 코드가 흩어지기 쉽습니다.

text
PostController에서 검증 실패 처리
UserController에서 검증 실패 처리
CommentController에서 검증 실패 처리
...

이렇게 되면 Controller마다 에러 응답 모양이 달라질 수 있습니다. 어떤 API는 { message: ... }, 어떤 API는 { error: ... }, 어떤 API는 그냥 문자열을 반환할 수도 있습니다.

Spring에서는 전역 예외 처리 클래스를 만들어 이런 처리를 한 곳으로 모을 수 있습니다.

java
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException ex) {
        ErrorResponse response = ErrorResponse.from(ex);
        return ResponseEntity.badRequest().body(response);
    }

    @ExceptionHandler(PostNotFoundException.class)
    public ResponseEntity<ErrorResponse> handlePostNotFound ex 

읽는 법은 이렇습니다.

text
어떤 Controller에서든 MethodArgumentNotValidException이 발생하면 handleValidation이 처리한다.
어떤 Controller에서든 PostNotFoundException이 발생하면 handlePostNotFound가 처리한다.
각 예외는 정해진 상태 코드와 정해진 ErrorResponse 모양으로 바뀐다.

AI가 만든 코드에서 GlobalExceptionHandler, ExceptionHandler, ControllerAdvice 같은 이름을 찾으면 에러 처리의 중심을 찾는 데 도움이 됩니다.


8. Service에서는 "서비스 규칙 위반"을 예외로 표현한다

예를 들어 게시글 상세 조회를 생각해 봅시다.

java
public PostResponse getPost(Long postId) {
    Post post = postRepository.findById(postId)
        .orElseThrow(() -> new PostNotFoundException(postId));

    return PostResponse.from(post);
}

이 코드는 문법보다 흐름을 읽으면 됩니다.

text
postId로 게시글을 찾는다.
없으면 PostNotFoundException을 던진다.
있으면 PostResponse로 바꿔서 반환한다.

여기서 PostNotFoundException은 Service가 판단한 비즈니스 실패입니다. 그리고 이 예외는 GlobalExceptionHandler에서 404 Not Found 응답으로 바뀌어야 합니다.

흐름을 연결하면 이렇게 됩니다.

text
Controller
  -> Service 호출
    -> Repository에서 게시글 찾기
      -> 없음
    -> PostNotFoundException 발생
  -> GlobalExceptionHandler가 잡음
  -> 404 + ErrorResponse 반환

AI 코드 리뷰에서는 이 연결이 끊겨 있지 않은지 확인해야 합니다.

  • Service가 커스텀 예외를 던지는가?
  • 그 예외를 전역 핸들러가 처리하는가?
  • 상태 코드가 상황에 맞는가?
  • 사용자에게 보여 줄 메시지와 개발 로그가 섞이지 않는가?

9. 검증 실패를 테스트하지 않으면 실제 화면에서 발견된다

AI가 만든 코드가 겉으로 보기에는 그럴듯해도, 실패 케이스 테스트가 없으면 중요한 버그가 남기 쉽습니다.

예를 들어 게시글 작성 API의 성공 테스트만 있으면 이런 문제를 놓칠 수 있습니다.

  • 빈 제목이 저장된다.
  • 너무 긴 제목이 저장된다.
  • 없는 카테고리 ID로 저장하려다 DB 오류가 난다.
  • 검증 실패 응답이 프론트엔드가 기대한 모양과 다르다.
  • 상태 코드가 400이어야 하는데 500이 나온다.

Spring Boot에서는 Controller 테스트에서 이런 실패를 확인할 수 있습니다.

java
@Test
void 제목이_비어있으면_400을_반환한다() throws Exception {
    mockMvc.perform(post("/api/posts")
            .contentType(MediaType.APPLICATION_JSON)
            .content("""
                {
                  "title": "",
                  "content": "본문",
                  "categoryId": 1
                }
                """))
        .andExpect(status().isBadRequest())
        .andExpect(jsonPath("$.code").

이 테스트를 직접 다 작성할 필요는 없습니다. 하지만 AI가 테스트를 만들어 줬다면 읽을 수 있어야 합니다.

읽는 포인트는 네 가지입니다.

text
어떤 요청을 보냈는가?
어떤 잘못된 값을 넣었는가?
어떤 상태 코드를 기대하는가?
응답 JSON의 어떤 필드를 확인하는가?

테스트 이름이 한국어든 영어든 핵심은 같습니다. 실패 케이스가 테스트에 포함되어 있는지 확인해야 합니다.


10. AI가 자주 놓치는 에러 처리 문제

AI가 만든 Spring Boot 코드에서 자주 보는 문제를 체크리스트처럼 정리해 보겠습니다.

1) DTO에는 검증이 있는데 Controller에 @Valid가 없다

DTO에 @NotBlank가 있어도 Controller에서 검증을 실행하지 않으면 기대한 대로 동작하지 않을 수 있습니다.

확인 질문:

text
@RequestBody 앞이나 요청 DTO 앞에 @Valid가 있는가?

2) 모든 예외를 RuntimeException으로 던진다

java
throw new RuntimeException("게시글을 찾을 수 없습니다.");

이렇게만 되어 있으면 전역 핸들러에서 어떤 상태 코드로 바꿔야 할지 구분하기 어렵습니다.

확인 질문:

text
PostNotFoundException, DuplicateEmailException처럼 의미 있는 예외 타입이 있는가?

3) DB 예외 메시지를 사용자에게 그대로 보여 준다

DB 내부 메시지에는 테이블명, 컬럼명, 제약조건 이름 같은 정보가 들어갈 수 있습니다. 사용자에게 그대로 보여 줄 필요가 없습니다.

확인 질문:

text
내부 예외 메시지를 그대로 response.message에 넣고 있지 않은가?

4) 에러 응답 모양이 API마다 다르다

프론트엔드는 에러 응답 모양이 일정해야 공통 처리 코드를 만들 수 있습니다.

확인 질문:

text
실패 응답이 항상 ErrorResponse 또는 같은 형식으로 내려오는가?

5) 필드별 검증 메시지가 사라진다

검증 실패는 필드별 안내가 중요합니다. 그런데 전역 핸들러가 모든 검증 실패를 "잘못된 요청입니다" 하나로만 바꾸면 화면에서 구체적인 안내를 하기 어렵습니다.

확인 질문:

text
fields 배열 또는 fieldErrors 같은 구조로 어떤 필드가 문제인지 내려오는가?

6) 인증 실패와 권한 실패를 섞는다

로그인하지 않은 사용자는 401, 로그인했지만 권한이 없는 사용자는 403으로 나누는 것이 보통입니다.

확인 질문:

text
토큰 없음/만료와 권한 부족을 구분하는가?

11. 프론트엔드 관점에서 에러 처리를 읽는 방법

진규가 프론트엔드 작업을 하면서 백엔드 코드를 리뷰해야 한다면, 에러 처리는 특히 화면과 연결해서 보면 좋습니다.

예를 들어 프론트엔드 코드가 이런 응답을 기대한다고 해 봅시다.

ts
type ApiError = {
  code: string;
  message: string;
  fields?: { field: string; message: string }[];
};

그런데 백엔드가 실제로는 이렇게 돌려주면 문제가 생깁니다.

json
{
  "errorCode": "VALIDATION_ERROR",
  "errorMessage": "입력값을 확인해 주세요."
}

의미는 비슷하지만 이름이 다릅니다. 프론트엔드의 공통 에러 처리 코드는 code와 message를 찾는데, 백엔드는 errorCode와 errorMessage를 보내고 있습니다.

이런 문제는 백엔드 문법을 몰라도 잡을 수 있습니다. API 계약 관점에서 보면 됩니다.

text
프론트엔드 타입 이름과 백엔드 JSON 필드 이름이 같은가?
필드별 에러 배열 이름이 같은가?
상태 코드별로 프론트엔드 분기와 백엔드 응답이 맞는가?

에러 응답은 성공 응답보다 덜 신경 쓰기 쉽지만, 실제 사용자는 에러 상황에서 더 많은 안내를 필요로 합니다.


12. 짧은 리뷰 루틴: 실패 요청 하나를 끝까지 따라가기

긴 백엔드 코드를 처음부터 끝까지 읽으려고 하면 힘듭니다. 대신 실패 요청 하나를 정해서 따라가면 구조가 보입니다.

예를 들어 "빈 제목으로 게시글 작성" 요청을 따라갑니다.

text
1. POST /api/posts로 요청이 들어온다.
2. Controller가 CreatePostRequest를 받는다.
3. @Valid가 CreatePostRequest의 @NotBlank를 실행한다.
4. title이 비어 있어서 MethodArgumentNotValidException이 발생한다.
5. GlobalExceptionHandler가 예외를 잡는다.
6. ErrorResponse(code=VALIDATION_ERROR, fields=[title...])를 만든다.
7. HTTP 400으로 프론트엔드에 반환한다.
8. 프론트엔드는 title 입력칸 아래에 메시지를 보여 준다.

이 흐름 중 하나라도 빠지면 실제 화면에서 어색한 버그가 생길 수 있습니다.

  • @Valid가 빠지면 저장 로직까지 들어갈 수 있습니다.
  • 전역 핸들러가 없으면 기본 에러 응답이 내려올 수 있습니다.
  • 필드별 메시지가 없으면 화면에서 구체적인 안내를 못 합니다.
  • 상태 코드가 틀리면 프론트엔드의 공통 에러 분기가 잘못 동작할 수 있습니다.

AI에게 백엔드 코드를 맡겼다면, 이런 식으로 대표 실패 케이스를 하나씩 추적해 달라고 시키는 것도 좋습니다.


13. AI에게 시킬 수 있는 좋은 검토 요청

백엔드 코드를 생성한 뒤 AI에게 막연히 "에러 처리 괜찮아?"라고 묻기보다, 조금 더 구체적으로 요청하면 결과가 좋아집니다.

예시 프롬프트입니다.

text
이 Spring Boot API에서 게시글 작성 요청의 검증/에러 흐름을 검토해 줘.
특히 아래를 확인해 줘.

1. 요청 DTO에 필수값/길이 검증이 있는지
2. Controller에서 @Valid가 실제로 적용되는지
3. 검증 실패가 400 + 일관된 ErrorResponse로 내려가는지
4. 존재하지 않는 categoryId가 404 또는 적절한 비즈니스 에러로 처리되는지
5. 프론트엔드가 필드별 메시지를 표시할 수 있는지
6. 실패 케이스 테스트가 있는지

문법 설명보다 실제 요청 흐름 기준으로 문제를 찾아 줘.

이런 요청은 "코드 예쁘게 고쳐 줘"보다 훨씬 실무적인 결과를 줍니다. AI가 만든 코드를 다시 AI로 검토할 때도 기준이 필요합니다.


14. 오늘의 체크리스트

AI가 만든 Spring Boot 백엔드에서 검증과 에러 응답을 볼 때는 아래 순서로 확인하면 됩니다.

text
[요청 DTO]
- 필수값에 @NotNull, @NotBlank 등이 있는가?
- 문자열 길이와 숫자 범위가 표현되어 있는가?
- 사용자 입력이 많은 API일수록 검증이 빠져 있지 않은가?

[Controller]
- 요청 DTO에 @Valid가 붙어 있는가?
- @RequestBody, @PathVariable, @RequestParam의 위치가 API 계약과 맞는가?

[Service]
- 없는 데이터, 중복, 권한 부족 같은 비즈니스 실패를 구분하는가?
- 의미 있는 커스텀 예외를 쓰는가?

[GlobalExceptionHandler]
- 검증 실패를 400으로 처리하는가?
- 비즈니스 예외를 상황에 맞는 상태 코드로 바꾸는가?
- 에러 응답 모양이 API마다 일관적인가?

[프론트엔드 연결]
- 에러 JSON 필드 이름이 프론트엔드 타입과 맞는가?
- 필드별 메시지를 화면에 표시할 수 있는가?

[테스트]
- 성공 케이스만 있는 것이 아니라 실패 케이스도 있는가?
- 상태 코드와 응답 JSON을 같이 검증하는가?

마무리

오늘은 백엔드의 검증과 에러 응답을 봤습니다. 이 주제는 문법보다 서비스 품질에 가깝습니다. 사용자가 잘못 입력했을 때 무엇을 알려 줄지, 프론트엔드가 어떤 기준으로 화면을 바꿀지, 개발자가 어떤 실패를 추적할 수 있을지가 모두 여기서 결정됩니다.

핵심은 네 가지입니다.

  1. 요청 DTO는 입력의 모양과 기본 규칙을 담는다.
  2. Controller의 @Valid는 그 규칙을 실제로 실행하게 한다.
  3. Service는 서비스 규칙 위반을 의미 있는 예외로 표현한다.
  4. 전역 예외 처리는 실패를 일관된 HTTP 상태 코드와 에러 응답으로 바꾼다.

다음 Day에서는 DB 접근을 읽기 위한 최소 지도를 잡겠습니다. Entity, Repository, JPA, 테이블, 연관관계가 어떤 식으로 연결되는지 보고, AI가 만든 DB 관련 코드에서 어디를 조심해야 하는지 살펴보겠습니다.

404
대상이 없음
없는 글/없는 페이지 안내
409현재 상태와 충돌이미 사용 중, 이미 처리됨 등 안내
500서버 내부 오류사용자에게 일반 오류 안내, 개발자는 로그 확인
(
PostNotFoundException
)
{
ErrorResponse response = ErrorResponse.of("POST_NOT_FOUND", ex.getMessage());
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(response);
}
}
value
(
"VALIDATION_ERROR"
)
)
;
}