직접 만든 Response 객체 -> ResponseEntity<>로 변경

JsonResponse 클래스 및 RentResponse, ErrorResponse

public class JsonResponse {
    private final int status; // HTTP 상태 코드
    private final String message; // 에러 메시지
    @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
    private LocalDateTime timestamp = LocalDateTime.now(); // 에러 발생 시간
}

public class RentResponse extends JsonResponse {
    public RentResponse(int status, String message) {
        super(status, message);
    }
}

public class ErrorResponse extends JsonResponse {
    public ErrorResponse(int status, String message) {
        super(status, message);
    }
}

기존에 RestController에서 값을 전달할 때, 이런 식으로 객체를 만들어서 전달했었다. JsonResponse라는 클래스로 다형성도 구현해서 나름 만족하고 사용하고 있었다.

실제 사용은 아래와 같이 사용했다.

@PostMapping("/{bookId}/rent")
public RentResponse rent(HttpSession session, @PathVariable("bookId") Long bookId, HttpServletResponse response) {
    User user = (User) session.getAttribute("user");
    Book findBook = bookService.findBookById(bookId);

    if (user.rent(findBook)) {
        return new RentResponse(
                HttpServletResponse.SC_OK,
                "정상적으로 대출되었습니다."
        );
    }

    response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

    return new RentResponse(
            HttpServletResponse.SC_BAD_REQUEST,
            "대출되지 않았습니다."
    );
}

다형성 측면에서는 나쁘지 않았지만, 중간에 status를 세팅해주어야 하고, 정상 대출 및 반납시에는 상태 코드를 생략해도 되었다. 실제로 클라이언트에서 중요하게 받는 것은 status와 message 였다.

const rent = id => {
    fetch(`/books/${id}/rent`, {
        method : "POST",
        headers : {
            "Content-Type": "application/json",
        }
    })
        .then((res) => {
            if (!res.ok) {
                return res.json().then(body => {
                    throw new Error(`HTTP Error! status : ${body.status}, message : ${body.message}`)
                })
            }
            return res.json();
        })
        .then((data) => alert("결과 : " + data.message))
        .catch(error => alert(error.message));
};

강의를 듣다 보니, ResponseEntity 클래스를 사용하면, 좀 더 단순하게 세팅이 가능할 것 같았다. 그리고, status를 Response 객체에 넣는 것은 중복으로 불필요하게 값을 넘기는 것이었다. 단순히 http 상태 코드를 클라이언트에서 확인해서 처리하면 될 일이었다.

ResponseEntity<String> 으로 개선

그래서, ResponseEntity<String>을 반환하는 방법으로 개선했다.

@PostMapping("/{bookId}/rent")
public ResponseEntity rent(HttpSession session, @PathVariable("bookId") Long bookId) {
    User user = (User) session.getAttribute("user");
    Book findBook = bookService.findBookById(bookId);

    log.debug("rent by user={}", user);
    log.debug("rent findBook={}", findBook);

    if (user.rent(findBook)) {
        return new ResponseEntity<>("정상 대출 되었습니다.", HttpStatus.OK);

    }

    return new ResponseEntity<>("정상 대출 되지 않았습니다.", HttpStatus.BAD_REQUEST);
}

클라이언트에서도 보다 간결하게 메시지와 상태를 받아 처리할 수 있게 되었다.

const rent = id => {
    fetch(`/books/${id}/rent`, {
        method : "POST",
        headers : {
            "Content-Type": "application/json",
        }
    })
        .then((res) => {
            if (!res.ok) {
                return res.text().then(body => {
                    throw new Error(`HTTP Error! status : ${res.status}, message : ${body}`)
                })
            }
            return res.text();
        })
        .then((data) => alert("결과 : " + data))
        .catch(error => alert(error.message));
};

댓글

개발자  김철준

백엔드 개발자 김철준의 블로그입니다.

주요 프로젝트