Files
llm-wiki/raw/official-docs/rfc9110-http-semantics.md
T

171 lines
37 KiB
Markdown

---
title: RFC 9110 — HTTP Semantics (Idempotent Methods + 4xx Status Codes)
source_type: official-doc
url: https://www.rfc-editor.org/rfc/rfc9110
archive_url:
status: raw
confidence: high
tags: [http, rfc, idempotency, status-code, content-negotiation, ietf-standards-track, outbound-http, api-contract]
related_projects: []
related_branches: [feature-outbound-http-client-baseline, feature-api-contract-baseline, feature-security-operational-baseline]
created: 2026-05-27
last_reviewed: 2026-05-27
---
# RFC 9110 — HTTP Semantics (Idempotent Methods + 4xx Status Codes)
> Layer: `raw/official-docs/` — IETF RFC 9110 (Internet Standard / STD 97, June 2022) 발췌. HTTP/1.1, HTTP/2, HTTP/3 가 공통으로 따르는 HTTP semantics 의 normative reference. 본 raw 는 §9.2.2 (idempotent methods) 와 §15.5.x (4xx 응답 코드 — 401/403/405/406/412/413/414/415 등) 만 발췌.
## Parent / 활용 branch (필수)
| Branch | 이 자료가 정당화하는 결정 |
|---|---|
| [[raw/branch-notes/feature-outbound-http-client-baseline]] | D6 §9.2.2 idempotent methods — outbound HTTP client 의 자동 재시도(retry) 정책이 GET/HEAD/PUT/DELETE 에만 안전하게 적용되는 표준 근거 |
| [[raw/branch-notes/feature-api-contract-baseline]] | D8 §15.5.14 status 413 + D9 §15.5.7 406 / §15.5.16 415 (Phase 1, 2026-05-27); **2026-05-31 발췌 보강**: D12 §15.5.6 405 Method Not Allowed + §10.2.1 Allow header (RFC9110-C9/C10), D13 §9.3.2 HEAD + §9.3.7 OPTIONS (RFC9110-C11/C12), D15 §8.8.3 ETag + §13.1.1 If-Match + §13.1.2 If-None-Match + §15.4.5 304 + §15.5.13 412 (RFC9110-C13~C17), D16 §12.5.5 Vary (RFC9110-C18), D8 형제 §15.5.15 414 URI Too Long (RFC9110-C19), D19 §6.6.1 Date (RFC9110-C20), D17 §10.2.3 Retry-After + §15.3.3 202 Accepted (RFC9110-C21/C22) |
| [[raw/branch-notes/feature-security-operational-baseline]] | D7 §15.5.2 401 Unauthorized (= 인증 자격 부재, WWW-Authenticate MUST) + §15.5.4 403 Forbidden (= 자격은 있으나 권한 불충분) 의 normative 정의 — 본 branch 의 401(authn) vs 403(authz) 분리의 HTTP semantics 근거 (RFC9110-C23/C24, 2026-06-08 발췌 보강) |
## 컨텍스트
API contract baseline 의 4xx 응답 매핑 (특히 body validation vs content-type negotiation 의 분기) 과 outbound HTTP client 의 자동 재시도 안전 조건을 결정하기 위한 표준 reference. RFC 7231 (예전 HTTP semantics) 를 obsolete 시킨 현행 IETF standard. WebFetch 가 본 RFC 의 큰 사이즈로 §9.2.2 / §15.5.x 본문을 잘라 반환 → `curl https://www.rfc-editor.org/rfc/rfc9110.txt` 로 직접 받아 `sed -n` 으로 해당 섹션 verbatim 발췌.
## 출처 / Source
- 원본 URL: https://www.rfc-editor.org/rfc/rfc9110
- 텍스트 버전: https://www.rfc-editor.org/rfc/rfc9110.txt
- 아카이브 URL: (미수집)
- 저자 / 조직: IETF — R. Fielding (Adobe, Ed.), M. Nottingham (Fastly, Ed.), J. Reschke (greenbytes, Ed.)
- 발행일: 2022-06 (RFC 9110 / STD 97 — Internet Standard, Standards Track)
- Obsoletes: RFC 2818, RFC 7230 부분, RFC 7231, RFC 7232, RFC 7233, RFC 7235, RFC 7538, RFC 7615, RFC 7694
- 마지막 확인일: 2026-05-27
## 왜 저장했는지 / Why archived
API contract baseline (D8/D9) 의 4xx 분기 결정과 outbound HTTP client (D6) 의 retry safety 결정을 정당화하는 1차 normative reference. company tech blog 의 retry/idempotency 사례를 official 로 부르려면 본 RFC 의 normative 정의가 corroborate 해야 함.
## 핵심 인용 / Key quotes (verbatim, 2026-05-27 capture via `curl` + `sed -n`)
> [§9.2.2 Idempotent Methods, line 3863] "A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. Of the request methods defined by this specification, PUT, DELETE, and safe request methods are idempotent."
> [§9.2.2 Idempotent Methods, line 3884] "A client SHOULD NOT automatically retry a request with a non- idempotent method unless it has some means to know that the request semantics are actually idempotent, regardless of the method, or some means to detect that the original request was never applied."
> [§9.2.2 Idempotent Methods, line 3902] "A proxy MUST NOT automatically retry non-idempotent requests. A client SHOULD NOT automatically retry a failed automatic retry."
> [§15.5.7 406 Not Acceptable, line 7615] "The 406 (Not Acceptable) status code indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request (Section 12.1), and the server is unwilling to supply a default representation."
> [§15.5.14 413 Content Too Large, line 7710] "The 413 (Content Too Large) status code indicates that the server is refusing to process a request because the request content is larger than the server is willing or able to process. The server MAY terminate the request, if the protocol version in use allows it; otherwise, the server MAY close the connection."
> [§15.5.14 413 Content Too Large, line 7716] "If the condition is temporary, the server SHOULD generate a Retry-After header field to indicate that it is temporary and after what time the client MAY try again."
> [§15.5.16 415 Unsupported Media Type, line 7738] "The 415 (Unsupported Media Type) status code indicates that the origin server is refusing to service the request because the content is in a format not supported by this method on the target resource."
> [§15.5.16 415 Unsupported Media Type, line 7742] "The format problem might be due to the request's indicated Content-Type or Content-Encoding, or as a result of inspecting the data directly."
### 2026-05-31 발췌 (D11~D19 정당화용 추가 14개)
> [§15.5.6 405 Method Not Allowed, line 7603] "The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. The origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods."
> [§10.2.1 Allow, line 4723] "An origin server MUST generate an Allow header field in a 405 (Method Not Allowed) response and MAY do so in any other response. An empty Allow field value indicates that the resource allows no methods, which might occur in a 405 response if the resource has been temporarily disabled by configuration."
> [§9.3.2 HEAD, line 3987] "The HEAD method is identical to GET except that the server MUST NOT send content in the response. HEAD is used to obtain metadata about the selected representation without transferring its representation data, often for the sake of testing hypertext links or finding recent modifications."
> [§9.3.2 HEAD, line 3992] "The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request method had been GET. However, a server MAY omit header fields for which a value is determined only while generating the content."
> [§9.3.7 OPTIONS, line 4336] "The OPTIONS method requests information about the communication options available for the target resource, at either the origin server or an intervening intermediary. This method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action."
> [§8.8.3 ETag, line 3572] "The \"ETag\" field in a response provides the current entity tag for the selected representation, as determined at the conclusion of handling the request. An entity tag is an opaque validator for differentiating between multiple representations of the same resource, regardless of whether those multiple representations are due to resource state changes over time, content negotiation resulting in multiple representations being valid at the same time, or both. An entity tag consists of an opaque quoted string, possibly prefixed by a weakness indicator."
> [§13.1.1 If-Match, line 5787] "The \"If-Match\" header field makes the request method conditional on the recipient origin server either having at least one current representation of the target resource, when the field value is \"*\", or having a current representation of the target resource that has an entity tag matching a member of the list of entity tags provided in the field value."
> [§13.1.1 If-Match, line 5793] "An origin server MUST use the strong comparison function when comparing entity tags for If-Match (Section 8.8.3.2), since the client intends this precondition to prevent the method from being applied if there have been any changes to the representation data."
> [§13.1.2 If-None-Match, line 5874] "The \"If-None-Match\" header field makes the request method conditional on a recipient cache or origin server either not having any current representation of the target resource, when the field value is \"*\", or having a selected representation with an entity tag that does not match any of those listed in the field value."
> [§15.4.5 304 Not Modified, line 7446] "The 304 (Not Modified) status code indicates that a conditional GET or HEAD request has been received and would have resulted in a 200 (OK) response if it were not for the fact that the condition evaluated to false. In other words, there is no need for the server to transfer a representation of the target resource because the request indicates that the client, which made the request conditional, already has a valid representation; the server is therefore redirecting the client to make use of that stored representation as if it were the content of a 200 (OK) response."
> [§15.5.13 412 Precondition Failed, line 7700] "The 412 (Precondition Failed) status code indicates that one or more conditions given in the request header fields evaluated to false when tested on the server (Section 13). This response status code allows the client to place preconditions on the current resource state (its current representations and metadata) and, thus, prevent the request method from being applied if the target resource is in an unexpected state."
> [§12.5.5 Vary, line 5670] "The \"Vary\" header field in a response describes what parts of a request message, aside from the method and target URI, might have influenced the origin server's process for selecting the content of this response."
> [§15.5.15 414 URI Too Long, line 7722] "The 414 (URI Too Long) status code indicates that the server is refusing to service the request because the target URI is longer than the server is willing to interpret. This rare condition is only likely to occur when a client has improperly converted a POST request to a GET request with long query information, when the client has descended into an infinite loop of redirection (e.g., a redirected URI prefix that points to a suffix of itself) or when the server is under attack by a client attempting to exploit potential security holes."
> [§6.6.1 Date, line 2306] "A sender that generates a Date header field SHOULD generate its field value as the best available approximation of the date and time of message generation. In theory, the date ought to represent the moment just before generating the message content. In practice, a sender can generate the date value at any time during message origination."
> [§10.2.3 Retry-After, line 4801] "Servers send the \"Retry-After\" header field to indicate how long the user agent ought to wait before making a follow-up request. When sent with a 503 (Service Unavailable) response, Retry-After indicates how long the service is expected to be unavailable to the client. When sent with any 3xx (Redirection) response, Retry-After indicates the minimum time that the user agent is asked to wait before issuing the redirected request."
> [§15.3.3 202 Accepted, line 6984] "The 202 (Accepted) status code indicates that the request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. There is no facility in HTTP for re-sending a status code from an asynchronous operation."
## Claims Extracted / 추출된 주장
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|---|---|---|---|---|---|
| RFC9110-C1 | HTTP 의 "idempotent" 정의: 동일 method 의 여러 identical request 가 단일 request 와 동일한 서버 효과를 가짐. RFC 9110 가 정의한 method 중 **PUT, DELETE, 그리고 safe methods (GET, HEAD, OPTIONS, TRACE)** 가 idempotent | [§9.2.2, line 3863] "A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request. Of the request methods defined by this specification, PUT, DELETE, and safe request methods are idempotent." | `official-standard` | RFC 9110 가 정의한 HTTP method 의 retry safety 판단 | POST / PATCH 가 idempotent 가 아니라는 normative 진술은 본 인용에 직접 포함 안됨 (열거 부재가 의미상 함의되나 별도 검증 권고). 또한 application-level idempotency key 패턴이 표준이라는 뜻은 아님 |
| RFC9110-C2 | client 는 non-idempotent method request 를 **automatically retry SHOULD NOT** — request 의 실제 semantics 가 idempotent 임을 알거나, 원 request 가 적용되지 않았음을 감지할 수단이 없으면 | [§9.2.2, line 3884] "A client SHOULD NOT automatically retry a request with a non- idempotent method unless it has some means to know that the request semantics are actually idempotent, regardless of the method, or some means to detect that the original request was never applied." | `official-standard` | outbound HTTP client 의 자동 retry 정책 (Resilience4j retry, Spring `RestClient` interceptor 등) | "수동 retry" (사용자가 명시적으로 다시 누르는 경우) 까지 금지한다는 뜻은 아님. 또한 어떤 application-level signal 이 "원 request 가 적용되지 않았음" 을 증명하는지는 별도 결정 |
| RFC9110-C3 | proxy 는 non-idempotent request 를 **automatically retry MUST NOT** | [§9.2.2, line 3902] "A proxy MUST NOT automatically retry non-idempotent requests. A client SHOULD NOT automatically retry a failed automatic retry." | `official-standard` | reverse proxy / API gateway 의 retry 동작 (Nginx `proxy_next_upstream`, Envoy retry policy 등) | application-level retry library (Resilience4j 등) 이 proxy 가 아닌 client 로 분류되는 한 본 MUST NOT 의 직접 대상은 아님 (C2 의 SHOULD NOT 이 적용됨) |
| RFC9110-C4 | **406 Not Acceptable** = target resource 가 proactive negotiation header (§12.1, Accept 계열) 에 부합하는 current representation 을 갖지 않고 server 가 default representation 도 제공하지 않을 때 | [§15.5.7, line 7615] "The 406 (Not Acceptable) status code indicates that the target resource does not have a current representation that would be acceptable to the user agent, according to the proactive negotiation header fields received in the request (Section 12.1), and the server is unwilling to supply a default representation." | `official-standard` | server 가 `Accept` / `Accept-Language` / `Accept-Charset` 등 헤더를 만족시킬 representation 이 없을 때의 응답 매핑 | request body 의 Content-Type 이 미지원일 때 (그것은 415) 와 혼동 금지. 406 은 **응답 표현** 협상 실패, 415 는 **요청 본문** 형식 미지원 |
| RFC9110-C5 | **413 Content Too Large** = server 가 request content 가 너무 커서 처리 거부. server 는 protocol 이 허용하면 request 종료 또는 connection close MAY | [§15.5.14, line 7710] "The 413 (Content Too Large) status code indicates that the server is refusing to process a request because the request content is larger than the server is willing or able to process. The server MAY terminate the request, if the protocol version in use allows it; otherwise, the server MAY close the connection." | `official-standard` | request body / multipart upload 크기 초과 응답 (예: Spring `MaxUploadSizeExceededException` → 413 매핑) | "정확한 byte 한계" 가 표준에 정의되어 있다는 뜻은 아님 — server 정책에 위임. 또한 streaming chunk 별 처리 시점 의무도 RFC 가 강제하지 않음 |
| RFC9110-C6 | 413 응답이 일시적이면 server 는 `Retry-After` 헤더 생성 SHOULD | [§15.5.14, line 7716] "If the condition is temporary, the server SHOULD generate a Retry-After header field to indicate that it is temporary and after what time the client MAY try again." | `official-standard` | 413 응답의 temporary vs permanent 구분 + Retry-After 발행 정책 | 모든 413 이 일시적이라는 뜻 아님. 영구적 (예: 정책상 unconditional rejection) 인 경우 Retry-After 불필요 |
| RFC9110-C7 | **415 Unsupported Media Type** = origin server 가 method/target resource 에 대해 요청 본문의 format 이 지원되지 않아 거부 | [§15.5.16, line 7738] "The 415 (Unsupported Media Type) status code indicates that the origin server is refusing to service the request because the content is in a format not supported by this method on the target resource." | `official-standard` | request body 의 Content-Type / Content-Encoding 이 server 가 처리할 수 없는 경우 (예: `application/xml` 만 받는 endpoint 에 `text/yaml` 전송) | "method 별로 어떤 media type 이 허용되는지" 의 카탈로그는 표준이 정의하지 않음 — application/resource 책임 |
| RFC9110-C8 | 415 의 format 문제는 request 의 `Content-Type` 또는 `Content-Encoding` 에서 비롯되거나, 데이터를 직접 검사한 결과일 수 있음 | [§15.5.16, line 7742] "The format problem might be due to the request's indicated Content-Type or Content-Encoding, or as a result of inspecting the data directly." | `official-standard` | 415 응답의 정확한 trigger 조건 분류 — header-based vs content-inspection | 어느 쪽 trigger 가 server 가 우선 선택해야 하는지는 표준이 강제하지 않음 |
| RFC9110-C9 | **405 Method Not Allowed** = origin server 가 method 는 알지만 target resource 가 지원하지 않음. 405 응답에 `Allow` header 생성 MUST + 지원 method 목록 포함 | [§15.5.6, line 7603] "The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. The origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods." | `official-standard` | API endpoint 의 method 미지원 응답 매핑 (예: DELETE-only endpoint 에 GET 요청 → 405 + `Allow: DELETE`) | 어떤 method 가 어느 resource 에 허용되는지의 카탈로그는 별도 (resource owner 책임). 405 응답 body 의 envelope shape 도 표준 외 — application 책임 |
| RFC9110-C10 | `Allow` header = origin server 가 405 응답에서 MUST 생성. 다른 응답에서는 MAY. 빈 Allow value = 해당 resource 가 어떤 method 도 허용 안 함 | [§10.2.1, line 4723] "An origin server MUST generate an Allow header field in a 405 (Method Not Allowed) response and MAY do so in any other response. An empty Allow field value indicates that the resource allows no methods, which might occur in a 405 response if the resource has been temporarily disabled by configuration." | `official-standard` | 405 응답 + `Allow` header 의 형식 + 빈 값 의미 | `Allow` header 가 OPTIONS 응답에 자동 포함되는지는 별도 (RFC 9110 §9.3.7 OPTIONS 의무 별도 발췌 필요) |
| RFC9110-C11 | **HEAD method** = GET 과 동일하나 server 는 response content 를 MUST NOT 전송. metadata 만 반환 (hypertext link test 또는 최근 수정 감지 용도) | [§9.3.2, line 3987] "The HEAD method is identical to GET except that the server MUST NOT send content in the response. HEAD is used to obtain metadata about the selected representation without transferring its representation data, often for the sake of testing hypertext links or finding recent modifications." | `official-standard` | GET 지원 endpoint 의 HEAD 자동 mirror (Spring MVC default) + 응답 body 0 검증 | "GET 지원 endpoint 가 HEAD 도 MUST 지원" 이라는 normative 진술은 본 인용 자체에는 *함의* — 명시적 MUST 는 다른 곳에 있을 수 있음. 본 인용은 "HEAD 가 있으면 GET 과 동일한 의미" 임을 정의 |
| RFC9110-C12 | **OPTIONS method** = target resource 의 communication options 요청. origin server 또는 intermediary 모두 가능. resource action 함의 없음 — pure introspection | [§9.3.7, line 4336] "The OPTIONS method requests information about the communication options available for the target resource, at either the origin server or an intervening intermediary. This method allows a client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action." | `official-standard` | OPTIONS 응답의 분기 결정 (resource metadata vs CORS preflight) — RFC 9110 자체는 두 용도 모두 허용 | CORS preflight 의 특별한 처리 (`Access-Control-Request-Method` header 의존) 는 RFC 9110 영역 밖 — WHATWG Fetch spec 영역 ([[raw/official-docs/fetch-spec-cors]] 참조) |
| RFC9110-C13 | **ETag** field = response 의 selected representation 에 대한 entity tag. opaque validator — resource state 변화·content negotiation 무관하게 representation 식별. opaque quoted string + optional weakness indicator | [§8.8.3, line 3572] "The \"ETag\" field in a response provides the current entity tag for the selected representation, as determined at the conclusion of handling the request. An entity tag is an opaque validator for differentiating between multiple representations of the same resource, regardless of whether those multiple representations are due to resource state changes over time, content negotiation resulting in multiple representations being valid at the same time, or both. An entity tag consists of an opaque quoted string, possibly prefixed by a weakness indicator." | `official-standard` | response 의 `ETag` 발행 — version field derived 또는 content hash derived | `ETag` 값의 정확한 derivation 방법 (version vs hash vs UUID) 은 server 자유 — opaque 성만 강제. weak validator (`W/"..."`) vs strong validator 선택 기준은 별도 (§8.8.3.3) |
| RFC9110-C14 | **If-Match** header = request method 를 conditional 화 — `"*"` 면 origin server 가 current representation 1개 이상 보유 조건, 또는 entity tag list 의 멤버 매칭 조건. origin server 는 strong comparison MUST 사용 — client 의 의도는 representation 변경 시 method 적용 방지 | [§13.1.1, line 5787] "The \"If-Match\" header field makes the request method conditional on the recipient origin server either having at least one current representation of the target resource, when the field value is \"*\", or having a current representation of the target resource that has an entity tag matching a member of the list of entity tags provided in the field value." + [line 5793] "An origin server MUST use the strong comparison function when comparing entity tags for If-Match (Section 8.8.3.2), since the client intends this precondition to prevent the method from being applied if there have been any changes to the representation data." | `official-standard` | write request 의 optimistic concurrency 검증 — `If-Match` mismatch 시 412 응답 | `If-Match` 누락된 write request 의 처리는 server 정책 — 본 인용은 "If-Match 가 *있으면* strong comparison" 만 강제. server 가 If-Match 를 강제 요구할지 (428 Precondition Required) 는 별도 (RFC 6585 §3) |
| RFC9110-C15 | **If-None-Match** header = request method 를 conditional 화 — `"*"` 면 recipient cache 또는 origin server 가 current representation 보유하지 않음 조건, 또는 entity tag list 의 어느 것과도 매칭하지 않음 조건. weak comparison MUST 사용 | [§13.1.2, line 5874] "The \"If-None-Match\" header field makes the request method conditional on a recipient cache or origin server either not having any current representation of the target resource, when the field value is \"*\", or having a selected representation with an entity tag that does not match any of those listed in the field value." | `official-standard` | read request 의 cache validation — `If-None-Match` match 시 304 응답 | weak vs strong comparison 의 정확한 algorithm 은 §8.8.3.2 — 본 인용 범위 밖. cache layer 의 If-None-Match 자동 처리 여부는 server/proxy 정책 |
| RFC9110-C16 | **304 Not Modified** status = conditional GET/HEAD 가 condition false 로 평가됨 → server 는 representation 전송 안 함, client 의 stored representation 을 200 응답인 것처럼 사용하도록 redirect | [§15.4.5, line 7446] "The 304 (Not Modified) status code indicates that a conditional GET or HEAD request has been received and would have resulted in a 200 (OK) response if it were not for the fact that the condition evaluated to false. In other words, there is no need for the server to transfer a representation of the target resource because the request indicates that the client, which made the request conditional, already has a valid representation; the server is therefore redirecting the client to make use of that stored representation as if it were the content of a 200 (OK) response." | `official-standard` | `If-None-Match` match 시 304 응답 — body 없음, envelope 우회 | 304 응답에 어떤 header field 를 MUST 생성해야 하는지는 §15.4.5 추가 부분 (Content-Location/Date/ETag/Vary, Cache-Control/Expires) — 별도 발췌 권고. envelope wrapping 의 304 우회는 표준 의무 (body 부재이므로 envelope 자체 불가) |
| RFC9110-C17 | **412 Precondition Failed** status = request header field 의 하나 이상의 condition 이 server 에서 false 평가됨. client 가 current resource state 에 precondition 두어 unexpected state 시 method 적용 방지 | [§15.5.13, line 7700] "The 412 (Precondition Failed) status code indicates that one or more conditions given in the request header fields evaluated to false when tested on the server (Section 13). This response status code allows the client to place preconditions on the current resource state (its current representations and metadata) and, thus, prevent the request method from being applied if the target resource is in an unexpected state." | `official-standard` | `If-Match` mismatch 시 412 응답 매핑 (409 Conflict 또는 500 으로 매핑 금지) | 412 응답의 envelope shape 은 application 책임. optimistic lock DB 레이어 충돌 → HTTP 412 매핑 의무는 본 인용 자체에 없음 — application 의 contract test 책임 |
| RFC9110-C18 | **Vary** field = response 의 어떤 부분이 origin server 의 content 선택 과정에 영향을 줬는지 description. method 와 target URI 외의 request 부분. wildcard `"*"` 또는 selecting header field list | [§12.5.5, line 5670] "The \"Vary\" header field in a response describes what parts of a request message, aside from the method and target URI, might have influenced the origin server's process for selecting the content of this response." | `official-standard` | content-negotiated 응답에 `Vary: Accept, Accept-Encoding, Authorization` 의무 — proxy/CDN cache poisoning 방지 | Vary 가 *없으면* cache poisoning 가능성 (proxy 가 다른 Accept-Language 응답을 동일 cache key 로 저장) — 본 인용은 의미론만 정의, "MUST generate" 진술은 별도 |
| RFC9110-C19 | **414 URI Too Long** status = server 가 target URI 가 너무 길어 처리 거부. POST→GET 잘못된 변환, 무한 redirect loop, 또는 보안 공격 시도 trigger | [§15.5.15, line 7722] "The 414 (URI Too Long) status code indicates that the server is refusing to service the request because the target URI is longer than the server is willing to interpret. This rare condition is only likely to occur when a client has improperly converted a POST request to a GET request with long query information, when the client has descended into an infinite loop of redirection (e.g., a redirected URI prefix that points to a suffix of itself) or when the server is under attack by a client attempting to exploit potential security holes." | `official-standard` | URI 길이 초과 응답 — Tomcat `maxHttpHeaderSize` (기본 8KB) 초과 시 raw 500 또는 잘못된 400 으로 변환되면 표준 위반 | 정확한 URI 길이 한계 (byte 수) 는 표준 미정 — server 정책 위임. envelope wrapping 도 application 책임 |
| RFC9110-C20 | **Date** header = message 생성 시점의 date+time. sender 는 best available approximation 으로 SHOULD 생성 | [§6.6.1, line 2306] "A sender that generates a Date header field SHOULD generate its field value as the best available approximation of the date and time of message generation. In theory, the date ought to represent the moment just before generating the message content. In practice, a sender can generate the date value at any time during message origination." | `official-standard` | 모든 응답에 `Date` header 자동 발행 — Spring/Tomcat default 포함 | 어떤 응답에 Date 가 MUST 인지 vs SHOULD 인지의 분기 (origin server vs proxy)는 §6.6.1 다른 부분 — 별도 발췌 권고. HTTP-date 형식 정의 (§5.6.7) 별도 |
| RFC9110-C21 | **Retry-After** header = server 가 client 에게 follow-up request 까지 대기 시간 안내. 503 응답 시 service unavailable 예상 시간, 3xx redirection 시 redirected request 까지 대기 시간 | [§10.2.3, line 4801] "Servers send the \"Retry-After\" header field to indicate how long the user agent ought to wait before making a follow-up request. When sent with a 503 (Service Unavailable) response, Retry-After indicates how long the service is expected to be unavailable to the client. When sent with any 3xx (Redirection) response, Retry-After indicates the minimum time that the user agent is asked to wait before issuing the redirected request." | `official-standard` | 413/429/503 + LRO polling 응답의 `Retry-After` 발행 정책 | Retry-After 가 4xx 응답 일반 (예: 412, 405) 에 적용 가능한지는 본 인용 범위 밖 — 503/3xx 만 정의. 413 의 일시적 경우는 §15.5.14 (RFC9110-C6) 별도 |
| RFC9110-C22 | **202 Accepted** status = request 가 processing 위해 accept 됐으나 processing 완료 안 됨. 비동기 처리 응답으로 intentionally noncommittal | [§15.3.3, line 6984] "The 202 (Accepted) status code indicates that the request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. There is no facility in HTTP for re-sending a status code from an asynchronous operation." | `official-standard` | Long-running operation (LRO) 응답 — 202 + `Location` header + polling endpoint (Google AIP-151 cross-cite) | "202 응답에 어떤 body 가 와야 하는지" 또는 polling URL 의 형식 (`/v1/operations/{id}`) 은 본 인용 범위 밖 — application 책임 (AIP-151 가 google API community guideline 으로 권고) |
| RFC9110-C23 | **401 Unauthorized** = request 가 target resource 에 대한 **valid authentication credentials 가 없어** 적용되지 않음. 401 생성 server 는 `WWW-Authenticate` header (≥1 challenge) MUST 전송. 자격이 *포함됐는데* 401 이면 그 자격에 대해 authorization 거부 | [§15.5.2, line 7550] "The 401 (Unauthorized) status code indicates that the request has not been applied because it lacks valid authentication credentials for the target resource. The server generating a 401 response MUST send a WWW-Authenticate header field (Section 11.6.1) containing at least one challenge applicable to the target resource." | `official-standard` | authn 실패 (missing/malformed/expired/invalid-signature/issuer/audience token) → **401 + WWW-Authenticate** 매핑 (`feature-security-operational-baseline` D7 + AuthN matrix). headers.yaml `WWW-Authenticate` row 정합 | valid token + scope vs role 같은 경계 case 에서 401 vs 403 중 어느 것인지는 본 인용이 정하지 않음 — 403 정의(C24)와 함께 application 결정 |
| RFC9110-C24 | **403 Forbidden** = server 가 request 를 **이해했으나 수행을 거부**. 자격이 제공됐으면 server 가 그 자격을 **권한 부여에 불충분**하다고 판단. client 는 동일 자격으로 자동 재시도 SHOULD NOT | [§15.5.4, line 7571] "The 403 (Forbidden) status code indicates that the server understood the request but refuses to fulfill it. ... If authentication credentials were provided in the request, the server considers them insufficient to grant access. The client SHOULD NOT automatically repeat the request with the same credentials." | `official-standard` | authz 실패 (valid token + 권한 부족 / cross-tenant) → **403** 매핑 (`feature-security-operational-baseline` D7 + AUTHZ matrix 2 rows: `AUTHZ_INSUFFICIENT_PERMISSION`/`AUTHZ_TENANT_MISMATCH`) | 권한 부족 resource 를 404 로 "hide" 하는 선택(§15.5.4 마지막 문단)은 별도 정책 결정 — 본 branch 미채택 |
## Usage Boundaries / 적용 경계
- **이 자료가 직접 증명하는 것**:
- `RFC9110-C1`~`C3`: idempotency 의 normative 정의 + automatic retry 의 client/proxy 의무 (SHOULD NOT / MUST NOT)
- `RFC9110-C4`: 406 의 의미론 (응답 표현 협상 실패)
- `RFC9110-C5`~`C6`: 413 의 의미론 + Retry-After SHOULD
- `RFC9110-C7`~`C8`: 415 의 의미론 (요청 본문 format 미지원) + trigger 조건
- `RFC9110-C9`~`C10`: 405 의 의미론 + `Allow` header MUST 의무 (api-contract-baseline D12)
- `RFC9110-C11`~`C12`: HEAD 와 OPTIONS method 의 정의 (api-contract-baseline D13)
- `RFC9110-C13`: ETag field 정의 (opaque validator) (api-contract-baseline D15)
- `RFC9110-C14`~`C15`: If-Match / If-None-Match conditional request 의미론 (api-contract-baseline D15)
- `RFC9110-C16`~`C17`: 304 / 412 status code 의미론 (api-contract-baseline D15)
- `RFC9110-C18`: Vary header 의미론 (api-contract-baseline D16)
- `RFC9110-C19`: 414 URI Too Long 의미론 (api-contract-baseline D8 형제)
- `RFC9110-C20`: Date header 의미론 (api-contract-baseline D19 — future)
- `RFC9110-C21`: Retry-After header 의미론 (api-contract-baseline D17 LRO polling)
- `RFC9110-C22`: 202 Accepted 의미론 (api-contract-baseline D17 LRO)
- `RFC9110-C23`~`C24`: 401 Unauthorized (authn 부재 + WWW-Authenticate MUST) / 403 Forbidden (자격 불충분) 의미론 — `feature-security-operational-baseline` D7 의 401/403 분리 근거 (2026-06-08)
- **이 자료가 증명하지 않는 것**:
- POST/PATCH 가 idempotent 가 아니라는 명시적 normative 진술 (열거 부재가 함의이나 별도 §9.2.1 safe methods 정의 + §9.3.x method 정의로 corroborate 필요)
- application-level idempotency key 패턴 (`Idempotency-Key` 헤더 — RFC 9457 / draft-ietf-httpapi-idempotency-key-header) 이 표준이라는 뜻은 아님 — 본 RFC 는 method-level idempotency 만 정의
- 어떤 4xx 응답이 retryable 한지 — `RFC9110-C6` 가 413 에 한해 Retry-After 가능성을 말할 뿐 일반 retry 정책은 별도 (RFC 7231 §6.4, OpenAPI vendor 정책 등)
- 422 Unprocessable Content vs 400 Bad Request 의 분기 — 별도 발췌 필요
- body 크기 한계의 구체적 byte 수 (예: 10MB, 100MB) — server 정책에 위임
- **내 프로젝트에 적용하려면 추가 확인이 필요한 것**:
- Spring `RestClient` / `WebClient` 의 retry interceptor 가 default 로 GET 외의 method 를 retry 하지 않는지 (Spring 구현 검증)
- Nginx `proxy_next_upstream` 의 default 가 idempotent method 만 retry 하는지 (Nginx vendor doc 별도 검증)
- ca-tmpl 의 `GlobalExceptionHandler``MaxUploadSizeExceededException` → 413, `HttpMediaTypeNotSupportedException` → 415, `HttpMediaTypeNotAcceptableException` → 406 매핑을 일관되게 수행하는지 (Spring 기본 매핑 검증)
## 메모 / Notes
- WebFetch 가 RFC 9110 전체 (10785 line) 를 한 번에 처리 못해 §9.2.2 / §15.5.x 본문을 truncate. `curl https://www.rfc-editor.org/rfc/rfc9110.txt` + `grep -n` 로 section line 찾고 `sed -n '<start>,<end>p'` 로 verbatim 발췌. 본 raw 의 모든 인용은 텍스트 버전 line number 표기.
- RFC 9110 §9.2.1 safe methods (GET, HEAD, OPTIONS, TRACE) 정의는 본 raw 에 직접 인용 없음 — RFC9110-C1 의 "safe request methods" 가 가리키는 enumeration 의 corroboration 필요 시 §9.2.1 별도 발췌.
- 422 Unprocessable Content (§15.5.21) 도 ca-tmpl validation 응답 매핑 후보 — 별도 raw 또는 후속 발췌 권고.
## Related / 관련
- 같은 주제 다른 official-doc:
- [[raw/official-docs/problem-detail-rfc-7807]] — error envelope 표준 (4xx 응답 body shape)
- 인용하는 branch:
- [[raw/branch-notes/feature-outbound-http-client-baseline]] (D6)
- [[raw/branch-notes/feature-api-contract-baseline]] (D8, D9)
- 인용하는 project:
- [[raw/project-notes/ca-skeleton-operational-contract]]
- 인용한 wiki 요약: (미작성)