2026.03.18

ErrorCode는 어떻게 설계해야 할까?

이전 글에서 예외 처리 구조를 정리하면서

ErrorCode를 Enum으로 관리하는 방식을 사용했다.

근데 막상 적용해보니까 느낀 건 하나였다.

👉 단순히 enum으로 만드는 게 중요한 게 아니라

👉 “에러 코드를 어떻게 설계할 것인가”가 더 중요했다.


왜 에러 코드가 필요할까?

처음에는 그냥 메시지만 내려줘도 된다고 생각했다.

{
  "message":"유저를 찾을 수 없습니다."
}

하지만 이 방식에는 분명한 문제가 있었다.

  • 프론트에서 문자열로 분기해야 한다 (비효율)
  • 메시지가 바뀌면 로직도 같이 깨진다
  • 어떤 종류의 에러인지 명확하지 않다

특히 협업하면서 느낀 건

👉 “메시지는 사람이 보는 용도고, 로직은 코드로 처리해야 한다” 는 점이었다.

그래서 단순 메시지가 아니라

👉 코드 기반으로 에러를 구분해야겠다고 생각했다.


내가 고민했던 설계 기준

에러 코드를 설계하면서 몇 가지 기준을 세웠다.


1. 도메인 단위로 나누기

USER_001
POST_003
CATEGORY_004

이렇게 도메인 prefix를 붙였다.

→ 이유

  • 어디서 발생한 에러인지 바로 알 수 있고
  • 도메인별로 관리하기 쉬워진다

👉 나중에 에러가 많아져도 정리가 잘 된다.


2. HTTP 상태코드와 함께 관리

USER_NOT_FOUND(404,"USER_001","유저를 찾을 수 없습니다.")

단순히 코드만 있는 게 아니라

  • 상태코드
  • 에러 코드
  • 메시지

를 하나로 묶어서 관리했다.

이렇게 하니까

👉 예외 하나만으로 응답 전체를 구성할 수 있게 됐다.


3. 에러 유형을 명확하게 구분하기

상태코드를 대충 쓰지 않고 기준을 정했다.

  • 400 → 잘못된 요청 (validation, 입력값)
  • 401 / 403 → 인증 / 권한 문제
  • 404 → 리소스 없음
  • 409 → 중복, 충돌

예를 들어

DUPLICATED_EMAIL(409, "USER_004", "이미 사용 중인 이메일입니다.")

👉 “중복”을 400으로 처리할 수도 있었지만

→ **의미적으로 더 맞는 409(CONFLICT)**로 분리했다.

이렇게 기준을 잡아두니까

나중에 에러를 추가할 때도 고민이 줄어들었다.


4. Validation 에러는 따로 처리

Validation은 일반 예외와 다르게 처리했다.

이유는 하나였다.

👉 어떤 필드에서 문제가 발생했는지 알려줘야 하기 때문

그래서 응답에 field를 포함시켰다.

{
  "status":400,
  "message":"제목은 공백일 수 없습니다.",
  "field":"title"
}

이걸 적용하고 나서

👉 프론트에서 에러 위치를 바로 표시할 수 있게 됐고

👉 UX도 훨씬 좋아졌다.


설계하면서 느낀 점

처음에는

👉 “에러 코드까지 이렇게 나눠야 하나?” 싶었는데

막상 적용해보니까 완전히 달랐다.

  • 에러가 훨씬 명확해졌고
  • 프론트와의 소통이 쉬워졌고
  • 유지보수가 훨씬 편해졌다

정리

이번에 ErrorCode를 설계하면서 느낀 건 하나였다.

👉 에러 코드는 단순한 값이 아니라, API와 프론트 사이의 약속이다.