[ZB_BOOK STUDY] 스프링 부트 핵심 가이드 (10)

Dreamer·2024년 4월 28일
0
post-thumbnail

📖 스프링 부트 핵심 가이드

: 스프링 부트를 활용한 애플리케이션 개발 실무


📝 목차

10장. 유효성 검사와 예외 처리

10-1. 일반적인 애플리케이션 유효성 검사의 문제점
10-2. Hibernate Validator
10-3. 스프링 부트에서의 유효성 검사
- 프로젝트 생성
- 스프링 부트용 유효성 검사 관련 의존성 추가
- 스프링 부트의 유효성 검사
- @Validated 활용
- 커스텀 Validation 추가

10-4. 예외 처리
- 예외와 에러
- 예외 클래스
- 예외 처리 방법
- 스프링 부트의 예외 처리 방식
- 커스텀 예외
- 커스텀 예외 클래스 생성하기


10장. 유효성 검사와 예외 처리

데이터를 사전 검증하는 작업 = 유효성 검사 또는 데이터 검증

10-1. 일반적인 애플리케이션 유효성 검사의 문제점

  • 계층별로 진행하는 유효성 검사는 검증 로직이 각 클래스별로 분산돼 있어 관리가 어려움
  • 검증 로직에 중복이 많아 여러 곳에 유사한 기능의 코드가 존재할 가능성 ⭕
  • 검증해야 할 값이 많다면 검증하는 코드가 길어진다 -> 코드가 복잡 & 가독성 저하

➡️ 문제 해결을 위해 java진영에서는 Bean Validation이라는 유효성 검사 프레임워크 제공

  • Bean Validation은 어노테이션을 통해 다양한 데이터를 검증하는 기능 제공

Bean Validation을 사용한다는 것은 유효성 검사를 위한 로직을 DTO 같은 도메인 모델과 묶어서 각 계층에서 사용하면서 검증 자체를 도메인 모델에 얹는 방식으로 수행
어노테이션을 사용한 검증 방식이기 때문에 코드의 간결함 유지도 가능

10-2. Hibernate Validator

: Bean Validation 명세의 구현체

스프링 부트에서는 Hibernate Validation를 유효성 검사 표준으로 채택
도메인 모텔에서 어노테이션을 통한 필드값 검증을 가능하게 도와준다.

10-3. 스프링 부트에서의 유효성 검사

프로젝트 생성

스프링 부트용 유효성 검사 관련 의존성 추가

spring-boot-starter-validation 의존성 추가

  • Maven 프로젝트인 경우 pom.xml 파일에 의존성 추가
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
  • Gradle 프로젝트인 경우 build.gradle 파일에 의존성 추가
dependencies {
   implementation 'org.springframework.boot:spring-boot-starter-validation'
}

스프링 부트의 유효성 검사

: 유효성 검사는 각 계층으로 데이터가 넘어오는 시점에 데이터에 대한 검사를 실시

스프링 부트 프로젝트에서는 계층 간 데이터 전송에 대체로 DTO객체를 활용하고 있기 때문에 유효성 검사를 DTO객체를 대상으로 수행하는 것이 일반적이다.

각 필드에 어노테이션 선언 ➡️ 각 어노테이션은 유효성 검사를 위한 조건을 설정

대표적인 어노테이션

✅ 문자열 검증

✅ 최댓값/최솟값 검증

✅ 값의 범위 검증

✅ 시간에 대한 검증

✅ 이메일 검증

✅ 자릿수 범위 검증

✅ Boolean 검증

✅ 문자열 길이 검증

✅ 정규식 검증

@Validated 활용

@Valid 자바에서 지원하는 어노테이션
@Validated 스프링에서 사용 가능 -> @Valid 어노테이션 기능을 포함
@Validated는 유효성 검사를 그룹으로 묶어 대상을 특정할 수 있는 기능이 있다.

  • 그룹을 지정해서 유효성 검사를 실시하는 경우
    @Validated 어노테이션에 특정 그룹을 설정하지 않은 경우
    : groups가 설정되지 않은 필드에 대해서 유효성 검사를 수행

    @Validated 어노테이션에 특정 그룹을 설정하는 경우
    : 지정된 그룹으로 설정된 필드에 대해서만 유효성검사를 수행

커스텀 Validation 추가

: 유효성 검사 어노테이션에서 제공하지 않은 기능을 사용해야 할 때,
ConstraintValidator와 커스텀 어코테이션을 조합해서 별도의 유효성 검사 어노테이션 생성 가능

