조회수: 91

422 Unprocessable Content 해결

422 Unprocessable Content는 본문이 파싱은 됐지만 서버 검증에 실패한 것입니다. 필드 오류를 읽고 400·415와 구분해 고칩니다. 무료 즉시 진단으로 바로 확인.

내 도메인에 이 문제가 있는지 지금 확인

무료, 가입 불필요. 이 가이드가 다루는 항목을 바로 검사하고 조치 방법을 알려드립니다.

Problem

POST·PUT·PATCH422 Unprocessable Content로 돌아옵니다. 엔드포인트는 존재하고, 인증도 되고, Content-Type도 맞고, JSON도 유효합니다 — 린터에 붙여넣으면 깨끗하게 파싱됩니다. 서버가 본문을 읽고, 이해하고, 그런데도 거부했습니다. 내용 중 뭔가가 규칙에 걸린 겁니다.

Symptoms

  • 같은 리소스에 GET은 200인데 쓰기 요청이 422를 반환합니다.
  • 응답 본문에 스택 트레이스가 아니라 필드 오류 목록이 담겨 있습니다 — "email": ["is invalid"], "errors": {...}.
  • 값 하나만 바꾸면 똑같은 페이로드가 통과합니다. 형식은 멀쩡하고 특정 필드가 범인이란 뜻입니다.
  • Rails 백엔드에서 폼 POST가 본문에 필드 오류 없이 422를 반환합니다 — 검증 상태 코드를 뒤집어쓴 CSRF 토큰 문제입니다.

What 422 Actually Means

RFC 9110(§15.5.21)은 422를 서버가 “요청 콘텐츠의 콘텐츠 타입”을 이해하고 “요청 콘텐츠의 문법이 올바르다”고 판단했지만 “담긴 지시를 처리할 수 없는” 것으로 정의합니다. 세 절을 순서대로 읽으세요: 미디어 타입이 받아들여졌고, 본문이 파싱됐고, 그다음에야 처리가 실패했습니다. 그 순서가 진단입니다. 422는 당신의 요청이 애플리케이션의 검증 계층까지 다 도달한 뒤에 거절됐다는 증거입니다.

이 코드는 알아둘 만한 혼란스러운 역사가 있습니다. WebDAV(RFC 4918 §11.2)에서 “Unprocessable Entity”로 태어났고, 그래서 옛 프레임워크와 MDN 옛 문서, Stack Overflow 답변 절반이 아직도 그렇게 부릅니다. RFC 9110이 이걸 핵심 HTTP 시맨틱스로 승격시키고 “Unprocessable Content”로 개명했습니다. 같은 코드, 같은 의미 — 인터넷이 15년간 명사 하나로 다퉜을 뿐입니다.

실무적 결론: 422는 입력이 형식은 잘 갖춰졌지만 비즈니스 규칙이나 검증 규칙을 깬 경우에 프레임워크가 꺼내 드는 코드입니다. Laravel은 ValidationException이 JSON을 기대하는 요청을 만나면 자동으로 422를 반환합니다. Django REST Framework와 FastAPI도 스키마 위반에 똑같이 합니다. Rails는 실패한 save의 관용적 응답으로 422 Unprocessable Entity를 씁니다. 422가 보이면 서버도 당신의 문법도 망가지지 않았습니다. 데이터가 규칙을 통과 못 했을 뿐입니다.

Top 3 Causes

  1. 필드 수준 검증 실패 - 압도적 1위. 필수 필드 누락, 너무 긴 문자열, 범위를 벗어난 숫자, 형식에 안 맞는 이메일, 허용 목록에 없는 enum 값. 프레임워크의 검증기(Laravel의 validate(), DRF 시리얼라이저, Pydantic 모델, ActiveModel 검증)가 파싱된 본문을 스키마에 비춰보고 안 맞는 첫 항목을 거부합니다. 좋은 소식: 응답 본문이 거의 항상 정확한 필드와 깨진 규칙을 알려줍니다. 뭘 하기 전에 그것부터 읽으세요.

  2. 의미·비즈니스 규칙 위반 - 문법도 멀쩡하고 필드도 개별적으론 다 유효한데, 요청이 현재 상태나 도메인 규칙에 비춰 말이 안 됩니다. 존재하지 않는 customer_id를 참조했습니다. start_dateend_date보다 뒤로 잡았습니다. 재고보다 많은 수량을 주문했습니다. 상호 배타적인 두 필드를 둘 다 넣었습니다. 잘못된 형식은 없습니다 — 조합이 불가능할 뿐이고, 서버가 그걸 실행하길 거부합니다.

  3. 오래됐거나 없는 CSRF·위조 방지 토큰 (Rails 계열) - 이건 데이터 문제로 위장합니다. 위조 방지를 처리 가능성 검사로 취급하는 프레임워크 — Rails가 대표적 — 는 토큰이 틀리거나 없으면 422로 답합니다. 필드는 흠잡을 데 없는데, 위조 방지 토큰이 만료됐거나, 안 보내졌거나, 로그인 후 갱신 안 돼서 요청이 거부됩니다. 서버 렌더링 백엔드에 자바스크립트 클라이언트를 붙이는 사람들이 여기 끊임없이 걸려서, 애초에 문제가 아니었던 필드 값을 한 시간씩 감사합니다.

