API 개발을 하다 보면 클라이언트 요청을 어떻게 처리할지, 특히 실패했을 때 어떤 HTTP 상태 코드를 반환할지 고민할 때가 많다.
현재는 대부분이 400 으로 응답하고 있다. 이번에 여러 상황을 정리해보면서 어떤 코드를 써야 하는지 생각해봤다.

1. 필수 파라미터가 없을 때

API 호출할 때 필수 값이 빠졌다. (ex. Id)

서버에서 이걸 검증하고 걸러낸다면?

이건 클라이언트가 잘못 보낸 요청이다. API 문제라기보다는, 잘못된 요청을 서버가 빠르게 걸러낸 것.

이렇게 잘못된 요청 파라미터로 인해 서버가 요청을 처리할 수 없는 경우.

400 Bad Request 이 적절하다고 생각한다.

2. 비즈니스 로직에서 막히는 경우

요청은 잘 왔는데, 서버 비즈니스 로직 상 허용할 수 없는 경우다. 아마도 가장 빈번한 케이스!

(ex. 비밀번호 변경 API에서 “최근 3회 사용한 비밀번호는 안 된다” 같은 규칙.)

이건 두 가지로 나눠볼 수 있다.

  • 403 Forbidden
    규칙상 금지된 행위 (ex: 그 비밀번호는 사용 금지)

  • 409 Conflict
    현재 상태와 충돌 발생 (ex: 비밀번호가 과거 기록과 충돌)

권한 문제로 보면 403, 상태 충돌로 보면 409를 쓰는 게 적절해보인다. 이건 생각하기 나름인듯하다.

3. 데이터 중복

저장 요청에서 데이터가 중복인 경우로 요청은 문제없지만, 서버 상태와 충돌이 발생한 경우다.

예를들면 아래 같은 경우다.

  • 중복된 username, email, ID
  • optimistic locking에서 버전 충돌

GPT느 409 Conflict 를 사용하라고 한다.

데이터 중복은 현재 상태와 충돌로 보는듯하다.

정리해보자

상황 추천 HTTP Status
잘못된 요청 파라미터, 누락 400 Bad Request
비즈니스 규칙 위반 403 Forbidden 또는 409 Conflict
중복 데이터 (예: 이메일 중복) 409 Conflict

혼자 작업하는게 아니고 상태값에 대한 서로의 의견도 조금씩은 달라서 참 어렵다.

상태값을 고를 땐

  • 문제의 원인이 클라이언트 쪽인가, 서버 쪽인가?
  • 어떤 종류의 오류인가?

이걸 잘 구분해야 한다.
괜히 500 같은 서버 에러로 잘못 응답하면, 클라이언트는 API가 고장난 줄 오해할 수 있다.