예외 처리 실전 적용 in Spring

Gihongg·2024년 3월 22일

Spring Boot

목록 보기
11/24

서론

예외 처리의 필요성

서버는 Request(요청)에 대한 Response(응답)를 반환해준다.

각 서버마다 정해진 응답의 API 규격을 지키기 위해 예외 처리가 필요하다.

정상적인 응답은 괜찮지만 에러로 인해 예외적인 응답이 반환되고, 그로인해 규격에 맞지 않는 응답이 클라이언트에게 도착하게된다면 Parsing에 문제가 생기게 된다.

그렇기 때문에 우리 서버가 항상 동일한 규격의 응답을 해줄 수 있도록 예외처리를 해주어야 하는 것이다.

실전 적용

사전 코드

UserResponse 클래스

package org.example.exception.model;

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UserResponse {
    private String name;
    private String id;
    private Integer age;

}

Api 클래스

package org.example.exception.model;


import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Data
@JsonNaming(value = PropertyNamingStrategies.SnakeCaseStrategy.class)
@Builder
public class Api<T> {

    private String resultCode;
    private String resultMessage;
    private T data;
}

RestController 코드

package org.example.exception.Controller;

import org.example.exception.model.Api;
import org.example.exception.model.UserResponse;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;


@RestController
@RequestMapping("/api/user")
public class UserApiController {

    private static List<UserResponse> userList=List.of(
            UserResponse.builder()
                    .id("1")
                    .age(20)
                    .name("홍길동")
                    .build()
            ,
            UserResponse.builder()
                    .id("2")
                    .age(22)
                    .name("유관순")
                    .build()

    );


    @GetMapping("/id/{userID}")
    public Api<UserResponse> getUser(
            @PathVariable String userID
    ){



        var user = userList.stream()
        .filter(it->it.getId().equals(userID))
        .findFirst().get();

        Api<UserResponse> response=Api
                .<UserResponse>builder()
                .resultCode(String.valueOf(HttpStatus.OK.value()))
                .resultMessage(HttpStatus.OK.name())
                .data(user)
                .build();

    return response;
    }
}

실행 후

이렇게 작성을 한 후 스프링을 실행시키고 http://localhost:8080/api/user/id/1
GET요청을 날리면 아래와 같은 응답이 나온다.

{
"result_code": "200",
"result_message": "OK",
"data":{
"name": "홍길동",
"id": "1",
"age": 20
}
}

하지만 http://localhost:8080/api/user/id/99 에 GET요청을 날리면

body에 어떠한 값도 응답되지 않는다.

해결법

전역적인 예외처리를 위해 예외처리 자바 파일을 하나 만들고
그 안을 아래의 코드로 작성한다.

package org.example.exception.exception;


import lombok.extern.slf4j.Slf4j;
import org.example.exception.model.Api;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.NoSuchElementException;

@Slf4j
@RestControllerAdvice(basePackages = "org.example.exception.Controller")   //RestApi가 사용되는 곳에 예외가 발생하는 것을 감지하는 어노테이션이다.
public class RestApiExceptionHandler {


    @ExceptionHandler(value = NoSuchElementException.class)
    public ResponseEntity<Api<Object>> noSuchElement(
            NoSuchElementException e
    ){
        log.error("",e);

        var response= Api.builder().resultCode(String.valueOf(HttpStatus.NOT_FOUND.value()))
                .resultMessage(HttpStatus.NOT_FOUND.getReasonPhrase())
                .build();


        return ResponseEntity
                .status(HttpStatus.NOT_FOUND)
                .body(response);
    }

}

이와 같이 특정한 예외 상황일 때 응답을 정해줄 수 있다.

그리고 잘못된 요청이 들어온다면 아래의 응답을 반환한다.

{
"result_code": "404",
"result_message": "Not Found",
"data": null
}

profile
전천후 개발자

0개의 댓글