


404 Not Found, 502 Bad Gateway, 500 Server Error
아마 웹 서비스를 자주 사용하는 사람이라면 심심치 않게 봤을 법한 문구들일 것이다. 구글링을 해서 나온 페이지에 들어갔는데 이미 삭제되어 400번대 에러를 만나기도 하고, 큰 행사의 티켓팅이나 세일 기간이 되면 사이트에 접속자가 몰려 위처럼 500번대의 에러가 심심치 않게 터지는 걸 경험하게 된다.
일반 사용자의 입장에서는 모두 '오류'라는 단어로 정리되지만, 개발자에게는 각각의 HTTP Status Code들이 어떤 의미를 갖고 있으며 언제 어떻게 사용하는 것인지 정리해보았다.

요청을 받았음을 뜻하고 요청이 처리되는 동안 임시로 발행된다. 거의 사용되지 않는다.
200번대의 코드들은 클라이언트의 요청을 받았으며 수락되었음을 의미한다.
200 (OK) : 요청이 성공임을 의미한다.
201 (Created) : 요청이 성공적이며 결과적으로 리소스가 생성되었음을 의미한다.
202 (Accepted) : 요청은 접수되었으나 아직 처리가 완료되지 않았음을 의미한다. 이때 요청의 처리 결과는 보장되지 않는다. 이는 배치 처리(일괄 처리)를 할 때 주로 사용된다.
204 (No Content) : 요청이 성공적으로 이루어졌고 요청 처리 결과로 content 리턴이 없음을 의미한다.
300번대는 리다이렉트 관련 코드들이다. 이때 웹 브라우저는 300번대 응답의 결과로 Location 헤더가 있으면, 해당 위치로 자동 이동한다.
300 (Multiple Choices) : 서버가 요청에 따라 여러 조치를 선택할 수 있다. 잘 사용되지 않는다.
301 (Moved Permanently) : 리다이렉트 시 요청 메서드를 GET으로 변경하며, URI를 영구적으로 변경한다. 이때 본문이 제거될 수도 있다.
예시 ) http -> https 변경 (Google. “Secure your site with HTTPS”)
302 (Found) : 리다이렉트 시 요청 메서드를 GET으로 변경하며 일시적으로 이동한다. 이 경우에도 본문이 제거될 수도 있다.
302는 원래 "Moved temporarily"로 불렸으나 302 리다이렉트를 구현하며 method를 GET으로 변경하도록 하는 시도가 이뤄지며 303과 307로 나누어지게 되었다. 많은 서비스에서 리다이렉션 후 Get 메서드로 변경이 되는 상황이라면 302코드를 기본적으로 사용한다.
303 (See Other) : 302 코드의 기능
304 (Not Modified) : 리소스가 변경되지 않았음을 알린다. 이 경우 클라이언트에 이미 전송했던 리소스가 있으므로 재전송할 필요가 없다. 따라서 캐시를 사용해 리다이렉트하게 된다.
307 (Temporary Redirect) : 리다이렉트 시 일시적으로 이동한다. 하지만 요청 메서드와 본문을 유지한다.
308 (Permanent Redirect) : 리다이렉트 시 영구적으로 이동한다. 하지만 요청 메서드와 본문을 유지한다.
📌 참고 1
리다이렉션은 영구 / 일시 / 특수 리다이렉션이 있다.
- 영구 리다이렉트(Permanent Redirect) : 특정 리소스의 URI가 영구적으로 이동했음을 의미한다.
- 일시 리다이렉트(Temporary Redirect) : 리소스의 URI가 일시적으로 변경됐음을 의미한다.
- 특수 리다이렉트 : 304 코드의 상황과 같이 cache refresh 가 일어나는 경우가 포함된다.
📌 참고 2
PRG (Post Redirect Get) 패턴
Post 메서드로 들어온 요청을 Get 메서드로 Redirect하는 방식
이때 URL이 이미 Post에서 Get으로 리다이렉트를 통해 메서드 변경이 되었기 때문에 새로고침을 하여도 Post 요청이 재차 이루어지지 않는다.
PRG 패턴이 필요한 이유는 바로 이 부분에 있다. 예를 들어 어떠한 양식을 제출하거나 주문을 넣는 경우 일의 중복이 일어나면 문제가 생긴다. 이러할 때 PRG 패턴을 통해 안전성을 추구할 수 있다.
클라이언트 측의 문제로 인한 오류가 생겼음을 나타내는 코드다.
400 (Bad Request) : 클라이언트 측의 문제로 인해 요청을 서버가 처리할 수 없음을 의미한다.
401 (Unauthorized) : 코드의 이름은 Unauthorized지만 authentication(인증)의 문제로, 클라이언트가 해당 리소스에 대해 인증이 필요함을 알린다.
403 (Forbidden) : 서버가 클라이언트의 요청을 이해하였지만 승인을 거부한 경우 사용된다. 예를 들어 인증은 되었으나 접근 권한이 만족되지 않은 상황에 사용될 수 있다.
404 (Not Found) : 클라이언트가 요청한 리소스를 찾을 수 없는 상황을 나타낸다. 경우에 따라 리소스는 있으나 클라이언트에게 어떠한 이유로 숨길 때도 사용될 수 있다.
서버측의 문제로 인한 오류가 생겼음을 나타내는 코드다.
HTTP Status Code는 어떻게 사용할까?
자바에는 package org.springframework.http에 enum 타입으로 HTTP Status를 정의해놨다. 따라서 필요에 따라 위의 패키지를 import한 후 필요한 상태 코드를 HttpStatus.NOT_FOUND 와 같이 사용할 수 있다.
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
class CustomException extends RuntimeException {}
@ResponseStatus 어노테이션을 Exception, Controller 등에서 사용할 수 있다.
public ResponseEntity rs(){
...
return new ResponseEntity(HttpStatus.OK);
}
HttpEntity를 상속하는 ResponseEntity는 HttpHeader, HttpBody, HttpStatus를 나타낼 수 있다.
HTTP Status Code는 서비스를 개발하기 위해서만 사용되는 것이 아니다. 어떠한 오류나 문제가 생겼을 때 사용자에게 문제가 생겼음을 알려야하는데, 이때 상태 코드에 따라 문제 상황에 맞는 적절한 페이지를 포워딩을 해야한다.
404 Not Found라는 문구가 적혀있는 기본 오류 페이지가 나온다고 가정을 하면 생기는 문제가 몇가지 있다.
사용자 편의성을 고려하지 않는다.
사용자 입장에서는 어떤 문제인지 인식하기 어려우며, 언제 문제가 해결되어 서비스를 제공받을 수 있는지 등을 충분하게 표현하지 못한다.
보안적으로 취약점을 노출할 수 있다.
예를 들어 403 Forbidden 오류 페이지가 뜬다면 해당 페이지에 접근 권한이 부족하다는 의미가 되고, 이를 통해 admin만이 접근할 수 있는 중요한 정보가 있을 수 있음을 유추할 수 있다.

올리브영의 경우, Http status code를 숨기고 내부적으로 사용하는 에러 코드(A4, B2)와 함께 사용자에게 적절한 설명을 첨부한다. 이러한 오류 페이지는 위에서 언급한 문제를 해결한다.
이를 통해 서비스를 구현할 때에 필요한 Http status code의 종류와 어떤 식으로 처리해야할지를 정리해 보았다.
📗 참고 서적 📗
자바 ORM 표준 JPA 프로그래밍 (저자 김영한)
wikipedia-http status