Diagnose with DechoNet

  • HTTP 진단으로 라우트 자체가 건강한지 확인하고 엔드포인트가 깨끗한 요청에 반환하는 정확한 상태 줄을 보세요. 422는 특정 본문을 가진 특정 쓰기 하나에 묶여 있으므로, 중립적 진단은 보통 200이나 405로 돌아옵니다 — 그리고 그 갈림이 핵심입니다. 엔드포인트가 평범한 요청에 정상 응답한다면, 422는 망가진 배포가 아니라 당신의 페이로드 대 서버의 규칙에 있습니다. 라우트가 살아 있는 걸 확인했다면, 진짜 답은 422 응답 본문에 있습니다: 서버가 돌려준 필드 오류 목록을 읽으세요.

Resolution Checklist

  • 응답 본문을 먼저 읽으세요. 422는 거의 항상 뭐가 실패했는지 구조화된 목록 — 필드 이름과 규칙 이름 — 을 담고 있습니다. 이게 가장 빠른 해결 경로인데, 대부분은 이걸 건너뛰고 자기 JSON을 추측합니다.
  • 모든 필드를 API의 문서화된 스키마와 대조하세요: 필수 vs 선택, 기대 타입(서버가 숫자 5를 원하는데 문자열 "5"를 보낸 게 전형적 422), 허용 enum 값, 최소/최대 길이, 이메일·날짜 같은 형식 규칙.
  • 스키마가 못 잡는 의미 충돌을 확인하세요 — 존재하지 않는 참조 ID, 거꾸로 된 날짜 범위, 유니크·상태 규칙을 어긴 값. 이건 필드 검증은 통과하고 비즈니스 로직에서 실패합니다.
  • Rails(또는 유사) 백엔드이고 422 본문에 필드 오류가 없다면 CSRF 토큰을 의심하세요. 유효한 위조 방지 토큰을 보내거나, 토큰 인증 API라면 위조 방지가 폼 세션이 아니라 API 요청용으로 설정됐는지 확인하세요.
  • 변장한 400이 아닌지 확인하세요. 서버가 본문을 파싱조차 못 하면 — 깨진 JSON, 틀린 괄호, 잘린 페이로드 — 422가 아니라 400이 나옵니다. 422는 파싱이 성공했다는 증거이니 문법 디버깅은 멈추세요.
  • 문제된 필드나 규칙을 고치고, 다시 보내고, 엔드포인트가 2xx를 반환하는지 확인하세요.

When to Escalate

  • 정당한 클라이언트가 유효하다고 믿는 데이터에서 422를 맞고 있다면, 불일치는 클라이언트의 가정과 서버의 검증 규칙 사이에 있습니다 — 요청을 문서가 설명하는 스키마가 아니라 API가 실제로 강제하는 스키마와 비교하세요. 문서화된 스키마와 강제되는 스키마는 누구나 인정하는 것보다 자주 어긋납니다.
  • 필드 오류도 메시지도 없는 텅 빈 본문의 422가 나온다면, 그건 클라이언트가 아니라 서버 측 버그입니다. 검증 근거로 입력을 거부하면서 어느 필드가 실패했는지 안 알려주는 API는 지원 티켓 생성기입니다. 해결책은 RFC 9110의 의도대로 422 페이로드가 구체적 실패를 나열하게 만드는 겁니다.

관련 도구

관련 가이드

가이드 공유

[Ad] Guide Detail Inline
← 전체 가이드 보기