티스토리 뷰

Spring

[Spring] Http 상태 코드 204(No Content)

heemang.dev 2024. 3. 17. 00:15

 

Http 상태 코드 204 - No Content

클라이언트가 요청한 정보를 전달받고, 이를 정상적으로 처리한다. 보통이라면 요청 내용을 처리한 응답 값을 클라이언트에 반환한다.

그러나 Http Method로 Delete를 사용한 경우에는 그렇지 않다. 예를 들어, 사용자가 1번 게시물을 삭제 요청을 하면 서버는 해당 게시물을 삭제한다. 서버는 게시물을 삭제하고 어떤 값을 반환해야할까? 아무리 생각해도 반환할 정보가 없다.(= Http Response Body가 없다) 왜냐하면 요청 자원을 삭제했기 때문에 서버에 저장된 자원이 존재하지 않기 때문이다.

 

따라서 이러한 경우에는 응답 상태 코드 204를 사용하는 것이 맞다고 생각한다. 이에 맞춰 코드를 개선해보겠다.

Service

기존 코드

기존 코드의 경우 반환 타입으로 DeleteSectionResponseDto를 반환하고 있다.

@Transactional
public DeleteSectionResponseDto deleteSection(Long sectionId) {
    Section findSection = sectionRepository.findById(sectionId)
        .orElseThrow(() -> new NoSuchElementException("section이 조회되지 않습니다."));
    sectionRepository.delete(findSection);
    return new DeleteSectionResponseDto(sectionId);
}

 DTO의 경우 id 필드만 가지고 있는데 생각해보면 삭제된 리소스의 id를 반환할 필요가 없다. 즉, DTO를 사용할 이유가 없다.

@Getter
@AllArgsConstructor
public class DeleteSectionResponseDto {

    private Long id;
}

따라서 변경 코드에는 DTO를 사용하지 않을 것이다.

변경 코드

DTO를 사용하지 않게 됨에 따라 반환 타입을 void로 변경하였다.

@Transactional
public void deleteSection(Long sectionId) {
    Section findSection = sectionRepository.findById(sectionId)
        .orElseThrow(() -> new NoSuchElementException("section이 조회되지 않습니다."));
    sectionRepository.delete(findSection);
}

 

Controller

컨트롤러는 Service 레이어에 의존하고 있다. 즉, 빈을 주입받아 SectionService를 사용하고 있다.

기존 코드

기존에는 SectionService가 삭제 응답 값으로 DeleteSectionResponseDTO 타입의 데이터를 반환하였다. 

@DeleteMapping("/{sectionId}")
public ApiResponse<DeleteSectionResponseDto> deleteSection(@PathVariable("id") Long sectionId) {
    DeleteSectionResponseDto response = sectionService.deleteSection(sectionId);
    return ApiResponse.successResponse(HttpStatus.OK, response);
}

변경 코드

그러나 SectionService가 void로 반환하는 것으로 바뀜에 따라, 컨트롤러 또한 이에 맞춰서 사용한다. 

// 특정 섹션 삭제
@DeleteMapping("/{sectionId}")
public ApiResponse<Void> deleteSection(@PathVariable("id") Long sectionId) {
    sectionService.deleteSection(sectionId);
    return ApiResponse.successResponse(HttpStatus.NO_CONTENT, null);
}

ApiResponse는 프론트엔드에 응답할 데이터 포맷을 정형화시킨 클래스이다.

 

@Getter
public class ApiResponse<T> {

    private int code; // 처리 코드
    private String message; // 예외 시에 전송 할 예외 메시지
    private T data; // 정상처리 시에 전송 할 데이터

    @Builder
    public ApiResponse(int code, String message, T data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> ApiResponse<T> successResponse(HttpStatus status, T data) {
        return ApiResponse.<T>builder()
            .code(status.value())
            .message(null)
            .data(data)
            .build();
    }

    public static <T> ApiResponse<T> errorResponse(HttpStatus status, String message) {
        return ApiResponse.<T>builder()
            .code(status.value())
            .message(message)
            .data(null)
            .build();
    }
}
Total
Today
Yesterday
최근에 올라온 글
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30