동일한 정규식을 계속 쓰는 @Pattern 어노테이션의 경우가 가장 흔한 사례

ConstraintValidator 인터페이스를 구현하는 클래스를 생성
(---Validator : 클래스명)

implement ConstraintValidator<> {

}

➡️ Validator 클래스를 ConstraintValidator 인터페이스의 구현체로 정의
인터페이스를 선언할 때, 어떤 어노테이션의 인터페이스인지 타입을 지정

10-4. 예외 처리

: 자바에서는 try/catch, throw 구문을 활용해 처리한다.
스프링 부트에서도 예외 처리할 수 있는 기능을 제공한다!

예외와 에러

  • 예외(Exception)
    : 애플리케이션이 정상적으로 동작하지 못하는 상황

  • 에러 (Error)
    : 주로 자바의 가상머신에서 발생시키는 것으로 예외와 달리 애플리케이션 코드에서 처리할 수 있는 것이 거의 없다.
    발생 시점에 처리하는 것이 아니라 문제가 발생하지 않도록 예방해서 원천적으로 차단

    ➡️ 메모리 부족(OutOfMemory), 스택 오버플로(StackOverFlow) 등

예외 클래스

예외 클래스의 상속 구조

모든 예외 클래스는 Throwalbe 클래스를 상속받는다.
Exception 클래스는 다양한 자식 클래스를 가지고 있는데,
Checked Exception과 Unchecked Exception으로 구분할 수 있다.

Checked ExceptionUnchecked Exception
처리 여부반드시 예외 처리 필요명시적 처리를 강제하지 않음
확인 시점컴파일 단계실행 중 단계 (런타임 단계)
대표적인 예외 클래스IOException
SQLException
RuntimeException
NullPointerException
IllegalArgumentException
IndexOutOfBoundException
SystemException

✅ Checked Exception
: 컴파일 단계에서 확인 가능한 예외 ➡️ 예외 처리 반드시 필요

✅ Unchecked Exception
: 문법상 문제 ❌, 프로그램이 동작하는 도중 예기치 않은 상황으로 발생하는 예외

  • RuntimeException을 상속⭕ Exception 클래스 = Unchecked Exception
  • RuntimeException을 상속❌ Exception 클래스 = Checked Exception

예외 처리 방법 (크게 3가지 방법)

  • 예외 복구
    : 예외 상황을 파악해서 문제를 해결하는 방법
    ➡️ try/catch 구문

  • 예외 처리 회피
    : 예외가 발생한 시점에서 바로 처리하는 것이 아니라 예외가 발생한 메서드를 호출한 곳에서 예외처리를 할 수 있게 전가하는 방식
    ➡️ throw 키워드 사용으로 어떤 예외가 발생했는지 호출부에 내용을 전달

  • 예외 전환
    : 예외 복구 + 예외 처리 회피 적절하게 섞은 방식
    예외가 발생 ➡️ 호출부로 예외 내용 전달 && 적합한 예외 타입으로 전달

스프링 부트의 예외 처리 방식

: 예외를 복구해서 정상으로 처리하기 보다는
요청을 보낸 클라이언트에 어떤 문제가 발생했는지 상황을 전달하는 경우가 많다.

Why? 외부에서 들어오는 요청에 담긴 데이터를 처리하는 경우가 많다.

✅ 클라이언트에 오류 메세지를 전달하려면,
각 레이어에서 발생한 예외를 엔드포인트 레벨인 컨트롤러로 전달해야 한다.

전달받은 예외를 스프링 부트에서 처리하는 방식으로 크게 두 가지가 있다.

  • @(Rest)ControllerAdvice@ExceptionHandler를 통해 모든 컨트롤러의 예외를 처리
    (@ControllerAdvice대신 @RestControllerAdvice를 사용하면 결과값을 JSON 형태로 반환할 수 있다.)

  • ExceptionHandler를 통해 특정 컨트롤러의 예외를 처리

커스텀 예외 (Custom Exception)

  • 네이밍에 개발자 의도를 담을 수 있다 ➡️ 이름만으로도 예외 상황 짐작 가능
  • 개발자가 관리하기 수월
  • 예외 상황에 대한 처리 용이

커스텀 예외 클래스 생성하기

커스텀 예외는 만드는 목적에 따라 생성하는 방법이 다르다!

profile
Moving forward based on records

0개의 댓글