
요즘 백엔드를 만지작 거리면서 계속 '이런 상황에서는 내가 어떤 상태코드로 리스폰스를 돌려보내야 하는 거지?'하는 의문이 들었다. 프론트 할 때는 크게 신경쓰지 않고 대충 숫자가 200대면 문제 없구나, 300대면 어디 다른 데로 가야하는 구나, 400대면 내가 문제가 있구나, 500대면 서버가 문제가 있구나 하면서 했는데, 내가 직접 돌려보내줘야 하는 순간이 찾아오니 한 번 제대로 짚고 넘어가야할 것 같은 느낌이 든다.
그래서 오늘은 자주 사용하게 될 상태 코드와 더불어 nestjs에서 각각을 다루는 메소드도 정리해보려 한다.
성공 응답
여기는 따로 nestjs 메소드가 없다. 아마도 각각의 orm이나 odm이 create update delelet find 등에 따라 알아서 상태 코드까지 리턴해주는 게 아닐까 싶다. 익스프레스에서는 res.status(201).send(data)의 형태 혹은 res.sendStatus(204)의 형태로 쓰이는 듯하다.
200 OK : 요청 성공. 주로 get 요청 혹은 patch와 put과 같은 업데이트 요청에 대한 상태 코드로 쓰인다.
201 Created : 요청의 결과로 새로운 리소스가 생성됨. post 요청 혹은 일부 put 요청에 대한 상태 코드로 쓰인다.
204 No Content : 요청에 대해서 보내줄 수 있는 콘텐츠가 없을 때. 주로 delete 요청에 대한 상태 코드로 쓰인다.
클라이언트 에러
400번대 에러는 클라이언트 쪽의 실수 혹은 문제로 인해 발생하는 에러를 모아두고 있다. 여기서부터는 nestjs 메소드가 있다. 사용 방법은 간단한데, 에러 이름 뒤에 Exception을 붙이는 것이다.
가령 로그인하지 않은 유저가 로그인해야 사용할 수 있는 유료 서비스에 접근한다면 1) 로그인도 안 되어있고 2) 돈도 안 냈지만 둘 중에 더 우선으로 확인하는 것은 403이 아닌 401이다. 따라서 throw new UnauthorizedException("로그인이 필요한 서비스입니다")를 던지면 된다.
400 Bad Request : 서버가 예상한 필드가 다 오지 않는 등 문법적으로 잘못된 요청일 때.
401 Unauthorized : 로그인 하지 않은 사용자가 로그인해야 하는 서비스에 접근할 때.
403 Forbidden : 권한이 없는 사용자가 권한이 필요한 서비스에 접근할 때.
404 Not Found : 미리 정한 필드 다 채워주고, 로그인도 하고, 권한도 있는데 서버에서 요청받은 리소스를 찾을 수 없을 때.
409 Conflict : 요청이 서버의 정책과 충돌될 때. 가령 닉네임은 Unique 필드인데, 누군가 이미 존재하는 닉네임으로 회원가입을 시도할 때.
418 I'm a teapot : 서버는 커피를 찻 주전자에 끓이는 것을 거절합니다.
서버 에러
500번대 에러는 클라이언트 쪽에서 문제 없이 요청을 보냈지만 서버의 문제로 인해 제대로 응답할 수 없는 경우 발생하는 에러를 모아두고 있다. 여기도 클라이언트 에러와 마찬가지로 nestjs 에러 처리 메소드를 사용할 수 있다.
500 Internal Server Error : 서버가 요청을 처리하는 방법을 알지 못할 때. (백엔드 개발자 잘못이다)
503 Service Unavailable : 서버가 요청을 처리할 준비가 되지 않은 상태
여담
나는 아마도 클라이언트 에러 쪽을 아주 자주 사용하게 될 것 같다. 이 글을 정리하면서 느낀 건데 특히 400번대 에러는 백엔드 개발자가 확인해야할 순서대로 번호가 매겨져있는 것 같다.
일단 클라이언트가 요청에 필요한 필드를 다 채워서 보내는 게 먼저고, 로그인이 되어있는지를 확인하고, 로그인 되어있더라도 권한이 있는지를 확인해야하며, 모든 게 다 완벽해도 서버에 필요한 리소스가 없을 수 있다(아마도 api params에 id 값을 잘못 넣어준 케이스가 많을 듯). 이 모든 게 다 제대로 들어왔다 해도 위의 닉네임 예시처럼 서버의 정책상 클라이언트의 요청을 수행해줄 수 없는 경우가 있을 것이다.
필드도 다 채워지고 로그인 후 권한이 존재하고 서버에 리소스가 있으며 서버 정책도 요청을 만족하지만, 서버가 커피를 찻 주전자에 끓이는 것을 거절할 지도 모르는 일이다.
더 읽어보기
2026.04.11
Trie 자료구조
문자열 데이터를 다룰 때 단순히 “이 단어가 있나?”만으로는 부족한 순간이 있다. 자동 완성처럼 특정 접두사로 시작하는 후보를 모아야 할 때도 있고, 어떤 키에 값을 두고 빠르게 찾고 싶을 때도 있다. 이럴 때 가장 자연스럽게 떠올릴 수 있는 자료구조가 바로 Trie이다. Trie는 무…
2026.03.04
JavaScript를 위한 더 나은 Streams API가 필요하다
이 포스트는 node.js의 코어 컨트리뷰트이며 Cloudflare Workers 팀 소속 개발자 James M Snell이 cloudflare 블로그에 올린 We deserve a better streams API for JavaScript 게시글을 번역한 것이다. 번역하는 과정에서…
2026.03.01
함수, 펑터, 그리고 모나드
복잡한 버그는 대개 거대한 기능이 아니라 사소한 데이터 변환 구간에서 시작된다. 문자열을 한 번 다듬고, 숫자를 한 번 바꾸고, 그 결과를 다음 단계로 넘기는 단순한 흐름이다. 그런데 조건이 조금씩 추가되는 순간 로직은 빠르게 복잡해진다. 값만 바꾸던 코드가 어느새 값의 부재, 비동기…
2026.01.15
Static Hermes로 JavaScript를 C 코드로 컴파일하기
이 포스트는 parcel의 메인테이너 Devon Govett가 자신의 블로그에 올린 How to compile JavaScript to C with Static Hermes 게시글을 번역한 것이다. 번역하는 과정에서 다소 의역이 있을 수 있으며, 일부 번역에는 사견이 포함되어있기도 하다…
2026.06.01
React Server Components를 위한 컴포넌트 아키텍처
이 포스트는 Vercel의 Next.js 팀 소속 개발자 Aurora Scharff가 자신의 블로그에 올린 Component Architecture for React Server Components 게시글을 번역한 것이다. 번역하는 과정에서 다소 의역이 있을 수 있으며, 일부 번역에는…
2026.05.26
차트는 멈췄는데 윈도우가 움직인다
상황 어느날 서비스를 살펴보시던 팀장님께서 이런 말씀을 slack에 남기셨다. 진호님, 예측 차트에서 zoom을 계속하면 어느 순간 라인 차트가 아니라 단일 스캐터 차트처럼 보이는 데, 이거 수정하면 좋을 거 같아요. 어느정도 zoom을 하면 그 이후로는 zoom이 안 되도록 할 수 없…
2026.05.21
피자가게로 이해하는 디자인 패턴
에이든 피자는 처음부터 복잡한 시스템을 만들 생각이 없었다. 처음에는 메뉴 몇 개만 만들면 됐다. 그런데 손님은 커스텀 주문을 넣기 시작했고, 주방은 상태를 나눠야 했고, 결제와 배달앱과 알림이 하나씩 붙었다. 코드도 가게를 닮는다. 장사가 잘될수록 이상하게 더 쉽게 망가진다. 디자인…
2026.05.21
7. Decorator — 토핑 추가할 때마다 클래스를 새로 만들 수 없다
에이든 피자에서 주문서를 객체로 만들자 취소와 재주문은 한결 편해졌다. 그런데 주문이 편해지자 손님들도 한결 편해졌다. 편해진 손님은 더 많은 요구를 한다. "치즈 추가요", "올리브도 추가요", "소스 많이요", "조금 더 바삭하게 구워주세요" 같은 요청이 주문대 위로 쌓이기 시작했다…
댓글
댓글을 불러오는 중...