HTTP 캐싱 - HTTP

HTTP 캐싱
=======

웹 사이트와 애플리케이션의 성능은 이전에 가져온 리소스들을 재사용함으로써 현저하게 향상될 수 있습니다. 웹 캐시는 레이턴시와 네트워크 트래픽을 줄여줌으로써 리소스를 보여주는 데에 필요한 시간을 줄여줍니다. HTTP 캐싱을 활용하면 웹 사이트가 좀 더 빠르게 반응하도록 만들 수 있습니다.

다른 종류의 캐시들
----------

캐싱은 주어진 리소스의 복사본을 저장하고 있다가 요청 시에 그것을 제공하는 기술입니다. 웹 캐시가 자신의 저장소 내에 요청된 리소스를 가지고 있다면, 요청을 가로채 원래의 서버로부터 리소스를 다시 다운로드하는 대신 리소스의 복사본을 반환합니다. 이것은 다음과 같은 몇 가지 목표를 달성하게 해줍니다: 모든 클라이언트를 서비스할 필요가 없어지므로 서버의 부하를 완화하고, (캐시가 원래 서버에 비해서) 클라이언트에 더 가까이에 있으므로 성능이 향상됩니다. 즉, 리소스를 회신하는데 더 적은 시간이 들게 됩니다. 웹 사이트에서 캐싱은 높은 성능을 달성하는 데에 주요한 요소입니다. 반면에 모든 리소스가 영원히 변하지 않는 것은 아니므로 리소스가 변하기 전까지만 캐싱하고 변한 이후에는 더이상 캐싱하지 않는 것이 중요합니다.

캐시에는 몇 가지 종류가 있습니다: 크게 사설(private) 혹은 공유(shared) 캐시 두 가지 부류로 분류될 수 있습니다. *공유 캐시*는 한 명 이상의 사용자가 재사용할 수 있도록 응답을 저장하는 캐시를 말합니다. *사설 캐시*는 한 명의 사용자만 사용하는 캐시를 말합니다. 이 페이지에서는 거의 대부분 브라우저와 프록시 캐시에 대해서만 다룰 것이나, 그 외에도 더 나은 신뢰도, 성능 그리고 웹 사이트와 웹 애플리케이션의 확장(scaling)을 위해 웹 서버 위에 배포되는 게이트웨이 캐시, CDN, 리버스 프록시 캐시 그리고 로드 밸랜서 등이 있습니다.

![What a cache provide, advantages/disadvantages of shared/private caches.](/ko/docs/Web/HTTP/Caching/http_cache_type.png)

### 사설 브라우저 캐시

사설 캐시는 단일 사용자가 전용으로 사용합니다. 브라우저 설정에서 "caching"을 본 적이 있을 겁니다. 브라우저 캐시는 그 사용자에 의하여 HTTP를 통해 다운로드된 모든 문서들을 가지고 있습니다. 이 캐시는 서버에 대한 추가적인 요청 없이 뒤로 가기나 앞으로 가기, 저장, 소스로 보기 등을 위해 방문했던 문서들을 사용할 수 있도록 해 줍니다. 또한 유사한 방법으로 캐시된 컨텐츠의 오프라인 브라우징을 개선시킵니다.

### 공유 프록시 캐시

공유 캐시는 한 명 이상의 사용자에 의해 재사용되는 응답을 저장하는 캐시입니다. 예를 들어, 당신의 회사의 ISP는 많은 사용자들을 서비스하기 위해 지역 네트워크 기반의 일부분으로서 웹 프록시를 설치해뒀을 수도 있는데, 그 덕분에 조회가 많이 되는 리소스들은 몇 번이고 재사용되어 네트워크 트래픽과 레이턴시를 줄여줍니다.

캐싱 동작의 대상
---------

HTTP 캐싱은 선택적(optional)이지만 캐시된 리소스를 재사용하는 것은 보통 바람직한 일입니다. 하지만, HTTP 캐시들은 일반적으로 `GET`에 대한 응답만을 캐싱하며, 다른 메서드들은 제외될 겁니다. 기본 캐시 키(primary cache key)는 요청 메서드 그리고 대상 URI로 구성됩니다(GET 요청만을 대상으로 하므로 URI만 사용되는 경우가 많습니다). 일반적인 캐싱 엔트리의 형태는 다음과 같습니다:

* 검색(retrieval) 요청의 성공적인 결과: HTML 문서, 이미지 혹은 파일과 같은 리소스를 포함하는 `GET` 요청에 대한 `200` (OK) 응답.
* 영구적인 리다이렉트: `301` (Moved Permanently) 응답.
* 오류 응답: `404` (Not Found) 결과 페이지.
* 완전하지 않은 결과: `206` (Partial Content) 응답.
* 캐시 키로 사용하기에 적절한 무언가가 정의된 경우의 `GET` 이외의 응답.

캐시 엔트리는 요청이 컨텐츠 협상의 대상인 경우, 두번째 키에 의해 구별되는 여러 개의 저장된 응답들로 구성될 수도 있습니다. 좀 더 자세한 내용을 참고하시려면 아래에서 `Vary` 헤더에 대해서 읽어보시기 바랍니다.

캐싱 제어
-----

### `Cache-control` 헤더

`Cache-Control` HTTP/1.1 기본 헤더 필드는 요청과 응답 양측 모두에 있어 캐싱 메커니즘을 위한 디렉티브를 지정하는데 사용됩니다. 이 헤더 필드가 제공하는 여러 디렉티브들로 캐싱 정책을 정의하고자 한다면 이 헤더를 사용하시기 바랍니다.

#### 캐시하지 않음

캐시는 클라이언트 요청 혹은 서버 응답에 관해서 어떤 것도 저장해서는 안됩니다. 요청은 서버 측으로 전송되고 전체 응답은 매번 다운로드됩니다.
```

Cache-Control: no-store
```

#### 캐시하지만 재검증

캐시된 복사본을 사용자에게 릴리즈 하기 전에, 유효성 확인을 위해 원 서버로 요청을 보냅니다.
```

Cache-Control: no-cache
```

#### 사설 캐시와 공개 캐시

"public" 디렉티브는 응답이 어떤 캐시에 의해서든 캐시되어도 좋다는 것을 가리킵니다. 이것은 HTTP 인증, 혹은 보통 캐시 가능하지 않은 응답 상태 코드를 지닌 페이지가 이제 캐시되어야 할 경우 유용할 수 있습니다.

반면 "private"은 응답이 단일 사용자만을 위한 것이며 공유 캐시에 의해 저장되어서는 안된다는 것을 가리킵니다. 사설 브라우저 캐시는 이런 경우에 응답을 저장할 수 있습니다.
```

Cache-Control: private
Cache-Control: public
```

#### 만료

여기서 가장 중요한 디렉티브는 "`max-age=<seconds>`"로 리소스가 유효하다고 판단되는 최대 시간을 말합니다. 이 디렉티브는 요청 시간에 상대적이며, `Expires`가 설정되어 있어도 그보다 우선합니다. 변경되지 않을 파일에 대해, 공격적으로 (긴 시간으로) 캐싱할 수 있습니다. 예를 들어 이미지, CSS 파일 그리고 JavaScript 파일과 같은 정적 파일들입니다.

좀 더 자세한 내용을 위해, 아래에서 유효성 섹션을 참고하시기 바랍니다.
```

Cache-Control: max-age=31536000
```

#### 검증

"`must-revalidate`" 디렉티브 사용 시, 캐시는 오래된 리소스를 사용하기 전에 그 상태를 확인하고 만료된 리소스는 사용하지 말아야 합니다. 좀 더 자세한 내용은, 아래에서 검증 섹션을 참고하시기 바랍니다.
```

Cache-Control: must-revalidate
```

### `Pragma` 헤더

`Pragma`는 HTTP/1.0 헤더입니다. `Pragma: no-cache`는 캐시가 검증을 위해 원래 서버에 요청을 보내도록 강제한다는 점에서 `Cache-Control: no-cache`와 유사합니다. 그러나 `Pragma`는 HTTP 응답에 대해 명세되지 않았으므로 일반적인 HTTP/1.1 `Cache-Control` 헤더를 신뢰성 있게 대체할 수 없습니다.

`Cache-Control` HTTP/1.1 헤더가 없는 HTTP/1.0 클라이언트와의 하위 호환성을 위한 경우에만 `Pragma`를 사용하여야 합니다.

유효성(Freshness)
--------------

리소스가 캐시 내에 저장되고 나면, 이론적으로는 영원히 캐시에 의해 서비스될 수도 있습니다. 캐시는 유한한 저장 공간을 가지므로 아이템들은 주기적으로 스토리지에서 제거됩니다. 이런 과정을 \*캐시 축출(cache eviction)\*이라고 부릅니다. 반면 어떤 리소스들은 서버 상에서 변경될 수 있고, 캐시가 갱신되어야 합니다. HTTP가 클라이언트-서버 프로토콜이므로, 리소스가 변경됐을 때 서버는 캐시와 클라이언트에 접근할 수 없습니다; 서버는 리소스에 대한 만료 시간을 알려줄 수밖에 없습니다. 만료 시간 이전에는, 리소스가 \*유효(fresh)\*합니다; 만료 시간 이후의 리소스는 \*실효(stale)\*됩니다. 축출 알고리즘은 대개 실효된 리소스보다 유효한 리소스에 특권을 부여합니다. 실효된 리소스는 축출되거나 무시되지 않는다는 것을 알아두시기 바랍니다; 캐시가 실효된 리소스에 대한 요청을 받은 경우, 이 리소스가 실제로 아직 유효한지 아닌지를 확인하기 위해 `If-None-Match`와 함께 요청을 전달합니다. 만약 그렇다면, 서버는 요청된 리소스 본문을 전송하지 않고 `304` (Not Modified) 헤더를 돌려보내 대역폭을 절약합니다.

다음은 이런 과정에 대한 공유 캐시 프록시를 이용한 예제입니다:

![Show how a proxy cache acts when a doc is not cache, in the cache and fresh, in the cache and stale.](/ko/docs/Web/HTTP/Caching/httpstaleness.png)

유효 수명은 몇가지 헤더에 근거해 계산됩니다. "`Cache-control: max-age=N`" 헤더가 설정된 경우, 유효 수명은 N과 동일합니다. 만약 이 헤더가 없다면, 이런 경우가 매우 많습니다만, `Expires` 헤더가 있는지 없는지를 검사합니다. `Expires` 헤더가 존재한다면, 그것의 값에서 `Date` 헤더의 값을 뺀 결과가 유효 수명이 됩니다.

### 유효성 검사 휴리스틱

원래 서버가 명시적으로 유효성을 지정하지 않았으면 (예를 들어 `Cache-Control` 또는 `Expires` 헤더를 사용해서), 휴리스틱으로 유효 기간을 추정합니다.

 이 경우에는 `Last-Modified` 헤더를 찾습니다. 이 헤더가 있다면, 캐시의 유효 수명은 `Date` 헤더 값에서 `Last-modified` 헤더 값을 뺀 값을 10으로 나눈 결과가 됩니다.
 만료 시간은 다음과 같이 계산됩니다:
```

expirationTime = responseTime + freshnessLifetime - currentAge
```

`responseTime`은 브라우저가 응답을 수신한 시간을 말합니다. 더 많은 정보를 위해서는 RFC 7234: Hypertext Transfer Protocol (HTTP/1.1): 4.2.2. Calculating Heuristic Freshness를 참조하시기 바랍니다.

### 리비전된(Revved) 리소스

우리가 캐시된 리소스들을 많이 사용할수록, 웹 사이트의 응답성과 성능은 점점 더 좋아질 것입니다. 이것을 최적화하기 위한 좋은 방법은 만료 시간을 가능한 더 먼 미래로 설정하는 것입니다. 이것은 정기적으로나 자주 업데이트되는 리소스에 대해서는 가능하지만, 드물게 업데이트되는 리소스의 경우에는 문제가 됩니다. 이런 리소스들을 캐시하면 이득이 크지만, 업데이트하기가 매우 어렵기 때문입니다. 캐시한 리소스로부터 최대한 활용되는 리소스들로, 앞서 얘기한 방법 덕분에 이러한 리소스들을 갱신하기 더 어렵게 됩니다. 대표적으로 각 웹 페이지에 포함되고 링크된 기술적인 리소스들이 그렇습니다: JavaScript와 CSS 파일들의 변경은 드물지만, 그것들이 변경되었을 때에는 빠르게 갱신되기를 원할 겁니다.

웹 개발자들은 Steve Sounders가 *revving*[1]이라고 불렀던 기술을 발명했습니다. 드물게 업데이트되는 파일들은 특정한 방법으로 이름붙여집니다: 파일들의 URL내에, 보통 파일명에, 수정(혹은 버전) 번호가 추가됩니다. 그렇게 해서 해당 리소스의 각각의 새로운 수정본 자체는 결코 변경되지 않으며, 보통 1년 혹은 그 이상의 아주 먼 미래로 만료 시간이 설정될 수 있습니다. 새로운 버전을 가지기 위해, 해당 리소스와의 모든 연결(link)들은 전부 변경되어야 하며, 그것이 이 방법의 단점입니다: 이 추가적인 복잡함은 보통 웹 개발자들이 사용하는 툴체인에 의해 다루어집니다. 드물게 변경되는 리소스들이 변경되는 경우 자주 변경되는 리소스에 추가적인 변경을 합니다. 이런 리소스들이 읽혀지는 경우, 다른 리소스들의 새로운 버전들도 읽혀지게 됩니다.

이 기술은 추가적인 이점도 가지고 있습니다: 캐시된 두 개의 리소스를 동시에 갱신해도 한 리소스의 오래된 버전이 다른 리소스의 새로운 버전과 함께 혼합되어 사용되는 경우를 초래하지 않을 것입니다. 이것은 웹 사이트가 상호 간의 의존성을 가지고 있는 CSS 스타일시트와 JavaScript를 가지고 있는 경우 (같은 HTML 요소를 참조하기에 서로 의존하게 됩니다) 매우 중요합니다.

![](/ko/docs/Web/HTTP/Caching/httprevved.png)

리소스에 추가되는 수정 버전은 1.1.3과 같은 전통적인 버전 번호 형식이 아니어도 되고, 단조 증가하는 숫자들이 아니어도 됩니다. 그것은 해시 혹은 날짜와 같이 충돌만 되지 않는다면 무엇이든지 될 수 있습니다.

캐시 검증
-----

캐시된 문서의 만료 시간이 가까워져오면, 문서가 검증되거나 다시 불러오게 됩니다. 검증은 서버가 *강한 검증* 혹은 *약한 검증* 중 하나라도 제공하는 경우에만 일어날 수 있습니다.

재검증은 사용자가 리로드 버튼을 누를 경우 촉발됩니다. 재검증은 캐시된 응답이 "`Cache-control: must-revalidate`" 헤더를 포함하고 있는 경우 일반적인 브라우징 중에도 촉발될 수 있습니다. 또 다른 요인은 `Advanced->Cache` 환경설정 패널 내에 캐시 검증 환경 설정입니다. 거기에는 문서가 로드될 때마다 검증을 강제할 수 있는 옵션이 있습니다.

### ETags

`ETag` 응답 헤더는 강한 검증으로써 사용될 수 있는 *사용자 에이전트에게 있어 불투명한(opaque)* 값입니다. 그것은 브라우저와 같은 HTTP 사용자 에이전트가 이 문자열이 무엇을 표현하는지 알 수 없고, 그것의 값이 무엇이 될지를 예측할 수 없다는 것을 의미합니다. `ETag` 헤더가 리소스에 대한 응답의 일부라면, 클라이언트는 이후 요청의 해더 내에 (캐시된 리소스를 검증하기 위해) `If-None-Match`를 줄 수 있습니다.

### Last-Modified

`Last-Modified` 응답 헤더는 약한 검증으로써 사용될 수 있습니다. 그것이 1초의 해상도만 가질 수 있기에 약하다고 간주됩니다. `Last-Modified` 헤더가 응답 내에 존재하면, 클라이언트는 캐시된 문서를 검증하기 위해 `If-Modified-Since` 요청 헤더를 줄 수 있습니다.

검증 요청을 받으면, 서버는 검증 요청을 무시하고 일반적인 `200` `OK`으로 응답하거나, 브라우저에게 캐시된 복사본을 사용하도록 지시하기 위해 `304` `Not Modified` (본문을 비워둔 상태로)를 반환할 수 있습니다. 후자의 응답은 캐시된 문서의 만료 시간을 갱신하는 헤더를 포함할 수도 있습니다.

상황에 따른 응답
---------

`Vary` HTTP 응답 헤더는 원 서버로부터 새로운 리소스를 요청해야 하는지 캐시된 응답이 사용될 수 있는지를 결정하기 위해 이후의 요청 헤더를 대조하는 방식을 결정합니다.

캐시가 `Vary` 헤더 필드를 지닌 요청을 수신한 경우, `Vary` 헤더에 의해 지정된 모든 헤더 필드들이 원래의 (캐시된) 요청과 새로운 요청 사이에서 일치하지 않는다면 그 캐시된 응답을 사용해서는 안 됩니다.

![The Vary header leads cache to use more HTTP headers as key for the cache.](/ko/docs/Web/HTTP/Caching/httpvary.png)

이 기능은 컨텐츠를 비압축 또는 (여러 가지) 압축 포맷으로 캐시될 수 있도록 하고, 유저 에이전트가 지원하는 포맷에 따라 제공하도록 할 때 흔히 사용됩니다. 예를 들어 서버는 `Vary: Accept-Encoding`을 설정하여 특정한 집합의 인코딩을 지원하는 (예를 들어 `Accept-Encoding: gzip,deflate,sdch`) 모든 요청들에 대해 각각 다른 버전의 리소스를 캐시하도록 할 수 있습니다.
```

Vary: Accept-Encoding
```

**참고:** `Vary`는 주의해서 사용하기 바랍니다 — 캐시의 효과를 떨어뜨리기 쉽습니다! 캐시 서버는 중복된 캐시 엔트리와 서버로의 불필요한 요청을 줄이기 위해 정규화를 하여야 합다. `Vary`에 지정된 헤더나 헤더 값이 여러 가지인 경우에는 특히 그렇습니다.

`Vary` 헤더는 데스크탑과 모바일 사용자에게 서로 다른 컨텐츠를 제공하거나, 검색 엔진에게 페이지의 모바일 버전을 발견할 수 있게 하는 (그리고 클로킹 의도가 없다고 알려주는) 데에도 유용합니다. 이것은 보통 `Vary: User-Agent` 헤더를 사용해서 할 수 있습니다. `User-Agent` (en-US) 헤더 값이 모바일과 데스크탑 클라이언트 간에 서로 다르기 때문입니다..
```

Vary: User-Agent
```

### 정규화

위에서 언급한 바와 같이, 캐시 서버는 기본적으로 (by default) 헤더와 헤더 값이 *정확히* 같은 요청*만* 매치시킵니다. 이것은 다른 유저 에이전트에 따라 미세한 차이가 있는 모든 요청들에 대해 원래 서버로 요청이 전달되고, 새로운 캐시 엔트리가 생성된다는 것을 의미합니다.

예를 들어, 기본적으로 다음 헤더들은 제각각 별개의 요청을 서버에 전달하고, 별개의 캐시 엔트리가 생성되는 결과를 초래합니다: `Accept-Encoding: gzip,deflate,sdch`, `Accept-Encoding: gzip,deflate`, `Accept-Encoding: gzip`. 심지어 원래 서버가 모든 요청들에 대해 똑같은 리소스(gzip)를 응답할 (그리고 저장하고 있을) 때에도 그렇습니다!

이러한 불필요한 요청과 중복된 캐시 엔트리를 피하기 위해서, 캐시 서버는 요청을 전처리해서 필요한 파일만 캐시하는 **정규화**를 하여야 합니다. 예를 들어, `Accept-Encoding`의 경우에는 다른 처리를 하기 전에 헤더 내의 `gzip`과 다른 압축 타입들을 체크할 수 있습니다 (아니면 그 헤더를 해제합니다). "수도 코드"로 표현한다면 다음과 같습니다:
```

// Normalize Accept-Encoding
if (req.http.Accept-Encoding) {
  if (req.http.Accept-Encoding ~ "gzip") {
    set req.http.Accept-Encoding = "gzip";
  }
  // elsif other encoding types to check
else {
  unset req.http.Accept-Encoding;
  }
}
```

`User-Agent` 값은 `Accept-Encoding`보다 더욱 다양합니다. 그래서 만약 모바일과 데스크탑 버전을 캐싱하기 위해 `Vary: User-Agent`를 사용한다면, 위와 유사하게 `"mobile"`과 `"desktop"` 값이 요청의 `User-Agent` 헤더에 있는지 체크한 후에, 그것을 해제할 수 있습니다.

함께 참고할 내용
---------

* RFC 7234: 하이퍼텍스트 전송 프로토콜 (HTTP/1.1): 캐싱
* 캐싱 튜토리얼 – Mark Nottingham
* HTTP 캐싱 – Ilya Grigorik
* 레드봇, 캐시와 관련된 HTTP 헤더 점검을 위한 도구.


컨텐츠 보안 정책 (CSP) - HTTP

컨텐츠 보안 정책 (CSP)
===============

**콘텐츠 보안 정책** (CSP)는 교차 사이트 스크립팅(XSS)과 데이터 주입 공격을 비롯한 특정 유형의 공격을 탐지하고 완화하는 데 도움이 되는 추가 보안 계층입니다. 이러한 공격은 데이터 절도에서 사이트 훼손, 맬웨어 배포에 이르기까지 모든 것에 사용됩니다.

 CSP는 이전 버전과 완벽하게 호환되도록 설계되었습니다(이전 버전과의 호환성에서 일부 명시적으로 언급된 불일치가 있는 CSP 버전 2는 제외, 자세한 내용은 여기 섹션 1.1 참조).
 이를 지원하지 않는 브라우저는 여전히 이를 구현하는 서버에서 작동하며 그 반대의 경우도 마찬가지입니다. CSP를 지원하지 않는 브라우저는 CSP를 무시하고 평소와 같이 작동하며 기본적으로 웹 콘텐츠에 대한 표준 동일 출처 정책을 사용합니다. 사이트에서 CSP 헤더를 제공하지 않는 경우 브라우저도 마찬가지로 표준 동일 출처 정책을 사용합니다.

CSP를 활성화하려면 `Content-Security-Policy` (en-US) HTTP 헤더를 반환하도록 웹 서버를 구성해야 합니다. (가끔씩 `X-Content-Security-Policy` 헤더를 볼수도 있지만, 이는 이전 버전이므로 더 이상 설정할 필요가 없습니다.)

다른 방법으론, `<meta>` 요소를 사용하여 정책을 구성할 수 있습니다. 예를 들면 다음과 같습니다.

```html
<meta
 http-equiv="Content-Security-Policy"
 content="default-src 'self'; img-src https://\*; child-src 'none';" />
```

**참고:** CSP 위반 보고서 전송과 같은 일부 기능은 HTTP 헤더를 사용할 때만 사용할 수 있습니다.

위협
--

### 교차 사이트 스크립팅 완화

CSP의 주요 목표는 XSS 공격을 완화하고 보고하는 것입니다. XSS 공격은 서버에서 받은 콘텐츠를 브라우저가 신뢰한다는 점을 악용합니다. 브라우저는 콘텐츠의 출처를 신뢰하기 때문에 콘텐츠가 이상한 곳에서 오더라도 악성 스크립트를 피해자의 브라우저에서 실행합니다.

CSP를 사용하면 서버 관리자가 브라우저에서 실행 가능한 스크립트의 유효한 소스로 간주해야 하는 도메인을 지정하여 XSS가 발생할 수 있는 벡터를 줄이거나 제거할 수 있습니다. 그러면 CSP 호환 브라우저는 허용된 도메인에서 받은 소스 파일에서 로드된 스크립트만 실행하고 HTML 속성을 포함한 인라인 스크립트 및 이벤트 처리 등의 다른 모든 스크립트는 무시합니다.

궁극적인 보호 형태로서 스크립트 실행을 허용하지 않으려는 사이트는 전역적으로 스크립트 실행을 허용하지 않도록 선택할 수 있습니다.

### 패킷 스니핑 공격 완화

콘텐츠를 로드할 수 있는 도메인을 제한하는 것 외에도 서버는 사용할 수 있는 프로토콜을 지정할 수 있습니다. 예를 들어(이상적으로는 보안 관점에서) 서버는 모든 콘텐츠가 HTTPS를 사용하여 로드되도록 지정할 수 있습니다. 완전한 데이터 전송 보안 전략에서는 데이터 전송을 위해 HTTPS를 적용할 뿐만 아니라 모든 쿠키에 `secure` 속성을 표시하고 HTTP 페이지는 해당 HTTPS 페이지로 자동 리디렉션을 제공합니다. 사이트는 `Strict-Transport-Security` HTTP 헤더를 사용하여 브라우저가 암호화된 채널을 통해서만 사이트에 연결하도록 할 수도 있습니다.

CSP 사용하기
--------

 컨텐츠 보안 정책 구성은 `Content-Security-Policy` (en-US) HTTP 헤더를 웹 페이지에 추가하고 사용자 에이전트가 해당 페이지에 대해 로드할 수 있는 리소스를 제어하는 값을 지정하는 작업이 수반됩니다.
 예를 들어 이미지를 업로드하고 표시하는 페이지는 어디에서나 이미지를 허용할 수 있지만 폼 작업은 특정 엔드포인트로 제한할 수 있습니다. 적절하게 설계된 콘텐츠 보안 정책은 교차 사이트 스크립팅 공격으로부터 페이지를 보호하는 데 도움이 됩니다. 이 문서에서는 이러한 헤더를 올바르게 구성하는 방법을 설명하고 예제를 살펴봅니다.

### 정책 지정하기

다음과 같이 `Content-Security-Policy` (en-US) HTTP 헤더를 사용하여 정책을 지정할 수 있습니다.

```http
Content-Security-Policy: policy
```

이 정책은 여러분의 콘텐츠 보안 정책을 설명하는 정책 지시문을 포함한 문자열입니다.

### 정책 작성하기

 정책은 일련의 정책 지시문을 사용하여 설정합니다. 각각의 지시문은 특정 리소스 유형 또는 정책 영역에 대한 정책을 나타냅니다. 자체 정책이 없을 때는 다른 리소스 유형에 대한 폴백인 `default-src` 지시문을 포함해야 합니다(전체 목록은 `default-src` 지시문 설명 참조). 인라인 스크립트 실행을 방지하고 `eval()` 사용을 차단하려면 정책에 `default-src` 또는 `script-src` 지시문을 포함해야 합니다.
 인라인 스타일이 `<style>` 요소 또는 `style` 속성에서 적용되는 것을 제한하려면 정책에 `default-src` 또는 `style-src` (en-US) 지시문이 포함되어야 합니다.
 다양한 유형의 항목에 대한 특정 지시문이 있으므로 각 유형은 글꼴, 프레임, 이미지, 오디오 및 비디오 미디어, 스크립트 및 작업자를 포함하여 자체 정책을 가질 수 있습니다.

정책 지시문의 전체 목록은 Content-Security-Policy 헤더 (en-US) 페이지를 참조하세요.

예제: 일반적인 사용 사례
--------------

이 섹션에서는 몇 가지 일반적인 보안 정책 시나리오의 예를 살펴봅니다.

### 예제 1

웹 사이트 관리자는 모든 콘텐츠가 사이트 자체의 출처(하위 도메인 제외)에서 오기를 원합니다.

```http
Content-Security-Policy: default-src 'self'
```

### 예제 2

웹 사이트 관리자는 신뢰할 수 있는 도메인 및 모든 하위 도메인의 콘텐츠를 허용하려고 합니다(CSP가 설정된 도메인과 동일할 필요는 없음).

```http
Content-Security-Policy: default-src 'self' example.com \*.example.com
```

### 예제 3

웹 사이트 관리자는 웹 애플리케이션 사용자가 자신의 콘텐츠에 모든 원본의 이미지를 포함할 수 있도록 허용하지만 오디오 또는 비디오 미디어는 신뢰할 수 있는 공급자로 제한하고 모든 스크립트는 신뢰할 수 있는 코드를 호스팅하는 특정 서버로만 제한하려고 합니다.

```http
Content-Security-Policy: default-src 'self'; img-src \*; media-src example.org example.net; script-src userscripts.example.com
```

기본적으로 여기서는 문서 원본의 콘텐츠만 허용되며 다음은 예외로 처리됩니다.

* 이미지는 출처에 상관없이 로드할 수 있습니다("\*" 와일드카드 참고).
* 미디어는 example.org 및 example.net에서만 허용되며 해당 사이트의 하위 도메인에서는 허용되지 않습니다.
* 실행 가능한 스크립트는 userscripts.example.com에서 온 것만 허용됩니다.
### 예제 4

온라인 뱅킹 사이트의 웹 사이트 관리자는 공격자가 요청을 도청하는 것을 방지하기 위해 모든 콘텐츠가 TLS를 사용하여 로드되었는지 확인하려고 합니다.

```http
Content-Security-Policy: default-src https://onlinebanking.example.com
```

서버는 단일 출처인 onlinebanking.example.com에서 특별히 HTTPS를 통해 로드되는 문서에 대한 액세스만 허용합니다.

### 예제 5

웹 메일 사이트의 웹 사이트 관리자는 전자 메일에 HTML을 허용하고 어디에서나 로드된 이미지를 허용하려고 하지만 JavaScript 또는 기타 잠재적으로 위험한 콘텐츠는 허용하지 않으려고 합니다.

```http
Content-Security-Policy: default-src 'self' \*.example.com; img-src \*
```

이 예제에선 `script-src`를 지정하지 않고, `default-src` 지시문을 사용합니다. 즉, 원본 서버에서만 스크립트를 로드할 수 있습니다.

정책 테스트하기
--------

 배포를 쉽게 하기 위해 CSP는 보고 전용 모드로 배포될 수 있습니다. 정책이 시행되지는 않지만 모든 위반 사항은 제공된 URI로 보고됩니다.
 추가적으로, 보고서 전용 헤더를 사용하여 정책을 실제로 배포하지 않고 정책에 대한 향후 개정을 테스트할 수도 있습니다.

`Content-Security-Policy-Report-Only` (en-US) HTTP 헤더를 사용하여 다음과 같이 정책을 지정할 수 있습니다.

```http
Content-Security-Policy-Report-Only: policy
```

`Content-Security-Policy-Report-Only` (en-US) 헤더와 `Content-Security-Policy` (en-US) 헤더가 모두 동일한 응답에 있으면, 두 정책은 모두 적용됩니다.
 `Content-Security-Policy-Report-Only` 정책은 보고서를 생성하지만 시행되지 않는 반면, `Content-Security-Policy` 헤더에 지정된 정책은 시행됩니다.

보고 활성화
------

기본적으로 위반 보고서는 전송되지 않습니다. 위반 보고를 활성화하려면 아래와 같이 보고서를 전달받을 하나 이상의 URI를 `report-to` 정책 지시문에 지정해야 합니다.

```http
Content-Security-Policy: default-src 'self'; report-to http://reportcollector.example.com/collector.cgi
```

그런 다음 보고서를 수신하도록 서버를 설정해야 하는데, 사용자가 적절하다고 판단하는 방식으로 데이터를 저장하거나 처리하면 됩니다.

위반 보고서 구문
---------

보고서 JSON 객체는 `application/csp-report` `Content-Type`과 함께 전송되며 다음 데이터를 포함합니다.

`blocked-uri`

콘텐츠 보안 정책에 의해 로드가 차단된 리소스의 URI입니다. 차단된 URI가 `document-uri`와 다른 출처인 경우, 차단된 URI는 스키마, 호스트 그리고 포트만 포함되도록 자릅니다.

`disposition`

`Content-Security-Policy-Report-Only` (en-US) 헤더 또는 `Content-Security-Policy` 헤더 사용 여부에 따라 `"enforce"` 또는 `"report"`로 나타납니다.

`document-uri`

위반이 발생한 문서의 URI입니다.

`effective-directive`

정책 시행으로 인해 위반이 발생한 지시문입니다. 실제로 적용된 지시문이 `style-src`인 경우에 Chrome이 `style-src-elem`/`style-src-attr`을 제공하는 것과 같이 일부 브라우저는 다른 값을 제공할 수 있습니다.

`original-policy`

`Content-Security-Policy` HTTP 헤더에 지정된 원래 정책입니다.

`referrer`
지원이 중단되었습니다

비표준

위반이 발생한 문서의 리퍼러입니다.

`script-sample`

위반을 일으킨 인라인 스크립트, 이벤트 처리기 또는 스타일의 처음 40자입니다. `'report-sample'`이 포함된 `script-src*`와 `style-src*` 위반에만 적용 가능합니다.

`status-code`

전역 객체가 인스턴스화된 리소스의 HTTP 상태 코드입니다.

`violated-directive`
지원이 중단되었습니다

위반이 발생한 지시문입니다. `violated-directive`는 `effective-directive` 필드의 역사적 이름이며 동일한 값을 가집니다.

위반 보고서 샘플
---------

`http://example.com/signup.html`에 있는 페이지를 생각해 봅시다. 다음 정책을 사용하여 `cdn.example.com`의 스타일시트를 제외한 모든 항목은 허용하지 않도록 설정합니다.

```http
Content-Security-Policy: default-src 'none'; style-src cdn.example.com; report-to /\_/csp-reports
```

`signup.html`의 HTML은 다음과 같습니다.

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="UTF-8" />
    <title>Sign Up</title>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    여기에 컨텐츠.
  </body>
</html>
```

 실수를 발견 했나요? 스타일시트는 `cdn.example.com`에서만 로드할 수 있지만 웹사이트는 자체 원본(`http://example.com`)에서 스타일시트를 로드하려고 합니다.
 CSP를 적용할 수 있는 브라우저는 문서를 방문할 때 다음 위반 보고서를 `http://example.com/_/csp-reports`에 POST 요청으로 보냅니다.

```json
{
  "csp-report": {
    "blocked-uri": "http://example.com/css/style.css",
    "disposition": "report",
    "document-uri": "http://example.com/signup.html",
    "effective-directive": "style-src-elem",
    "original-policy": "default-src 'none'; style-src cdn.example.com; report-to /\_/csp-reports",
    "referrer": "",
    "status-code": 200,
    "violated-directive": "style-src-elem"
  }
}
```

 보시다시피 보고서에는 `blocked-uri`의 위반 리소스에 대한 전체 경로가 포함됩니다. 하지만 항상 그런 것은 아닙니다. 예를 들어, `signup.html`이 `http://anothercdn.example.com/stylesheet.css`에서 CSS를 로드하려고 하면 브라우저는 전체 경로를 포함하지 **않고** 원본(`http://anothercdn.example.com`)만 포함시킵니다.
 CSP 명세서에서 이 이상한 동작에 대한 설명을 들을 수 있습니다. 요약하자면 이는 교차 출처 리소스에 대한 민감한 정보의 유출을 방지하기 위함입니다.

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

### 호환성 참고 사항

Safari 웹 브라우저의 일부 버전에는 특정 비호환성이 있으며, 이로 인해 Content Security Policy 헤더가 설정되어 있지만 Same Origin 헤더가 아닌 경우 브라우저가 자체 호스팅된 콘텐츠와 오프사이트 콘텐츠를 차단하고 콘텐츠 보안 정책이 콘텐츠를 허용하지 않기 때문에 콘텐츠를 잘못 보고합니다.

같이 보기
-----

* `Content-Security-Policy` (en-US) HTTP 헤더
* `Content-Security-Policy-Report-Only` (en-US) HTTP 헤더
* WebExtensions의 콘텐츠 보안 (en-US)
* 웹 워커의 CSP (en-US)
* 개인 정보 보호, 권한 및 정보 보안 (en-US)
* CSP 평가자 - 여러분의 콘텐츠 보안 정책을 평가할 수 있습니다.


HTTP 개요 - HTTP

HTTP 개요
=======

**HTTP는 HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는** 프로토콜입니다. HTTP는 웹에서 이루어지는 모든 데이터 교환의 기초이며, 클라이언트-서버 프로토콜이기도 합니다. 클라이언트-서버 프로토콜이란 (보통 웹브라우저인) 수신자 측에 의해 요청이 초기화되는 프로토콜을 의미합니다. 하나의 완전한 문서는 텍스트, 레이아웃 설명, 이미지, 비디오, 스크립트 등 불러온(fetched) 하위 문서들로 재구성됩니다.

![웹 문서는 다른 리소스들의 구성](/ko/docs/Web/HTTP/Overview/fetching_a_page.png)

클라이언트와 서버들은 (데이터 스트림과 대조적으로) 개별적인 메시지 교환에 의해 통신합니다. 보통 브라우저인 클라이언트에 의해 전송되는 메시지를 요청(*requests*)이라고 부르며, 그에 대해 서버에서 응답으로 전송되는 메시지를 응답(*responses*)이라고 부릅니다.

![TCP(전송 계층) 및 IP(네트워크 계층) 위 및 표시 계층 아래의 응용 계층 프로토콜로서의 HTTP.](/ko/docs/Web/HTTP/Overview/http-layers.png)

1990년대 초에 설계된 HTTP는 거듭하여 진화해온 확장 가능한 프로토콜입니다. HTTP는 애플리케이션 계층의 프로토콜로, 신뢰 가능한 전송 프로토콜이라면 이론상으로는 무엇이든 사용할 수 있으나 TCP 혹은 암호화된 TCP 연결인 TLS를 통해 전송됩니다. HTTP의 확장성 덕분에, 오늘날 하이퍼텍스트 문서 뿐만 아니라 이미지와 비디오 혹은 HTML 폼 결과와 같은 내용을 서버로 포스트(POST)하기 위해서도 사용됩니다. HTTP는 또한 필요할 때마다 웹 페이지를 갱신하기 위해 문서의 일부를 가져오는데 사용될 수도 있습니다.

HTTP 기반 시스템의 구성요소
-----------------

HTTP는 클라이언트-서버 프로토콜입니다. 요청은 하나의 개체, 사용자 에이전트(또는 그것을 대신하는 프록시)에 의해 전송됩니다. 대부분의 경우, 사용자 에이전트는 브라우저지만, 무엇이든 될 수 있습니다. 예를 들어, 검색 엔진 인덱스를 채워넣고 유지하기 위해 웹을 돌아다니는 로봇이 그러한 경우입니다.

각각의 개별적인 요청들은 서버로 보내지며, 서버는 요청을 처리하고 *response*라고 불리는 응답을 제공합니다. 이 요청과 응답 사이에는 여러 개체들이 있는데, 예를 들면 다양한 작업을 수행하는 게이트웨이 또는 캐시 역할을 하는 프록시 등이 있습니다.

![클라이언트 서버 체인](/ko/docs/Web/HTTP/Overview/client-server-chain.png)

실제로는 브라우저와 요청을 처리하는 서버 사이에는 좀 더 많은 컴퓨터들이 존재합니다: 라우터, 모뎀 등이 있죠. 웹의 계층적인 설계 덕분에, 이들은 네트워크와 전송 계층 내로 숨겨집니다. HTTP은 애플리케이션 계층의 최상위에 있습니다. 네트워크 문제를 진단하는 것도 중요하지만, 기본 레이어들은 HTTP의 명세와는 거의 관련이 없습니다.

### 클라이언트: 사용자 에이전트

사용자 에이전트는 사용자를 대신하여 동작하는 모든 도구입니다. 이 역할은 주로 브라우저에 의해 수행됩니다; 엔지니어들과 자신들의 애플리케이션을 디버그하는 웹 개발자들이 사용하는 프로그램들은 예외입니다.

브라우저는 **항상** 요청을 보내는 개체입니다. 그것은 결코 서버가 될 수 없습니다(수년에 걸쳐 서버 초기화된 메시지를 시뮬레이션하기 위해 몇 가지 메커니즘이 추가되어 왔지만).

웹 페이지를 표시하기 위해, 브라우저는 페이지의 HTML 문서를 가져오기 위한 요청을 전송한 뒤, 파일을 구문 분석하여 실행해야 할 스크립트 그리고 페이지 내 포함된 하위 리소스들(보통 이미지와 비디오)을 잘 표시하기 위한 레이아웃 정보(CSS)에 대응하는 추가적인 요청들을 가져옵니다. 그런 뒤에 브라우저는 완전한 문서인 웹 페이지를 표시하기 위해 그런 리소스들을 혼합합니다. 브라우저에 의해 실행된 스크립트는 이후 단계에서 좀 더 많은 리소스들을 가져올 수 있으며 브라우저는 그에 따라 웹 페이지를 갱신하게 됩니다.

웹 페이지는 하이퍼텍스트 문서로, 표시된 텍스트의 일부는 사용자가 사용자 에이전트를 제어하고 웹을 돌아다닐 수 있도록 새로운 웹 페이지를 가져오기 위해 실행(보통 마우스 클릭에 의해)될 수 있는 링크임을 뜻합니다. 브라우저는 HTTP 요청 내에서 이런 지시 사항들을 변환하고 HTTP 응답을 해석하여 사용자에게 명확한 응답을 표시합니다.

### 웹 서버

통신 채널의 반대편에는 클라이언트에 의한 요청에 대한 문서를 *제공*하는 서버가 존재합니다. 서버는 사실 상 논리적으로 단일 기계입니다.이는 로드(로드 밸런싱) 혹은 그때 그때 다른 컴퓨터(캐시, DB 서버, e-커머스 서버 등과 같은)들의 정보를 얻고 완전하게 혹은 부분적으로 문서를 생성하는 소프트웨어의 복잡한 부분을 공유하는 서버들의 집합일 수도 있기 때문입니다.

서버는 반드시 단일 머신일 필요는 없지만, 여러 개의 서버를 동일한 머신 위에서 호스팅 할 수는 있습니다. HTTP/1.1과 `Host` 헤더를 이용하여, 동일한 IP 주소를 공유할 수도 있습니다.

### 프록시

웹 브라우저와 서버 사이에서는 수많은 컴퓨터와 머신이 HTTP 메시지를 이어 받고 전달합니다. 여러 계층으로 이루어진 웹 스택 구조에서 이러한 컴퓨터/머신들은 대부분은 전송, 네트워크 혹은 물리 계층에서 동작하며, 성능에 상당히 큰 영향을 주지만 HTTP 계층에서는 이들이 어떻게 동작하는지 눈에 보이지 않습니다. 이러한 컴퓨터/머신 중에서도 애플리케이션 계층에서 동작하는 것들을 일반적으로 **프록시**라고 부릅니다. 프록시는 눈에 보이거나 그렇지 않을 수도 있으며(프록시를 통해 요청이 변경되거나 변경되지 않는 경우를 말함) 다양한 기능들을 수행할 수 있습니다:

* 캐싱 (캐시는 공개 또는 비공개가 될 수 있습니다 (예: 브라우저 캐시))
* 필터링 (바이러스 백신 스캔, 유해 컨텐츠 차단(자녀 보호) 기능)
* 로드 밸런싱 (여러 서버들이 서로 다른 요청을 처리하도록 허용)
* 인증 (다양한 리소스에 대한 접근 제어)
* 로깅 (이력 정보를 저장)
HTTP의 기초적인 측면
-------------

### HTTP은 간단합니다

HTTP는 사람이 읽을 수 있으며 간단하게 고안되었습니다. 심지어 HTTP/2가 다소 더 복잡해졌지만 여전히 HTTP 메세지를 프레임별로 캡슐화하여 간결함을 유지하였습니다. HTTP 메시지들은 사람이 읽고 이해할 수 있어, 테스트하기 쉽고 초심자의 진입장벽을 낮췄습니다.

### HTTP은 확장 가능합니다

HTTP/1.0에서 소개된, HTTP 헤더는 HTTP를 확장하고 실험하기 쉽게 만들어주었습니다. 클라이언트와 서버가 새로운 헤더의 시맨틱에 대해 간단한 합의만 한다면, 언제든지 새로운 기능을 추가할 수 있습니다.

### HTTP은 상태는 없지만 세션은 있습니다

 HTTP는 상태를 저장하지 않습니다(Stateless). 동일한 연결 상에서 연속하여 전달된 두 개의 요청 사이에는 연결고리가 없습니다. 이는 e-커머스 쇼핑 바구니처럼, 일관된 방식으로 사용자가 페이지와 상호작용하길 원할 때 문제가 됩니다. 하지만, HTTP의 핵심은 상태가 없는 것이지만 HTTP 쿠키는 상태가 있는 세션을 만들도록 해줍니다.
 헤더 확장성을 사용하여, 동일한 컨텍스트 또는 동일한 상태를 공유하기 위해 각각의 요청들에 세션을 만들도록 HTTP 쿠키가 추가됩니다.

### HTTP와 연결

연결은 전송 계층에서 제어되므로 근본적으로 HTTP 영역 밖입니다. HTTP는 연결될 수 있도록 하는 근본적인 전송 프로토콜을 요구하지 않습니다; 다만 그저 신뢰할 수 있거나 메시지 손실이 없는(최소한의 오류는 표시) 연결을 요구할 뿐입니다. 인터넷 상의 가장 일반적인 두 개의 전송 프로토콜 중에서 TCP는 신뢰할 수 있으며 UDP는 그렇지 않습니다. 그러므로 HTTP는 연결이 필수는 아니지만 연결 기반인 TCP 표준에 의존합니다.

클라이언트와 서버가 HTTP를 요청/응답으로 교환하기 전에 여러 왕복이 필요한 프로세스인 TCP 연결을 설정해야 합니다. HTTP/1.0의 기본 동작은 각 요청/응답에 대해 별도의 TCP 연결을 여는 것입니다. 이 동작은 여러 요청을 연속해서 보내는 경우에는 단일 TCP 연결을 공유하는 것보다 효율적이지 못합니다.

이러한 결함을 개선하기 위해, HTTP/1.1은 (구현하기 어렵다고 입증된) 파이프라이닝 개념과 지속적인 연결의 개념을 도입했습니다: 기본적인 TCP 연결은 `Connection` 헤더를 사용해 부분적으로 제어할 수 있습니다. HTTP/2는 연결을 좀 더 지속되고 효율적으로 유지하는데 도움이 되도록, 단일 연결 상에서 메시지를 다중 전송(multiplex)하여 한 걸음 더 나아갔습니다.

HTTP에 더 알맞은 좀 더 나은 전송 프로토콜을 설계하는 실험이 진행 중에 있습니다. 예를 들어, 구글은 좀 더 신뢰성있고 효율적인 전송 프로토콜을 제공하기 위해 UDP기반의 QUIC를 실험하고 있습니다.

HTTP로 제어할 수 있는 것
----------------

HTTP의 확장 가능한 특성은 수년 간에 걸쳐 웹의 점점 더 많은 기능들을 제어하도록 허용되어 왔습니다. 캐시 혹은 인증 메서드는 HTTP에 초기부터 제어해왔던 기능이며, 반면에 `origin` 제약사항을 완화시키는 조치는 2010년에 들어서 추가되었습니다.

다음은 HTTP 사용하여 제어 가능한 일반적인 기능 목록입니다.

* **캐시**
    + HTTP로 문서가 캐시되는 방식을 제어할 수 있습니다. 서버는 캐시 대상과 기간을 프록시와 클라이언트에 지시할 수 있고 클라이언트는 저장된 문서를 무시하라고 중간 캐시 프록시에게 지시할 수 있습니다.
* **`origin` 제약사항을 완화하기**
    + 스누핑과 다른 프라이버시 침해를 막기 위해, 브라우저는 웹 사이트 간의 엄격한 분리를 강제합니다. **동일한 origin**으로부터 온 페이지만이 웹 페이지의 전체 정보에 접근할 수 있죠. 그런 제약 사항은 서버에 부담이 되지만, HTTP 헤더를 통해 그것을 완화시킬 수 있습니다. 그런 덕분에 문서는 다른 도메인으로부터 전달된 정보를 패치워크할 수 있습니다(그렇게 하려면 어떤 경우에 보안과 관련된 사항이 있을 수도 있습니다).
* **인증**
    + 어떤 페이지들은 보호되어 오로지 특정 사용자만이 그것에 접근할 수도 있습니다. 기본 인증은 HTTP를 통해 `WWW-Authenticate` (en-US) 또는 유사한 헤더를 사용해 제공되거나, HTTP 쿠키를 사용해 특정 세션을 설정하여 이루어질 수도 있습니다.
* **프록시와 터널링 (en-US)**
    + 서버 혹은 클라이언트 혹은 그 둘 모두는 종종 인트라넷에 위치하며 다른 개체들에게 그들의 실제 주소를 숨기기도 합니다. HTTP 요청은 네트워크 장벽을 가로지르기 위해 프록시를 통해 나가게 되죠. 모든 프록시가 HTTP 프록시는 아닙니다. 예를 들면 SOCKS 프로토콜은 좀 더 저수준에서 동작합니다. FTP와 같은 다른 프로토콜도 이 프록시를 통해 처리될 수 있습니다.
* **세션**
    + 쿠키 사용은 서버 상태를 요청과 연결하도록 해줍니다. 이것은 HTTP가 기본적으로 상태없는 프로토콜임에도 세션을 만들어주는 계기가 됩니다. 이것은 e-커머스 쇼핑 바구니를 위해서 유용할 뿐만 아니라 사용자 구성을 허용하는 모든 사이트에 대해서 유용합니다.
HTTP 흐름
-------

클라이언트가 서버와 통신하고자 할 때, 최종 서버가 됐든 중간 프록시가 됐든 다음 단계의 과정을 수행합니다.

1. TCP 연결을 엽니다. TCP 연결은 요청을 보내거나(혹은 여러 개의 요청) 응답을 받는데 사용됩니다. 클라이언트는 새 연결을 열거나, 기존 연결을 재사용하거나, 서버에 대한 여러 TCP 연결을 열 수 있습니다.
2. HTTP 메시지를 전송합니다. HTTP 메시지(HTTP/2 이전)는 인간이 읽을 수 있습니다. HTTP/2에서는 이런 간단한 메시지가 프레임 속으로 캡슐화되어 직접 읽는게 불가능하지만 원칙은 동일합니다.

```http
GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
```

3. 서버에 의해 전송된 응답을 읽어들입니다

```http
HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

<!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
```

4. 연결을 닫거나 다른 요청들을 위해 재사용합니다.

HTTP 파이프라이닝이 활성화되면, 첫번째 응답을 완전히 수신할 때까지 기다리지 않고 여러 요청을 보낼 수 있습니다. HTTP 파이프라이닝은 오래된 소프트웨어와 최신 버전이 공존하고 있는, 기존의 네트워크 상에서 구현하기 어렵다는게 입증되었으며, 프레임안에서 보다 활발한 다중 요청을 보내는 HTTP/2로 교체되고 있습니다.

HTTP 메시지
--------

HTTP/1.1와 초기 HTTP 메시지는 사람이 읽을 수 있습니다. HTTP/2에서, 이 메시지들은 새로운 이진 구조인 프레임 안으로 임베드되어, 헤더의 압축과 다중화와 같은 최적화를 가능케 합니다. 본래의 HTTP 메시지의 일부분만이 이 버전의 HTTP 내에서 전송된다고 할지라도, 각 메시지의 의미들은 변화하지 않으며 클라이언트는 본래의 HTTP/1.1 요청을 (가상으로) 재구성합니다. 그러므로 HTTP/1.1 포맷 내에서 HTTP/2를 이해하는 것은 여전히 유용합니다.

HTTP 메시지의 두 가지 타입인 요청(requests)과 응답(responses)은 각자의 특성있는 형식을 가지고 있습니다.

### 요청

요청은 다음의 요소들로 구성됩니다.

![HTTP 요청](/ko/docs/Web/HTTP/Overview/http_request.png)

* HTTP 메서드, 보통 클라이언트가 수행하고자 하는 동작을 정의한 `GET`, `POST` 같은 동사나 `OPTIONS`나 `HEAD`와 같은 명사입니다. 일반적으로, 클라이언트는 리소스를 가져오거나(`GET`을 사용하여) HTML 폼 (en-US)의 데이터를 전송(`POST`를 사용하여)하려고 하지만, 다른 경우에는 다른 동작이 요구될 수도 있습니다.
* 가져오려는 리소스의 경로; 예를 들면 프로토콜 (`http://`), 도메인 (여기서는 `developer.mozilla.org`), 또는 TCP 포트 (여기서는 `80`)인 요소들을 제거한 리소스의 URL입니다.
* HTTP 프로토콜의 버전.
* 서버에 대한 추가 정보를 전달하는 선택적 헤더들.
* `POST`와 같은 몇 가지 메서드를 위한, 전송된 리소스를 포함하는 응답의 본문과 유사한 본문.
### 응답

응답은 다음의 요소들로 구성됩니다.

![HTTP 응답](/ko/docs/Web/HTTP/Overview/http_response.png)

* HTTP 프로토콜의 버전
* 요청의 성공 여부와, 그 이유를 나타내는 상태 코드
* 아무런 영향력이 없는, 상태 코드의 짧은 설명을 나타내는 상태 메시지
* 요청 헤더와 비슷한, HTTP 헤더들
* 선택 사항으로 가져온 리소스가 포함되는 본문
HTTP 기반 API
-----------

HTTP 기반으로 가장 일반적으로 사용된 API는 user agent와 서버간에 데이터를 교환하는데 사용될 수 있는 `XMLHttpRequest` API 입니다. 최신 `Fetch API`는 보다 강력하고 유연한 기능을 제공합니다.

또 다른 API인 서버-전송 이벤트는 서버가 전송 메커니즘으로 HTTP를 사용하여, 클라이언트로 이벤트를 보낼 수 있도록 하는 단방향 서비스입니다. 클라이언트는 `EventSource` (en-US) 인터페이스를 사용하여, 연결을 맺고 이벤트 핸들러를 설정합니다. 클라이언트 브라우저는 HTTP 스트림으로 도착한 메시지를 적절한 `Event` 객체로 자동 변환하여, 알려진 경우 해당 이벤트 `type`에 대해 등록된 이벤트 핸들러로 전달하거나 또는 특정 유형의 이벤트가 설정되지 않은 경우에는 `onmessage` (en-US) 이벤트 핸들러로 전달합니다.

결론
--

HTTP는 사용이 쉬운 확장 가능한 프로토콜입니다. 헤더를 쉽게 추가하는 능력을 지닌 클라이언트-서버 구조는 HTTP가 웹의 확장된 수용력과 함께 발전할 수 있게 합니다.

HTTP/2가 성능 향상을 위해 HTTP 메시지를 프레임 내로 임베드하여 약간의 복잡함을 더했을지라도, 애플리케이션의 관점에서 볼 때, 메시지의 기본적인 구조는 HTTP/1.0이 릴리즈된 이후와 동일합니다. 세션의 흐름은 여전히 단순하여, 간단한 HTTP 메시지 모니터를 이용한 조사와 디버그를 가능하게 해줍니다.


교차 출처 리소스 공유 (CORS) - HTTP

교차 출처 리소스 공유 (CORS)
===================

**교차 출처 리소스 공유**(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행합니다.

교차 출처 요청의 예시: `https://domain-a.com`의 프론트 엔드 JavaScript 코드가 `XMLHttpRequest`를 사용하여 `https://domain-b.com/data.json`을 요청하는 경우.

보안 상의 이유로, 브라우저는 스크립트에서 시작한 교차 출처 HTTP 요청을 제한합니다. 예를 들어, `XMLHttpRequest`와 Fetch API는 동일 출처 정책을 따릅니다. 즉, 이 API를 사용하는 웹 애플리케이션은 자신의 출처와 동일한 리소스만 불러올 수 있으며, 다른 출처의 리소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 합니다.
 ![](/ko/docs/Web/HTTP/CORS/cors_principle.png)

CORS 체제는 브라우저와 서버 간의 안전한 교차 출처 요청 및 데이터 전송을 지원합니다. 최신 브라우저는 `XMLHttpRequest` 또는 Fetch와 같은 API에서 CORS를 사용하여 교차 출처 HTTP 요청의 위험을 완화합니다.

이 글은 누가 읽어야 하나요?
----------------

모든 사람이요, 진짜로.

명확히 말하자면, 이 글은 **웹 관리자**, **서버 개발자** 그리고 **프론트엔드 개발자**를 위한 것입니다. 최신 브라우저는 헤더와 정책 집행을 포함한 클라이언트 측 교차 출처 공유를 처리합니다. 그러나 CORS 표준에 맞춘다는 것은 서버에서도 새로운 요청과 응답 헤더를 처리해야 한다는 것입니다. 서버 개발자에게는 (PHP 코드 조각과 함께 하는) 서버 관점의 교차 출처 공유를 다루고 있는 다른 글로 보충하면 도움이 될 것입니다.

어떤 요청이 CORS를 사용하나요?
-------------------

교차 출처 공유 표준은 다음과 같은 경우에 사이트간 HTTP 요청을 허용합니다.

* 위에서 논의한 바와 같이, `XMLHttpRequest`와 Fetch API 호출.
* 웹 폰트(CSS 내 `@font-face`에서 교차 도메인 폰트 사용 시), so that servers can deploy TrueType fonts that can only be cross-site loaded and used by web sites that are permitted to do so.
* WebGL 텍스쳐.
* `drawImage()` (en-US)를 사용해 캔버스에 그린 이미지/비디오 프레임.
* 이미지로부터 추출하는 CSS Shapes. (en-US)

이 글은 교차 출처 리소스 공유에 대한 일반적인 논의이며 필요한 HTTP 헤더에 대한 내용도 포함하고 있습니다.

기능적 개요
------

교차 출처 리소스 공유 표준은 웹 브라우저에서 해당 정보를 읽는 것이 허용된 출처를 서버에서 설명할 수 있는 새로운 HTTP 헤더를 추가함으로써 동작합니다. 추가적으로, 서버 데이터에 부수 효과(side effect)를 일으킬 수 있는 HTTP 요청 메서드(`GET`을 제외한 HTTP 메서드)에 대해, CORS 명세는 브라우저가 요청을 `OPTIONS` 메서드로 "프리플라이트"(preflight, 사전 전달)하여 지원하는 메서드를 요청하고, 서버의 "허가"가 떨어지면 실제 요청을 보내도록 요구하고 있습니다. 또한 서버는 클라이언트에게 요청에 "인증정보"(쿠키, HTTP 인증)를 함께 보내야 한다고 알려줄 수도 있습니다.

CORS 실패는 오류의 원인이지만, 보안상의 이유로 JavaScript에서는 오류의 상세 정보에 접근할 수 없으며, 알 수 있는 것은 오류가 발생했다는 사실 뿐입니다. 정확히 어떤 것이 실패했는지 알아내려면 브라우저의 콘솔을 봐야 합니다.

이후 항목에서는 시나리오와 함께, 사용한 HTTP 헤더의 상세 내용을 다룹니다.

접근 제어 시나리오 예제
-------------

교차 출처 리소스 공유가 동작하는 방식을 보여주는 세 가지 시나리오를 제시하겠습니다. 모든 예제는 지원하는 브라우저에서 교차 출처 요청을 생성할 수 있는 `XMLHttpRequest`를 사용합니다.

서버 관점의 교차 출처 리소스 공유에 대한 논의는 (PHP 코드와 함께 하는) 서버 사이드 접근 제어 (CORS) 문서에서 확인할 수 있습니다.

### 단순 요청(Simple requests)

일부요청은 CORS preflight 를 트리거하지 않습니다. `Fetch` 명세(CORS를 정의한)는 이 용어를 사용하지 않지만, 이 기사에서는 "simple requests"라고 하겠습니다. "simple requests"는 **다음 조건을 모두 충족하는 요청입니다:**

* 다음 중 하나의 메서드
    + `GET`
    + `HEAD`
    + `POST`
* 유저 에이전트가 자동으로 설정 한 헤더 (예를들어, `Connection`, `User-Agent` (en-US), Fetch 명세에서 "forbidden header name"으로 정의한 헤더)외에, 수동으로 설정할 수 있는 헤더는 오직 Fetch 명세에서 "CORS-safelisted request-header"로 정의한 헤더 뿐입니다.
    + `Accept`
    + `Accept-Language`
    + `Content-Language`
    + `Content-Type` (아래의 추가 요구 사항에 유의하세요.)
* `Content-Type` 헤더는 다음의 값들만 허용됩니다.
    + `application/x-www-form-urlencoded`
    + `multipart/form-data`
    + `text/plain`
* 요청에 사용된 `XMLHttpRequestUpload` (en-US) 객체에는 이벤트 리스너가 등록되어 있지 않습니다. 이들은 `XMLHttpRequest.upload` 프로퍼티를 사용하여 접근합니다..
* 요청에 `ReadableStream` 객체가 사용되지 않습니다.

**참고:** 이는 웹 컨텐츠가 이미 발행할 수 있는 것과 동일한 종류의 cross-site 요청입니다. 서버가 적절한 헤더를 전송하지 않으면 요청자에게 응답 데이터가 공개되지 않습니다. 따라서 cross-site 요청 위조를 방지하는 사이트는 HTTP 접근 제어를 두려워 할 만한 부분이 없습니다.

**참고:** **주의:** WebKit Nightly 와 Safari Technology Preview 는 `Accept`, `Accept-Language`, `Content-Language` 헤더에서 허용되는 값에 대한 추가 제약이 있습니다. 이러한 헤더 중 하나에 "nonstandard" 값이 존재하면, WebKit/Safari 는 더이상 요청을 "simple request"로 간주하지 않습니다. 다음 Webkit 버그 외에 WebKit/Safari 가 "nonstandard" 으로 간주하는 값은 문서화되어 있지 않습니다.

* Require preflight for non-standard CORS-safelisted request headers Accept, Accept-Language, and Content-Language
* Allow commas in Accept, Accept-Language, and Content-Language request headers for simple CORS
* Switch to a blacklist model for restricted Accept headers in simple CORS requests

이 부분은 명세가 아니기 때문에 다른 브라우저에는 이러한 추가 제한 사항이 없습니다.

예를들어, `https://foo.example` 의 웹 컨텐츠가 `https://bar.other` 도메인의 컨텐츠를 호출하길 원합니다. `foo.example`에 배포된 JavaScript에는 아래와 같은 코드가 사용될 수 있습니다.
```

const xhr = new XMLHttpRequest();
const url = 'https://bar.other/resources/public-data/';

xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();
```

클라이언트와 서버간에 간단한 통신을 하고, CORS 헤더를 사용하여 권한을 처리합니다.

![](/ko/docs/Web/HTTP/CORS/simple-req-updated.png)

이 경우 브라우저가 서버로 전송하는 내용을 살펴보고, 서버의 응답을 확인합니다.
```

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
```

요청 헤더의 `Origin`을 보면, `https://foo.example`로부터 요청이 왔다는 것을 알 수 있습니다.
```

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[…XML Data…]
```

서버는 이에 대한 응답으로 `Access-Control-Allow-Origin` 헤더를 다시 전송합니다. 가장 간단한 접근 제어 프로토콜은 `Origin` 헤더와 `Access-Control-Allow-Origin` 을 사용하는 것입니다. 이 경우 서버는 `Access-Control-Allow-Origin: *`, 으로 응답해야 하며, 이는 **모든** 도메인에서 접근할 수 있음을 의미합니다. `https://bar.other` 의 리소스 소유자가 *오직* `https://foo.example` 의 요청만 리소스에 대한 접근을 허용하려는 경우 다음을 전송합니다.
```

Access-Control-Allow-Origin: https://foo.example
```

이제 `https://foo.example` 이외의 도메인은 cross-site 방식으로 리소스에 접근할 수 없습니다. 리소스에 대한 접근을 허용하려면, `Access-Control-Allow-Origin` 헤더에는 요청의 `Origin` 헤더에서 전송된 값이 포함되어야 합니다.

### 프리플라이트 요청

"preflighted" request는 위에서 논의한 "simple requests" 와는 달리, 먼저 `OPTIONS` 메서드를 통해 다른 도메인의 리소스로 HTTP 요청을 보내 실제 요청이 전송하기에 안전한지 확인합니다. cross-origin 요청은 유저 데이터에 영향을 줄 수 있기 때문에 이와같이 미리 전송(preflighted)합니다.

다음은 preflighted 할 요청의 예제입니다.
```

const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://bar.other/resources/post-here/');
xhr.setRequestHeader('Ping-Other', 'pingpong');
xhr.setRequestHeader('Content-Type', 'application/xml');
xhr.onreadystatechange = handler;
xhr.send('<person><name>Arun</name></person>');
```

위의 예제는 `POST` 요청과 함께 함께 보낼 XML body를 만듭니다. 또한 비표준 HTTP `Ping-Other` 요청 헤더가 설정됩니다. 이러한 헤더는 HTTP/1.1의 일부가 아니지만 일반적으로 웹 응용 프로그램에 유용합니다. Content-Type 이 `application/xml`이고, 사용자 정의 헤더가 설정되었기 때문에 이 요청은 preflighted 처리됩니다.

![](/ko/docs/Web/HTTP/CORS/preflight_correct.png)

(참고: 아래 설명 된 것처럼 실제 `POST` 요청에는 `Access-Control-Request-*` 헤더가 포함되지 않습니다. `OPTIONS` 요청에만 필요합니다.)

클라이언트와 서버간의 완전한 통신을 살펴보겠습니다. 첫 번째 통신은 *preflight request/response*입니다.
```

OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: http://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

HTTP/1.1 204 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
```

preflight request가 완료되면 실제 요청을 전송합니다.
```

POST /resources/post-here/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: https://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: https://foo.example
Pragma: no-cache
Cache-Control: no-cache

<person><name>Arun</name></person>

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some GZIP'd payload]
```

첫 번째 예제의 1 - 10 행은 `OPTIONS` 메서드를 사용한 preflight request를 나타냅니다. 브라우저는 위의 JavaScript 코드 스니펫이 사용중인 요청 파라미터를 기반으로 전송해야 합니다. 그렇게 해야 서버가 실제 요청 파라미터로 요청을 보낼 수 있는지 여부에 응답할 수 있습니다. OPTIONS는 서버에서 추가 정보를 판별하는데 사용하는 HTTP/1.1 메서드입니다. 또한 safe 메서드이기 때문에, 리소스를 변경하는데 사용할 수 없습니다. OPTIONS 요청과 함께 두 개의 다른 요청 헤더가 전송됩니다. (10, 11행)
```

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
```

`Access-Control-Request-Method` 헤더는 preflight request의 일부로, 실제 요청을 전송할 때 `POST` 메서드로 전송된다는 것을 알려줍니다. `Access-Control-Request-Headers` 헤더는 실제 요청을 전송 할 때 `X-PINGOTHER` 와 `Content-Type` 사용자 정의 헤더와 함께 전송된다는 것을 서버에 알려줍니다. 이제 서버는 이러한 상황에서 요청을 수락할지 결정할 수 있습니다.

위의 13 - 22 행은 서버가 요청 메서드와 (`POST`) 요청 헤더를 (`X-PINGOTHER`) 받을 수 있음을 나타내는 응답입니다. 특히 16 - 19행을 살펴보겠습니다.
```

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
```

서버는 `Access-Control-Allow-Methods` 로 응답하고 `POST` 와 `GET` 이 리소스를 쿼리하는데 유용한 메서드라고 가르쳐줍니다. 이 헤더는 `Allow` 응답 헤더와 유사하지만, 접근 제어 컨텍스트 내에서 엄격하게 사용됩니다.

또한 `Access-Control-Allow-Headers` 의 값을 "`X-PINGOTHER, Content-Type`" 으로 전송하여 실제 요청에 헤더를 사용할 수 있음을 확인합니다. `Access-Control-Allow-Methods`와 마찬가지로 `Access-Control-Allow-Headers` 는 쉼표로 구분된 허용 가능한 헤더 목록입니다.

마지막으로`Access-Control-Max-Age`는 다른 preflight request를 보내지 않고, preflight request에 대한 응답을 캐시할 수 있는 시간(초)을 제공합니다. 위의 코드는 86400 초(24시간) 입니다. 각 브라우저의 최대 캐싱 시간은 `Access-Control-Max-Age` 가 클수록 우선순위가 높습니다.

#### Preflighted requests 와 리다이렉트

모든 브라우저가 preflighted request 후 리다이렉트를 지원하지는 않습니다. preflighted request 후 리다이렉트가 발생하면 일부 브라우저는 다음과 같은 오류 메시지를 띄웁니다.

>
> 요청이 'https://example.com/foo'로 리다이렉트 되었으며, preflight가 필요한 cross-origin 요청은 허용되지 않습니다.
>
>
>

>
> 요청에 preflight가 필요합니다. preflight는 cross-origin 리다이렉트를 허용하지 않습니다.
>
>
>

CORS 프로토콜은 본래 그 동작(리다이렉트)이 필요했지만, 이후 더 이상 필요하지 않도록 변경되었습니다. 그러나 모든 브라우저가 변경 사항을 구현하지는 않았기 때문에, 본래의 필요한 동작은 여전히 나타납니다.

브라우저가 명세를 따라잡을 때 까지 다음 중 하나 혹은 둘 다를 수행하여 이 제한을 해결할 수 있습니다.

* preflight 리다이렉트를 방지하기 위해 서버측 동작을 변경
* preflight를 발생시키지 않는 simple request 가 되도록 요청을 변경

이것이 가능하지 않은 경우 다른 방법도 있습니다.

1. Fetch API를 통해 `Response.url` (en-US) 이나 `XMLHttpRequest.responseURL` (en-US)를 사용하여 simple request 를 작성합니다. 이 simple request를 이용하여 실제 preflighted request가 끝나는 URL을 판별하세요.
2. 첫 번째 단계에서 `Response.url` 혹은 `XMLHttpRequest.responseURL` 로부터 얻은 URL을 사용하여 또 다른 요청(실제 요청)을 만듭니다.

그러나 요청에 `Authorization` 헤더가 있기 때문에 preflight를 트리거하는 요청일 경우에, 위의 단계를 사용하여 제한을 제거할 수 없습니다. 또한 요청이 있는 서버를 제어하지 않으면 문제를 해결할 수 없습니다.

### 자격 증명을 포함한 요청

`XMLHttpRequest` 혹은 Fetch 를 사용할 때 CORS 에 의해 드러나는 가장 흥미로운 기능은 "credentialed" requests 입니다. credentialed requests는 HTTP cookies 와 HTTP Authentication 정보를 인식합니다. 기본적으로 cross-site `XMLHttpRequest` 나 Fetch 호출에서 브라우저는 자격 증명을 보내지 **않습니다.** `XMLHttpRequest` 객체나 `Request` 생성자가 호출될 때 특정 플래그를 설정해야 합니다.

이 예제에서 원래 `http://foo.example` 에서 불러온 컨텐츠는 쿠키를 설정하는 `http://bar.other` 리소스에 simple GET request를 작성합니다. foo.example의 내용은 다음과 같은 JavaScript를 포함할 수 있습니다.
```

const invocation = new XMLHttpRequest();
const url = 'http://bar.other/resources/credentialed-content/';

function callOtherDomain() {
  if (invocation) {
    invocation.open('GET', url, true);
    invocation.withCredentials = true;
    invocation.onreadystatechange = handler;
    invocation.send();
  }
}
```

7행은 쿠키와 함께 호출하기위한 `XMLHttpRequest` 의 플래그를 보여줍니다. 이 플래그는 `withCredentials` 라고 불리며 부울 값을 갖습니다. 기본적으로 호출은 쿠키 없이 이루어집니다. 이것은 simple `GET` request이기 때문에 preflighted 되지 않습니다. 그러나 브라우저는 `Access-Control-Allow-Credentials`: `true` 헤더가 없는 응답을 **거부합니다**. 따라서 호출된 웹 컨텐츠에 응답을 제공하지 **않습니다.**

![](/ko/docs/Web/HTTP/CORS/cred-req-updated.png)

클라이언트와 서버간의 통신 예제는 다음과 같습니다.
```

GET /resources/credentialed-content/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Referer: http://foo.example/examples/credential.html
Origin: http://foo.example
Cookie: pageAccess=2

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:34:52 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Credentials: true
Cache-Control: no-cache
Pragma: no-cache
Set-Cookie: pageAccess=3; expires=Wed, 31-Dec-2008 01:34:53 GMT
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 106
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

[text/plain payload]
```

10행에는 `http://bar.other`의 컨텐츠를 대상으로 하는 쿠키가 포함되어 있습니다. 하지만 17행의 `Access-Control-Allow-Credentials`: `true` 로 응답하지 않으면, 응답은 무시되고 웹 컨텐츠는 제공되지 않습니다.

#### 실행 전 요청 및 자격 증명

CORS 실행 전 요청에는 자격 증명이 포함되지 않아야 합니다. 실행 전 요청에 대한 *응답*은 `Access-Control-Allow-Credentials: true`를 지정하여 자격 증명으로 실제 요청을 수행할 수 있음을 나타내야 합니다.

**참고:** #### 참고일부 엔터프라이즈 인증 서비스는 `cors-protocol-and-credentials` 사양을 위반하여 실행 전 요청에서 TLS 클라이언트 인증서를 보내도록 요구합니다.Firefox 87에서는 기본 설정을 지정하여 이 비준수 동작을 활성화할 수 있습니다: `network.cors_preflight.allow_client_cert`을 `true`로 설정 (Firefox bug 1511151). Chromium 기반 브라우저는 현재 항상 CORS 실행 전 요청에서 TLS 클라이언트 인증서를 보냅니다(Chrome bug 775438).

#### 자격증명 요청 및 와일드카드(Credentialed requests and wildcards)

자격 증명 요청에 응답할 때 서버는 **반드시** "`*`" 와일드카드를 지정하는 대신 `Access-Control-Allow-Origin` 헤더 값에 출처를 지정해야 합니다.

위 예제의 요청 헤더에 `Cookie` 헤더가 포함되어 있기 때문에 `Access-Control-Allow-Origin` 헤더의 값이 "\*"인 경우 요청이 실패합니다. 위 요청은 `Access-Control-Allow-Origin` 헤더가 "`*`" 와일드 카드가 아니라 "`http://foo.example`" 본래 주소이기 때문에 자격증명 인식 컨텐츠는 웹 호출 컨텐츠로 리턴됩니다.

위 예제의 `Set-Cookie` 응답 헤더는 추가 쿠키를 설정합니다. 실패한 경우 사용한 API에 따라 예외가 발생합니다.

#### Third-party cookies

CORS 응답에 설정된 쿠키에는 일반적인 third-party cookie 정책이 적용됩니다. 위의 예제는 `foo.example`에서 페이지를 불러지만 20행의 쿠키는 `bar.other` 가 전송합니다. 때문에 사용자의 브라우저 설정이 모든 third-party cookies를 거부하도록 되어 있다면, 이 쿠키는 저장되지 않습니다.

HTTP 응답 헤더
----------

이 섹션에서는 Cross-Origin 리소스 공유 명세에 정의된 대로 서버가 접근 제어 요청을 위해 보내는 HTTP 응답 헤더가 나열되어 있습니다. The previous section gives an overview of these in action.

### Access-Control-Allow-Origin

리턴된 리소스에는 다음 구문과 함께 하나의 `Access-Control-Allow-Origin` 헤더가 있을 수 있습니다.
```

Access-Control-Allow-Origin: <origin> | *
```

`Access-Control-Allow-Origin` 은 단일 출처를 지정하여 브라우저가 해당 출처가 리소스에 접근하도록 허용합니다. 또는 자격 증명이 **없는** 요청의 경우 "`*`" 와일드 카드는 브라우저의 origin에 상관없이 모든 리소스에 접근하도록 허용합니다.

예를들어 `https://mozilla.org` 의 코드가 리소스에 접근 할 수 있도록 하려면 다음과 같이 지정할 수 있습니다.
```

Access-Control-Allow-Origin: https://mozilla.org
```

서버가 "`*`" 와일드카드 대신에 하나의 origin을 지정하는 경우, 서버는 `Vary` 응답 헤더에 `Origin` 을 포함해야 합니다. 이 origin은 화이트 리스트의 일부로 요청 origin에 따라 동적으로 변경될 수 있습니다. 서버 응답이 `Origin` 요청 헤더에 따라 다르다는것을 클라이언트에 알려줍니다.

### Access-Control-Expose-Headers

`Access-Control-Expose-Headers` 헤더를 사용하면 브라우저가 접근할 수 있는 헤더를 서버의 화이트리스트에 추가할 수 있습니다.
```

Access-Control-Expose-Headers: <header-name>[, <header-name>]*
```

예를들면 다음과 같습니다.
```

Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
```

`X-My-Custom-Header` 와 `X-Another-Custom-Header` 헤더가 브라우저에 드러납니다.

### Access-Control-Max-Age

`Access-Control-Max-Age` 헤더는 preflight request 요청 결과를 캐시할 수 있는 시간을 나타냅니다. preflight request 예제는 위를 참조하세요.
```

Access-Control-Max-Age: <delta-seconds>
```

`delta-seconds` 파라미터는 결과를 캐시할 수 있는 시간(초)를 나타냅니다.

### Access-Control-Allow-Credentials

`Access-Control-Allow-Credentials` 헤더는 `credentials` 플래그가 true일 때 요청에 대한 응답을 표시할 수 있는지를 나타냅니다. preflight request에 대한 응답의 일부로 사용하는 경우, credentials을 사용하여 실제 요청을 수행할 수 있는지를 나타냅니다. simple `GET` requests는 preflighted되지 않으므로 credentials이 있는 리소스를 요청하면, 이 헤더가 리소스와 함께 반환되지 않습니다. 이 헤더가 없으면 브라우저에서 응답을 무시하고 웹 컨텐츠로 반환되지 않는다는 점을 주의하세요.
```

Access-Control-Allow-Credentials: true
```

Credentialed requests 은 위에 설명되어 있습니다.

### Access-Control-Allow-Methods

`Access-Control-Allow-Methods` 헤더는 리소스에 접근할 때 허용되는 메서드를 지정합니다. 이 헤더는 preflight request에 대한 응답으로 사용됩니다. 요청이 preflighted 되는 조건은 위에 설명되어 있습니다.
```

Access-Control-Allow-Methods: <method>[, <method>]*
```

이 헤더를 브라우저로 전송하는 예제를 포함하여 preflight request 의 예제는, 위에 나와 있습니다.

### Access-Control-Allow-Headers

preflight request 에 대한 응답으로 `Access-Control-Allow-Headers` 헤더가 사용됩니다. 실제 요청시 사용할 수 있는 HTTP 헤더를 나타냅니다.
```

Access-Control-Allow-Headers: <header-name>[, <header-name>]*
```

HTTP 요청 헤더
----------

이 섹션에는 cross-origin 공유 기능을 사용하기 위해 클라이언트가 HTTP 요청을 발행할 때 사용할 수 있는 헤더가 나열되어 있습니다. 이 헤더는 서버를 호출할 때 설정됩니다. cross-site `XMLHttpRequest` 기능을 사용하는 개발자는 프로그래밍 방식으로 cross-origin 공유 요청 헤더를 설정할 필요가 없습니다.

### Origin

`Origin` 헤더는 cross-site 접근 요청 또는 preflight request의 출처를 나타냅니다.
```

Origin: <origin>
```

origin 은 요청이 시작된 서버를 나타내는 URI 입니다. 경로 정보는 포함하지 않고, 오직 서버 이름만 포함합니다.

**참고:** `origin` 값은 `null` 또는 URI 가 올 수 있습니다.

접근 제어 요청에는 **항상** `Origin` 헤더가 전송됩니다.

### Access-Control-Request-Method

`Access-Control-Request-Method` 헤더는 실제 요청에서 어떤 HTTP 메서드를 사용할지 서버에게 알려주기 위해, preflight request 할 때에 사용됩니다.
```

Access-Control-Request-Method: <method>
```

이 사용법의 예제는 위에서 찾을 수 있습니다.

### Access-Control-Request-Headers

`Access-Control-Request-Headers` 헤더는 실제 요청에서 어떤 HTTP 헤더를 사용할지 서버에게 알려주기 위해, preflight request 할 때에 사용됩니다.
```

Access-Control-Request-Headers: <field-name>[, <field-name>]*
```

이 사용법의 예제는 위에서 찾을 수 있습니다.

명세
--

| Specification |
| --- |
| Fetch Standard # http-access-control-allow-origin |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* CORS errors
* Enable CORS: I want to add CORS support to my server
* `XMLHttpRequest`
* Fetch API
* Will it CORS? - an interactive CORS explainer & generator
* Using CORS with All (Modern) Browsers
* How to run Chrome browser without CORS
* Stack Overflow answer with "how to" info for dealing with common problems:
    + How to avoid the CORS preflight
    + How to use a CORS proxy to get around *"No Access-Control-Allow-Origin header"*
    + How to fix *"Access-Control-Allow-Origin header must not be the wildcard"*


HTTP 기본 - HTTP

HTTP 기본
=======

HTTP는 확장 가능한 프로토콜로 리소스 및 URI(Uniform Resource Identifier), 간단한 메시지 구조, 클라이언트-서버 통신 흐름과 같은 개념에 의존합니다. 이러한 기본 개념을 토대로, 새로운 HTTP 메서드나 헤더의 생성을 통해 새로운 기능과 새로운 의미를 더하는 수많은 확장들이 수년간 생겨났습니다.

글 목록
----

HTTP의 개요

HTTP는 무엇이고 웹 아키텍처에서 그 역할은 무엇인지, 프로토콜 스택에서의 위치를 서술하고 있습니다.

HTTP의 진화

HTTP는 1990년대 초반에 만들어지고 여러번 확장되어 왔습니다. 이 항목에서는 HTTP의 역사에 대해서 훑어보고 HTTP/0.9, HTTP/1.0, HTTP/1.1 그리고 수년에 걸쳐 중요하지는 않지만 새로운 기능이 소개된 현대의 HTTP/2에 대해서 서술하고 있습니다.

리소스와 URIs

리소스에 대한 개념, 식별자, 그리고 웹에서의 위치에 대해서 간략히 소개합니다.

웹 리소스 식별

웹 리소스가 어떻게 참조되는지 그리고 어디에 위치하는지를 서술합니다.

데이터 URL

특정 종류의 URI는 직접 대표하는 리소스를 포함합니다. 데이터 URL은 매우 편리하지만 위험성을 가지고 있습니다.

리소스 URL
비표준

리소스 URL(`resource` 스키마가 접두사로 붙어있는 URL)은 Firefox와 Firefox 확장 프로그램들에서 내적으로 리소스를 로드하기 위해서 사용됩니다. 하지만 몇몇 브라우저로 연결할 수 있는 사이트의 정보로도 사용할 수 있습니다.

MIME 타입

HTTP/1.0부터는 다양한 타입의 콘텐츠를 전송할 수 있습니다. 이 글에서는 `Content-Type` 헤더와 MIME 표준을 사용하여 이를 수행하는 방법을 설명합니다.

www와 비-www URL 중에서 선택하기

이 글에서는 www 접두사 도메인을 사용할지 여부를 선택하는 방법과, 그 선택의 결과에 대한 지침을 제공합니다.

HTTP 세션의 흐름

이 글은 일반적인 HTTP 세션에 대해서 서술합니다. 예를 들어, 당신이 웹 페이지에서 링크 또는 이미지를 클릭하였을 때 무슨 일이 일어나는지를 들 수 있습니다.

HTTP 메시지

HTTP 메시지는 요청 혹은 응답을 하는 도중에 전송됩니며, 아주 명확한 구조를 가지고 있습니다. 이 간략한 글에서는 그 구조, 목적과 가능성에 대해서 서술합니다.

HTTP/2에서의 프레임과 메시지 구조

HTTP/2는 HTTP/1.x 메시지를 바이너리 프레임에 넣어 표시하고 캡슐화를 합니다. 이 글은 그 프레임의 구조, 목적, 그리고 인코드 방법에 대해서 설명합니다.

HTTP/1.x의 연결 관리

HTTP/1.1은 HTTP가 영구적 연결과 파이프라이닝을 지원한 첫 버전입니다. 이 글은 두 개념에 대해서 설명합니다.

HTTP/2에서의 연결 관리

HTTP/2는 어떻게 연결이 생성되고 관리되는지에 대해서 완벽하게 재검토했습니다. 이 글은 어떻게 HTTP 프레임이 멀티플렉싱이 가능한지 그리고 이전 HTTP 버전에서 발생한 'head-of-line' 블로킹 문제를 어떻게 풀었는지에 대해서 설명합니다.

콘텐츠 협상

HTTP는 브라우저가 선호하는 포맷, 언어 또는 인코딩을 알려주는 방법으로 `Accept`로 시작하는 HTTP 헤더 세트를 도입합니다. 이 항목은 어떻게 이러한 협상이 시작하는지, 어떻게 서버가 반응하기를 기대하는지 그리고 어떻게 가장 적절한 응답을 주는지에 대해서 설명합니다.


HTTP 상태 코드 - HTTP

HTTP 상태 코드
==========

HTTP 응답 상태 코드는 특정 HTTP 요청이 성공적으로 완료되었는지 알려줍니다. 응답은 5개의 그룹으로 나누어집니다: 정보를 제공하는 응답, 성공적인 응답, 리다이렉트, 클라이언트 에러, 그리고 서버 에러. 상태 코드는 section 10 of RFC 2616에 정의되어 있습니다.

정보 응답
-----

`100 Continue`

이 임시적인 응답은 지금까지의 상태가 괜찮으며 클라이언트가 계속해서 요청을 하거나 이미 요청을 완료한 경우에는 무시해도 되는 것을 알려줍니다.

`101 Switching Protocol`

이 코드는 클라이언트가 보낸 `Upgrade` (en-US) 요청 헤더에 대한 응답에 들어가며 서버에서 프로토콜을 변경할 것임을 알려줍니다.

`102 Processing` (en-US) (WebDAV)

이 코드는 서버가 요청을 수신하였으며 이를 처리하고 있지만, 아직 제대로 된 응답을 알려줄 수 없음을 알려줍니다.

`103 Early Hints`

이 상태 코드는 주로 `Link` (en-US) 헤더와 함께 사용되어 서버가 응답을 준비하는 동안 사용자 에이전트가(user agent) 사전 로딩(preloading (en-US))을 시작할 수 있도록 한다.

성공 응답
-----

`200 OK`

 요청이 성공적으로 되었습니다. 성공의 의미는 HTTP 메소드에 따라 달라집니다:
 GET: 리소스를 불러와서 메시지 바디에 전송되었습니다.
 HEAD: 개체 해더가 메시지 바디에 있습니다.
 PUT 또는 POST: 수행 결과에 대한 리소스가 메시지 바디에 전송되었습니다.
 TRACE: 메시지 바디는 서버에서 수신한 요청 메시지를 포함하고 있습니다.

`201 Created`

요청이 성공적이었으며 그 결과로 새로운 리소스가 생성되었습니다. 이 응답은 일반적으로 POST 요청 또는 일부 PUT 요청 이후에 따라옵니다.

`202 Accepted`

요청을 수신하였지만 그에 응하여 행동할 수 없습니다. 이 응답은 요청 처리에 대한 결과를 이후에 HTTP로 비동기 응답을 보내는 것에 대해서 명확하게 명시하지 않습니다. 이것은 다른 프로세스에서 처리 또는 서버가 요청을 다루고 있거나 배치 프로세스를 하고 있는 경우를 위해 만들어졌습니다.

`203 Non-Authoritative Information`

이 응답 코드는 돌려받은 메타 정보 세트가 오리진 서버의 것과 일치하지 않지만 로컬이나 서드 파티 복사본에서 모아졌음을 의미합니다. 이러한 조건에서는 이 응답이 아니라 200 OK 응답을 반드시 우선됩니다.

`204 No Content`

요청에 대해서 보내줄 수 있는 콘텐츠가 없지만, 헤더는 의미있을 수 있습니다. 사용자-에이전트는 리소스가 캐시된 헤더를 새로운 것으로 업데이트 할 수 있습니다.

`205 Reset Content`

이 응답 코드는 요청을 완수한 이후에 사용자 에이전트에게 이 요청을 보낸 문서 뷰를 리셋하라고 알려줍니다.

`206 Partial Content`

이 응답 코드는 클라이언트에서 복수의 스트림을 분할 다운로드를 하고자 범위 헤더를 전송했기 때문에 사용됩니다.

`207 Multi-Status` (en-US) (WebDAV)

멀티-상태 응답은 여러 리소스가 여러 상태 코드인 상황이 적절한 경우에 해당되는 정보를 전달합니다.

`208 Multi-Status` (en-US) (WebDAV)

DAV에서 사용됩니다: propstat(property와 status의 합성어) 응답 속성으로 동일 컬렉션으로 바인드된 복수의 내부 멤버를 반복적으로 열거하는 것을 피하기 위해 사용됩니다.

`226 IM Used` (en-US) (HTTP Delta encoding)

서버가 GET 요청에 대한 리소스의 의무를 다 했고, 그리고 응답이 하나 또는 그 이상의 인스턴스 조작이 현재 인스턴스에 적용이 되었음을 알려줍니다.

리다이렉션 메시지
---------

`300 Multiple Choice`

요청에 대해서 하나 이상의 응답이 가능합니다. 사용자 에이전트 또는 사용자는 그중에 하나를 반드시 선택해야 합니다. 응답 중 하나를 선택하는 방법에 대한 표준화 된 방법은 존재하지 않습니다.

`301 Moved Permanently`

이 응답 코드는 요청한 리소스의 URI가 변경되었음을 의미합니다. 새로운 URI가 응답에서 아마도 주어질 수 있습니다.

`302 Found`

이 응답 코드는 요청한 리소스의 URI가 일시적으로 변경되었음을 의미합니다. 새롭게 변경된 URI는 나중에 만들어질 수 있습니다. 그러므로, 클라이언트는 향후의 요청도 반드시 동일한 URI로 해야합니다.

`303 See Other`

클라이언트가 요청한 리소스를 다른 URI에서 GET 요청을 통해 얻어야 할 때, 서버가 클라이언트로 직접 보내는 응답입니다.

`304 Not Modified`

이것은 캐시를 목적으로 사용됩니다. 이것은 클라이언트에게 응답이 수정되지 않았음을 알려주며, 그러므로 클라이언트는 계속해서 응답의 캐시된 버전을 사용할 수 있습니다.

`305 Use Proxy`
지원이 중단되었습니다

이전 버전의 HTTP 기술 사양에서 정의되었으며, 요청한 응답은 반드시 프록시를 통해서 접속해야 하는 것을 알려줍니다. 이것은 프록시의 in-band 설정에 대한 보안상의 걱정으로 인하여 사라져가고 있습니다.

`306 unused`

이 응답 코드는 더이상 사용되지 않으며, 현재는 추후 사용을 위해 예약되어 있습니다. 이것은 HTTP 1.1 기술사양 이전 버전에서 사용되었습니다.

`307 Temporary Redirect`

클라리언트가 요청한 리소스가 다른 URI에 있으며, 이전 요청과 동일한 메소드를 사용하여 요청해야할 때, 서버가 클라이언트에 이 응답을 직접 보냅니다. 이것은 `302 Found` HTTP 응답 코드와 동일한 의미를 가지고 있으며, 사용자 에이전트가 반드시 사용된 HTTP 메소드를 변경하지 말아야 하는 점만 다릅니다: 만약 첫 요청에 `POST`가 사용되었다면, 두번째 요청도 반드시 `POST`를 사용해야 합니다.

`308 Permanent Redirect`

이것은 리소스가 이제 HTTP 응답 헤더의 `Location:` 에 명시된 영구히 다른 URI에 위치하고 있음을 의미합니다. 이것은 `301 Moved Permanently` HTTP 응답 코드와 동일한 의미를 가지고 있으며, 사용자 에이전트가 반드시 HTTP 메소드를 변경하지 말아야 하는 점만 다릅니다: 만약 첫 요청에 `POST`가 사용되었다면, 두번째 요청도 반드시 `POST`를 사용해야 합니다.

클라이언트 에러 응답
-----------

`400 Bad Request`

이 응답은 잘못된 문법으로 인하여 서버가 요청을 이해할 수 없음을 의미합니다.

`401 Unauthorized`

비록 HTTP 표준에서는 "미승인(unauthorized)"를 명확히 하고 있지만, 의미상 이 응답은 "비인증(unauthenticated)"을 의미합니다. 클라이언트는 요청한 응답을 받기 위해서는 반드시 스스로를 인증해야 합니다.

`402 Payment Required`

이 응답 코드는 나중에 사용될 것을 대비해 예약되었습니다. 첫 목표로는 디지털 결제 시스템에 사용하기 위하여 만들어졌지만 지금 사용되고 있지는 않습니다.

`403 Forbidden`

클라이언트는 콘텐츠에 접근할 권리를 가지고 있지 않습니다. 예를들어 그들은 미승인이어서 서버는 거절을 위한 적절한 응답을 보냅니다. 401과 다른 점은 서버가 클라이언트가 누구인지 알고 있습니다.

`404 Not Found`

서버는 요청받은 리소스를 찾을 수 없습니다. 브라우저에서는 알려지지 않은 URL을 의미합니다. 이것은 API에서 종점은 적절하지만 리소스 자체는 존재하지 않음을 의미할 수도 있습니다. 서버들은 인증받지 않은 클라이언트로부터 리소스를 숨기기 위하여 이 응답을 403 대신에 전송할 수도 있습니다. 이 응답 코드는 웹에서 반복적으로 발생하기 때문에 가장 유명할지도 모릅니다.

`405 Method Not Allowed`

요청한 메소드는 서버에서 알고 있지만, 제거되었고 사용할 수 없습니다. 예를 들어, 어떤 API에서 리소스를 삭제하는 것을 금지할 수 있습니다. 필수적인 메소드인 `GET`과 `HEAD`는 제거될 수 없으며 이 에러 코드를 리턴할 수 없습니다.

`406 Not Acceptable`

이 응답은 서버가 서버 주도 콘텐츠 협상 을 수행한 이후, 사용자 에이전트에서 정해준 규격에 따른 어떠한 콘텐츠도 찾지 않았을 때, 웹서버가 보냅니다.

`407 Proxy Authentication Required` (en-US)

이것은 401과 비슷하지만 프록시에 의해 완료된 인증이 필요합니다.

`408 Request Timeout`

이 응답은 요청을 한지 시간이 오래된 연결에 일부 서버가 전송하며, 어떨 때에는 이전에 클라이언트로부터 어떠한 요청이 없었다고 하더라도 보내지기도 합니다. 이것은 서버가 사용되지 않는 연결을 끊고 싶어한다는 것을 의미합니다. 이 응답은 특정 몇몇 브라우저에서 빈번하게 보이는데, Chrome, Firefox 27+, 또는 IE9와 같은 웹서핑 속도를 올리기 위해 HTTP 사전 연결 메카니즘을 사용하는 브라우저들이 해당됩니다. 또한 일부 서버는 이 메시지를 보내지 않고 연결을 끊어버리기도 합니다.

`409 Conflict`

이 응답은 요청이 현재 서버의 상태와 충돌될 때 보냅니다.

`410 Gone`

이 응답은 요청한 콘텐츠가 서버에서 영구적으로 삭제되었으며, 전달해 줄 수 있는 주소 역시 존재하지 않을 때 보냅니다. 클라이언트가 그들의 캐쉬와 리소스에 대한 링크를 지우기를 기대합니다. HTTP 기술 사양은 이 상태 코드가 "일시적인, 홍보용 서비스"에 사용되기를 기대합니다. API는 알려진 리소스가 이 상태 코드와 함께 삭제되었다고 강요해서는 안된다.

`411 Length Required`

서버에서 필요로 하는 `Content-Length` 헤더 필드가 정의되지 않은 요청이 들어왔기 때문에 서버가 요청을 거절합니다.

`412 Precondition Failed` (en-US)

클라이언트의 헤더에 있는 전제조건은 서버의 전제조건에 적절하지 않습니다.

`413 Payload Too Large`

요청 엔티티는 서버에서 정의한 한계보다 큽니다; 서버는 연결을 끊거나 혹은 `Retry-After` 헤더 필드로 돌려보낼 것이다.

`414 URI Too Long`

클라이언트가 요청한 URI는 서버에서 처리하지 않기로 한 길이보다 깁니다.

`415 Unsupported Media Type`

요청한 미디어 포맷은 서버에서 지원하지 않습니다, 서버는 해당 요청을 거절할 것입니다.

`416 Requested Range Not Satisfiable`

`Range` 헤더 필드에 요청한 지정 범위를 만족시킬 수 없습니다; 범위가 타겟 URI 데이터의 크기를 벗어났을 가능성이 있습니다.

`417 Expectation Failed` (en-US)

이 응답 코드는 `Expect` 요청 헤더 필드로 요청한 예상이 서버에서는 적당하지 않음을 알려줍니다.

`418 I'm a teapot`

서버는 커피를 찻 주전자에 끓이는 것을 거절합니다.

`421 Misdirected Request` (en-US)

서버로 유도된 요청은 응답을 생성할 수 없습니다. 이것은 서버에서 요청 URI와 연결된 스킴과 권한을 구성하여 응답을 생성할 수 없을 때 보내집니다.

`422 Unprocessable Entity` (WebDAV)

요청은 잘 만들어졌지만, 문법 오류로 인하여 따를 수 없습니다.

`423 Locked` (en-US) (WebDAV)

리소스는 접근하는 것이 잠겨있습니다.

`424 Failed Dependency` (WebDAV)

이전 요청이 실패하였기 때문에 지금의 요청도 실패하였습니다.

`426 Upgrade Required`

서버는 지금의 프로토콜을 사용하여 요청을 처리하는 것을 거절하였지만, 클라이언트가 다른 프로토콜로 업그레이드를 하면 처리를 할지도 모릅니다. 서버는 `Upgrade` (en-US) 헤더와 필요로 하는 프로토콜을 알려주기 위해 426 응답에 보냅니다.

`428 Precondition Required` (en-US)

오리진 서버는 요청이 조건적이어야 합니다. 클라이언트가 리소스를 GET해서, 수정하고, 그리고 PUT으로 서버에 돌려놓는 동안 서드파티가 서버의 상태를 수정하여 발생하는 충돌인 '업데이트 상실'을 예방하기 위한 목적입니다.

`429 Too Many Requests`

사용자가 지정된 시간에 너무 많은 요청을 보냈습니다("rate limiting").

`431 Request Header Fields Too Large`

요청한 헤더 필드가 너무 크기 때문에 서버는 요청을 처리하지 않을 것입니다. 요청은 크기를 줄인 다음에 다시 전송해야 합니다.

`451 Unavailable For Legal Reasons` (en-US)

사용자가 요청한 것은 정부에 의해 검열된 웹 페이지와 같은 불법적인 리소스입니다.

서버 에러 응답
--------

`500 Internal Server Error`

서버가 처리 방법을 모르는 상황이 발생했습니다. 서버는 아직 처리 방법을 알 수 없습니다.

`501 Not Implemented`

요청 방법은 서버에서 지원되지 않으므로 처리할 수 없습니다. 서버가 지원해야 하는 유일한 방법은 `GET`와 `HEAD`이다. 이 코드는 반환하면 안됩니다.

`502 Bad Gateway`

이 오류 응답은 서버가 요청을 처리하는 데 필요한 응답을 얻기 위해 게이트웨이로 작업하는 동안 잘못된 응답을 수신했음을 의미합니다.

`503 Service Unavailable`

서버가 요청을 처리할 준비가 되지 않았습니다. 일반적인 원인은 유지보수를 위해 작동이 중단되거나 과부하가 걸렸을 때 입니다. 이 응답과 함께 문제를 설명하는 사용자 친화적인 페이지가 전송되어야 한다는 점에 유의하십시오. 이 응답은 임시 조건에 사용되어야 하며, `Retry-After:` HTTP 헤더는 가능하면 서비스를 복구하기 전 예상 시간을 포함해야 합니다. 웹마스터는 또한 이러한 일시적인 조건 응답을 캐시하지 않아야 하므로 이 응답과 함께 전송되는 캐싱 관련 헤더에 대해서도 주의해야 합니다.

`504 Gateway Timeout`

이 오류 응답은 서버가 게이트웨이 역할을 하고 있으며 적시에 응답을 받을 수 없을 때 주어집니다.

`505 HTTP Version Not Supported`

요청에 사용된 HTTP 버전은 서버에서 지원되지 않습니다.

`506 Variant Also Negotiates` (en-US)

서버에 내부 구성 오류가 있다. 즉, 요청을 위한 투명한 컨텐츠 협상이 순환 참조로 이어진다.

`507 Insufficient Storage` (en-US)

서버에 내부 구성 오류가 있다. 즉, 선택한 가변 리소스는 투명한 콘텐츠 협상에 참여하도록 구성되므로 협상 프로세스의 적절한 종료 지점이 아닙니다.

`508 Loop Detected` (en-US) (WebDAV)

서버가 요청을 처리하는 동안 무한 루프를 감지했습니다.

`510 Not Extended` (en-US)

서버가 요청을 이행하려면 요청에 대한 추가 확장이 필요합니다.

`511 Network Authentication Required` (en-US)

511 상태 코드는 클라이언트가 네트워크 액세스를 얻기 위해 인증을 받아야 할 필요가 있음을 나타냅니다.

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

더 보기
----

* 위키백과에서 상태코드 목록
* 상태코드의 최상위 도메인 등록 단체 공식 등록


HTTP/1.x의 커넥션 관리 - HTTP

HTTP/1.x의 커넥션 관리
================

커넥션 관리는 HTTP의 주요 주제입니다: 대규모로 커넥션을 열고 유지하는 것은 웹 사이트 혹은 웹 애플리케이션의 성능에 많은 영향을 줍니다. HTTP/1.x에는 몇 가지 모델이 존재합니다: 단기 커넥션, 영속적인 커넥션, 그리고 *HTTP 파이프라이닝.*

HTTP는 클라이언트와 서버 사이의 커넥션을 제공하는 TCP를 전송프로토콜로 주로 이용합니다. 초기에는, HTTP는 이런 커넥션들을 다루기 위해 단일 모델을 제공했습니다. 요청이 보내져야 할 때마다 커넥션들은 매번 새롭게 생성되었고 응답이 도착한 이후에 연결을 닫는 형태로 단기로만 유지되었습니다.

각각의 TCP 연결을 여는 것은 자원을 소비하기 때문에 이러한 단순한 모델은 선천적으로 성능상의 제약을 발생시킵니다. 몇몇 메시지들은 클라이언트와 서버 사이에서 교환되어야만 하며, 네트워크의 지연과 대역폭은 요청이 전송되어야 할 때마다 성능에 영향을 줍니다. 현대의 웹 페이지들은 필요로 하는 정보를 제공하기 위해 많은 요청(12개 혹은 그 이상)을 필요로 하므로, 이런 초창기 모델이 비효율적인 것은 자명합니다.

HTTP/1.1에서 두 가지 모델이 추가되었습니다. 영속적인 커넥션 모델은 연속적인 요청 사이에 커넥션을 유지하여 새 커넥션을 여는데 필요한 시간을 줄입니다. HTTP 파이프라이닝은 한 단계 더 나아가, 응답조차도 기다리지 않고 연속적인 요청을 보내서 네트워크 지연을 더욱 줄입니다.

![단시간 연결, 영구 연결 및 HTTP 파이프라인의 세 가지 HTTP/1.x 연결 모델의 성능의 비교](/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x/http1_x_connections.png)

**참고:** HTTP/2는 커넥션 관리의 몇가지 모델을 더 추가합니다.

명심해야 할 중요한 점은 HTTP 내 커넥션 관리가 end-to-end가 아닌 hop-by-hop인 두 개의 연속된 노드 사이의 커넥션에 적용된다는 것입니다. 클라이언트와 첫 번째 프록시 사이의 커넥션 모델은 프록시와 최종 목적 서버(혹은 중간 프록시들) 간의 것과는 다를 수도 있습니다. `Connection`와 `Keep-Alive`와 같이 커넥션 모델을 정의하는 데 관여하는 HTTP 헤더들은 hop-by-hop 헤더이며, 중간 노드에 의해 그 값들이 변경될 수 있습니다.

HTTP/1.1 커넥션이 TLS/1.0이나 WebSocket, 혹은 평문 HTTP/2와 같은 다른 프로토콜로 업그레이드 되었다는 점에서 관련된 주제는 HTTP 커넥션 업그레이드의 개념입니다. 이 프로토콜 업그레이드 메커니즘은 다른 곳에서 더 자세히 설명되어 있습니다.

단기 커넥션
------

HTTP 본래의 모델이자 HTTP/1.0의 기본 커넥션은 *단기 커넥션*입니다. 각각의 HTTP 요청은 각각의 커넥션 상에서 실행됩니다. 이는 TCP 핸드 셰이크는 각 HTTP 요청 전에 발생하고, 이들이 직렬화됨을 의미합니다.

TCP 핸드셰이크는 그 자체로 시간을 소모하기는 하지만 TCP 커넥션은 지속적으로 연결되었을 때 부하에 맞춰 더욱 예열되어 더욱 효율적으로 작동합니다. 단기 커넥션들은 TCP의 이러한 효율적인 특성을 사용하지 않게 하며 예열되지 않은 새로운 연결을 통해 지속적으로 전송함으로써 성능이 최적 상태보다 저하됩니다.

이 모델은 HTTP/1.0에서 사용된 기본 모델입니다(`Connection` 헤더가 존재하지 않거나, 그것의 값이 `close`로 설정된 경우). HTTP/1.1에서는, 이 모델은 `Connection` 헤더가 `close` 값으로 설정되어 전송된 경우에만 사용됩니다.

**참고:** 영속적인 커넥션을 지원하지 않는 매우 낡은 시스템을 다루는 것이 아니라면, 이 모델을 사용하려고 애쓸 필요가 없습니다.

영속적인 커넥션
--------

단기 커넥션은 두 가지 결점을 지니고 있습니다: 새로운 연결을 맺는데 드는 시간이 상당하다는 것과, TCP기반 커넥션의 성능은 오직 커넥션이 예열된 상태일 때만 나아진다는 것입니다. 이런 문제를 완화시키기 위해, HTTP/1.1보다도 앞서 영*속적인 커넥션*의 컨셉이 만들어졌습니다. 이는 *keep-alive 커넥션*이라고 불리기도 합니다.

영속적인 커넥션은 얼마간 연결을 열어놓고 여러 요청에 재사용함으로써, 새로운 TCP 핸드셰이크를 하는 비용을 아끼고, TCP의 성능 향상 기능을 활용할 수 있습니다. 커넥션은 영원히 열려있는지 않으며, 유휴 커넥션들은 얼마 후에 닫힙니다(서버는 `Keep-Alive` 헤더를 사용해서 연결이 최소한 얼마나 열려있어야 할지를 설정할 수 있습니다).

물론 영속적인 커넥션도 단점을 가지고 있습니다. 유휴 상태일때에도 서버 리소스를 소비하며, 과부하 상태에서는 DoS attacks을 당할 수 있습니다. 이런 경우에는 커넥션이 유휴 상태가 되자마자 닫히는 비영속적 커넥션(non-persistent connections)을 사용하는 것이 더 나은 성능을 보일 수 있습니다.

HTTP/1.0 커넥션은 기본적으로 영속적이지 않습니다. `Connection`를 `close`가 아닌 다른 것으로, 일반적으로 `retry-after`로 설정하면 영속적으로 동작하게 될 겁니다.

반면, HTTP/1.1에서는 기본적으로 영속적이며 헤더도 필요하지 않습니다(그러나 HTTP/1.0으로 동작하는 경우(fallback)에 대비해서 종종 추가하기도 합니다.).

HTTP 파이프라이닝
-----------

**참고:** HTTP 파이프라이닝은 모던 브라우저에서 기본적으로 활성화되어있지 않습니다:

* 버그가 있는 프록시들이 여전히 많은데, 이들은 웹 개발자들이 쉽게 예상하거나 분석하기 힘든 이상하고 오류가 있는 동작을 야기합니다.
* 파이프라이닝은 정확히 구현해내기 복잡합니다: 전송 중인 리소스의 크기, 사용될 효과적인 RTT, 그리고 효과적인 대역폭은 파이프라인이 제공하는 성능 향상에 직접적으로 영향을 미칩니다. 이런 내용을 모른다면, 중요한 메시지가 덜 중요한 메시지에 밀려 지연될 수 있습니다. 중요성에 대한 생각은 페이지 레이아웃 중에도 진전됩니다. 그러므로 파이프라이닝은 대부분의 경우 미미한 수준의 향상만을 가져다 줍니다.
* 파이프라이닝은 HOL 문제에 영향을 받습니다.

이런 이유들로, 파이프라이닝은 더 나은 알고리즘인 멀티플렉싱으로 대체되었는데, 이는 HTTP/2에서 사용됩니다.

기본적으로, HTTP 요청은 순차적입니다. 현재의 요청에 대한 응답을 받고 나서야 다음 요청을 실시합니다. 네트워크 지연과 대역폭 제한에 걸려 다음 요청을 보내는 데까지 상당한 딜레이가 발생할 수 있습니다.

파이프라이닝이란 같은 영속적인 커넥션을 통해서, 응답을 기다리지 않고 요청을 연속적으로 보내는 기능입니다. 이것은 커넥션의 지연를 회피하고자 하는 방법입니다. 이론적으로는, 두 개의 HTTP 요청을 하나의 TCP 메시지 안에 채워서(be packed) 성능을 더 향상시킬 수 있습니다. HTTP 요청의 사이즈는 지속적으로 커져왔지만, 일반적인 MSS(최대 세그먼트 크기)는 몇 개의 간단한 요청을 포함하기에는 충분히 여유있습니다.

모든 종류의 HTTP 요청이 파이프라인으로 처리될 수 있는 것은 아닙니다: `GET`, `HEAD`, `PUT` 그리고 `DELETE` 메서드같은 idempotent 메서드만 가능합니다. 실패가 발생한 경우에는 단순히 파이프라인 컨텐츠를 다시 반복하면 됩니다.

오늘날, 모든 HTTP/1.1 호환 프록시와 서버들은 파이프라이닝을 지원해야 하지만, 실제로는 많은 프록시와 서버들은 제한을 가지고 있습니다. 모던 브라우저가 이 기능을 기본적으로 활성화하지 않는 이유입니다.

도메인 샤딩
------

**참고:** 매우 명확하고 당면해있는 요구사항이 아니라면, 이 제외된(deprecated) 기술을 사용하지 마십시오. 대신 HTTP/2로 전환하시기 바랍니다. HTTP/2에서 도메인 샤딩은 더 이상 유용하지 않습니다. HTTP/2 커넥션은 우선 순위가 없는 병렬 요청들을 매우 잘 다룹니다. 도메인 샤딩은 성능 측면에서도 좋지 못합니다. 대부분의 HTTP/2 구현체는 우발적으로 일어나는 도메인 샤딩을 되돌리기 위해 커넥션 합치기(connection coalescing)라고 불리는 기술을 사용합니다.

요청 사이에 실제 정렬이 없음에도 HTTP/1.x 커넥션이 요청을 직렬화함으로써, 대역폭이 충분히 큰 경우가 아니고는 효율적이지 못합니다. 이런 단점을 피하기 위해, 브라우저들은 각 도메인에 대한 몇 개의 커넥션을 맺고 병렬로 요청을 보냅니다. 기본값은 한때 2개 혹은 3개였지만, 지금은 이것이 증가하여 일반적으로 병력 커넥션은 6개입니다. 만약 이것보다 많이 시도한다면 서버 측의 DoS 보호 동작을 야기할 위험이 있습니다.

서버가 더 빠른 웹 사이트나 애플리케이션 반응을 원한다면, 서버가 더 많은 커넥션을 열도록 강제할 수 있습니다. 예를 들어, `www.example.com` 라는 하나의 도메인에서 모든 리소스를 가져오는 대신, `www1.example.com`, `www2.example.com`, `www3.example.com`와 같이 몇 개의 도메인으로 분할할 수 있습니다. 이런 각각의 도메인들은 동일한 서버로 연결되고, 브라우저는 그런 각각의 도메인마다 6개의 커넥션을 맺을 것입니다(예제에서는 총 18개로 늘어납니다). 이러한 기법을 **도메인 샤딩**이라고 부릅니다.

![](/ko/docs/Web/HTTP/Connection_management_in_HTTP_1.x/httpsharding.png)

결론
--

개선된 커넥션 관리는 HTTP 성능을 상당한 수준만큼 향상시킬 수 있습니다. 영속적인 커넥션을 사용하는 HTTP/1.1 혹은 HTTP/1.0는 - 적어도 그 커넥션이 유휴 상태가 될 때까지 - 최상의 성능을 이끌어냅니다. 그러나, 파이프라이닝의 실패로 더 나은 커넥션 관리 모델이 고안되었고, 이는 HTTP/2에 포함되었습니다.


HTTP 범위 요청 - HTTP

HTTP 범위 요청
==========

HTTP 범위 요청은 HTTP의 일정 부분만 서버에서 클라이언트로 보내도록 허락하는 것입니다. 부분 요청은 예를들어 대형 미디어나 파일 다운로드 도중 일시정지와 다시 시작 기능에 유용합니다.

서버가 부분 요청을 지원하는지 확인
-------------------

서버가 범위 요청을 지원한다면, HTTP 응답에 `Accept-Ranges`이 존재(그리고 그 값이 "`none`"이 아님)할 것입니다. 이는 예를들면 `HEAD` 를 cURL에서 요청함으로 확인할 수 있습니다.
```

curl -I http://i.imgur.com/z4d4kWk.jpg

HTTP/1.1 200 OK
...
Accept-Ranges: bytes
Content-Length: 146515
```

이 응답에서, `Accept-Ranges: bytes`는 바이트가 범위 요청에서 최소단위로 사용될 수 있음을 알려줍니다. 여기에서 `Content-Length` 헤더 역시 이미지를 얻기 위한 최대 크기를 알 수 있어 유용합니다.

만약 사이트에서 `Accept-Ranges`헤더를 빠트린다면, 분할 요청을 지원하지 않는 것으로 생각됩니다. 일부 사이트는 명확하게 "`none`"을 값으로 보내 지원하지 않는 것을 알려줍니다. 일부 어플리케이션에서는 다운로드 매니저에서 일시정지 버튼을 없애버리는 경우가 있습니다.
```

curl -I https://www.youtube.com/watch?v=EwTZ2xpQwpA

HTTP/1.1 200 OK
...
Accept-Ranges: none
```

서버에 특정 범위를 요청
-------------

만약 서버가 범위 요청을 지원한다면, `Range` 헤더를 사용하여 요청할 수 있습니다. 이는 서버에서 문서의 일부분만 돌려주면 된다는 것을 알 수 있게 해줍니다.

### 단일 부분 범위

우리는 리소스의 단일 부분에 대해서만 요청할 수 있습니다. 역시 cURL을 사용하여 테스트 합니다. "`-H`"는 HTTP요청의 헤더에 추가된다는 옵션이며, 이 경우에는 `Range`헤더로 첫 1024 바이트를 요청합니다.
```

curl http://i.imgur.com/z4d4kWk.jpg -i -H "Range: bytes=0-1023"
```

요청은 다음처럼 보여집니다:
```

GET /z4d4kWk.jpg HTTP/1.1
Host: i.imgur.com
Range: bytes=0-1023
```

서버에서 `206` `Partial Content` 상태로 응답합니다:
```

HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/146515
Content-Length: 1024
...
(binary content)
```

`Content-Length` 헤더는 이제 요청한 범위의 크기(전체 이미지의 크기가 아님)를 알려줍니다. `Content-Range` 헤더는 리소스의 전체 크기와 메시지가 어느 부분에 속하는지 알려줍니다.

### 다중 부분 범위

`Range` 헤더는 문서의 여러 부분 역시 다중 범위 요청을 통해 한번에 가져올 수 있습니다. 범위는 콤마로 나누어집니다.
```

curl http://www.example.com -i -H "Range: bytes=0-50, 100-150"
```

서버는 `206` `Partial Content` 상태로 응답하며 `Content-Type``: multipart/byteranges; boundary=3d6b6a416f9b5` 는 다중 부분 바이트 범위를 알려줍니다. 각 부분은 고유의 `Content-Type`과 `Content-Range` 영역을 가지고 있으며, 경계를 나누는 문자열인 경계 파라미터를 필요로 합니다.
```

HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 282

--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 0-50/1270

<!doctype html>
<html>
<head>
    <title>Example Do
--3d6b6a416f9b5
Content-Type: text/html
Content-Range: bytes 100-150/1270

eta http-equiv="Content-type" content="text/html; c
--3d6b6a416f9b5--
```

### 조건 분할 요청

리소스에 대해 추가 요청을 재개하기에 앞서, 마지막에 분할된 데이터를 받은 이후 저장된 리소스가 수정되지는 않았는지 확인해야 합니다.

`If-Range` HTTP 요청 헤더는 범위 요청에 조건을 만듭니다: 만약 조건이 만족하면, 분할 요청은 서버에서 처리되어 `206` `Partial Content` 응답과 함께 적절한 바디와 돌아올겁니다. 만약 조건이 만족하지 못한다면, 전체 리소스가 `200` `OK` 상태로 보내집니다. 이 헤더는 `Last-Modified` 확인자나 `ETag`와 함께 사용될 수 있지만, 동시에는 안됩니다.
```

If-Range: Wed, 21 Oct 2015 07:28:00 GMT
```

분할 요청 응답
--------

범위 요청을 처리할 때, 다음의 3가지 상태가 있습니다:

* 성공적으로 보내질 경우에는, `206` `Partial Content` 상태가 서버에서 돌아옵니다.
* 범위를 벗어난 경우(범위 값이 리소스 크기를 벗어났을 때), 서버는 `416` `Requested Range Not Satisfiable` 상태로 답합니다.
* 범위 요청을 지원하지 않는 경우, 서버는 `200` `OK` 상태를 돌려보냅니다.
`Chunked Transfer-Encoding`과 비교
-------------------------------

`Transfer-Encoding` 헤더는 `chunked encoding` 또한 지원하며, 이는 대용량 데이터를 클라이언트에 보낼 때와 요청이 모두 처리되기 전까지 총 크기를 알 수 없을 때 유용합니다. 서버는 데이터를 클라이언트에 응답 버퍼링 없이 즉시 보내거나, 정확한 길이를 측정하여 지연 시간을 향상시킵니다. 범위 요청과 청크는 호환되어 함께 사용할 수도 있고, 따로 사용할 수 있습니다.

함께 참고할 내용
---------

* 연관된 상태 코드 `200`, `206`, `416`.
* 연관된 헤더: `Accept-Ranges`, `Range`, `Content-Range`, `If-Range`, `Transfer-Encoding`.
* Download resumption in Internet Explorer


전형적인 HTTP 세션 - HTTP

전형적인 HTTP 세션
============

HTTP와 같은 클라이언트-서버 프로토콜에서, 세션은 다음의 세 가지 과정으로 이루어집니다.

1. 클라이언트가 TCP 연결을 수립합니다(또는 전송 계층이 TCP가 아닌 다른 적당한 연결로).
2. 클라이언트는 요청을 전송한 뒤 응답을 기다립니다.
3. 서버는 요청에 대해 처리하고 그에 대한 응답을 상태 코드 그리고 요청에 부합하는 데이터와 함께 돌려보냅니다.

HTTP/1.1부터는 세번째 과정 이후 클라이언트가 해당 시점에 또 다른 요청을 보낼 수 있도록 연결을 더 이상 닫지 않습니다. 그러므로 두번째, 세번째 과정이 몇 번에 걸쳐 일어날 수 있습니다.

연결 수립
-----

클라이언트-서버 프로토콜에, 클라이언트는 연결을 수립합니다. HTTP에서 연결을 여는 것은 보통의 경우 TCP인 기본적인 전송 계층 내에서 연결을 수립하는 것을 뜻합니다.

TCP를 이용할 경우, 컴퓨터 상의 HTTP 서버를 위한 기본 포트는 80인데 8000 혹은 8080처럼 다른 포트들도 자주 사용되곤 합니다. 요청을 위한 페이지 URL은 도메인 이름과 포트 번호 둘 다 포함하지만 포트 번호가 80일 경우 생략 가능합니다. 좀 더 자세한 내용은 웹 리소스 식별을 참고하시기 바랍니다.

**참고:** **기억하세요** 클라이언트-서버 모델은 서버로 하여금 명시적인 요청없이 클라이언트로 데이터를 전송하는 것을 허용하지 않습니다. 이런 문제에 대한 해결책으로, 웹 개발자들은 몇 가지 기술을 사용합니다: `XMLHTTPRequest` 혹은 `Fetch` API를 통해 주기적으로 서버에 핑하기, HTML 웹소켓 API, 혹은 그와 유사한 프로토콜 사용

클라이언트 요청 전송
-----------

연결이 한번 수립되고 나면 사용자-에이전트는 요청을 보낼 수 있습니다(사용자-에이전트는 일반적으로 웹 브라우저를 말하지만, 예를 들자면 crawler와 같이 무엇이든 될 수 있습니다). 클라이언트 요청은 세 가지 블록으로 나누어진 CRLF(라인 피드를 따르는 캐리지 리턴)로 구분된 텍스트 지시자들로 이루어집니다.

1. 첫번째 줄은 파라메터가 따르는 요청 메서드를 포함합니다.
    * 문서의 경로, 즉 프로토콜과 도메인 이름을 제외한 절대 URL
    * 사용중인 HTTP 프로토콜 버전
2. 바로 다음 줄들은 각각 특정 헤더를 나타내는데 데이터의 종류가 적합한지(예를 들어, 언어는 무엇인지, MIME 타입은 무엇인지 등) 혹은 서버의 동작을 수정하는 몇 가지 데이터(예를 들어 이미 캐시되어 있는 경우 응답을 전송하지 않는다든지 하는) 등에 관한 몇 가지 정보를 서버에게 제공합니다. 이런 HTTP 헤더들은 빈 줄로 끝나는 블록을 형성합니다.
3. 마지막 블록은 부가적인 데이터 블록으로. 더 많은 데이터를 포함하며 주로 POST 메서드에 의해 사용됩니다.
### 요청 예제

develper.mozilla.org. http://developer.mozilla.org/의 최상위 페이지를 가져오도록 요청하고, 가능하다면 서버에게 사용자-에이전트가 해당 페이지에 대해 프랑스어로 된 페이지를 원한다고 알려줍니다.
```

GET / HTTP/1.1
Host: developer.mozilla.org
Accept-Language: fr
```

헤더 블록으로부터 데이터 블록을 구분짓는 첫번째 빈줄에 주목하세요. 헤더 중에 `Content-Length:` 헤더가 없으므로, 데이터 블록은 비어있고 서버는 헤더의 마지막을 나타내는 빈 줄을 받는 즉시 요청을 처리할 수 있습니다.

다음은 결과 전송 형식입니다.
```

POST /contact_form.php HTTP/1.1
Host: developer.mozilla.org
Content-Length: 64
Content-Type: application/x-www-form-urlencoded

name=Joe%20User&request=Send%20me%20one%20of%20your%20catalogue
```

### 요청 메서드

HTTP는 주어진 자원에 대해 실행되길 바라는 동작을 가리키는 요청 메서드 집합을 정의합니다. 그것들이 명사가 될 수 있으지라도, 이 요청 메서드들은 때때로 HTTP 동사로써 참조됩니다. 일반적으로 대부분의 요청은 `GET과` `POST입니다`.

* `GET` 메서드는 지정된 자원의 표시를 요청합니다. `GET`을 사용하는 요청은 데이터를 가져오는 것 외에는 할 수 없습니다.
* `POST` 메서드는 서버에 데이터를 전송하여 서버가 상태를 바꾸도록 만듭니다. 이것은 HTML Forms (en-US)에서 자주 사용되는 메서드입니다.
서버 응답의 구조
---------

연결된 에이전트가 자신의 요청을 전송하고 난 뒤에, 웹 서버가 그것을 처리하고 최종적으로 응답을 돌려보내게 됩니다. 클라이언트 요청과 유사하게 서버 응답은 세 개의 다른 블록으로 나누어진 CRLF로 구분된 텍스트 지시자들로 형성됩니다.

1. 상태 줄인 첫번째 줄은 상태 요청(그리고 인간이 읽을 수 있는 텍스트 내에서의 의미)이 따르도록 사용된 HTTP 버전의 acknowledgment로 구성됩니다.
2. 다음 줄들은 각각 특정 HTTP 헤더를 나타는데, 전송되는 데이터에 관한 정보(이를테면, 타입, 데이터 크기, 사용된 압축 알고리즘, 캐시에 대한 힌트 등)를 클라이언트에게 제공합니다. 클라이언트의 요청에 대한 HTTP 헤더 블록과 유사하게, 이 HTTP 헤더들은 빈 줄로 끝나는 블록을 형성합니다.
3. 마지막 블록은 데이터 블록으로 (존재한다면) 데이터를 포함합니다.
### 응답 예제

웹 페이지의 성공적인 수신
```

HTTP/1.1 200 OK
Date: Sat, 09 Oct 2010 14:28:02 GMT
Server: Apache
Last-Modified: Tue, 01 Dec 2009 20:18:22 GMT
ETag: "51142bc1-7449-479b075b2891b"
Accept-Ranges: bytes
Content-Length: 29769
Content-Type: text/html

<!DOCTYPE html... (here comes the 29769 bytes of the requested web page)
```

요청 자원이 영구적으로 옮겨졌다는 내용의 알림
```

HTTP/1.1 301 Moved Permanently
Server: Apache/2.2.3 (Red Hat)
Content-Type: text/html; charset=iso-8859-1
Date: Sat, 09 Oct 2010 14:30:24 GMT
Location: https://developer.mozilla.org/ (this is the new link to the resource; it is expected that the user-agent will fetch it)
Keep-Alive: timeout=15, max=98
Accept-Ranges: bytes
Via: Moz-Cache-zlb05
Connection: Keep-Alive
X-Cache-Info: caching
X-Cache-Info: caching
Content-Length: 325 (the content contains a default page to display if the user-agent is not able to follow the link)

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="https://developer.mozilla.org/">here</a>.</p>
<hr>
<address>Apache/2.2.3 (Red Hat) Server at developer.mozilla.org Port 80</address>
</body></html>
```

요청된 자원이 존재하지 않는다는 내용의 알림
```

HTTP/1.1 404 Not Found
Date: Sat, 09 Oct 2010 14:33:02 GMT
Server: Apache
Last-Modified: Tue, 01 May 2007 14:24:39 GMT
ETag: "499fd34e-29ec-42f695ca96761;48fe7523cfcc1"
Accept-Ranges: bytes
Content-Length: 10732
Content-Type: text/html

<!DOCTYPE html... (contains a site-customized page helping the user to find the missing resource)
```

### 응답 상태 코드

HTTP 응답 상태 코드는 특정 HTTP 요청이 성공적으로 끝났는지 아닌지를 가르킵니다. 응답은 다섯가지 계층 내로 그룹화됩니다: 정보를 제공하는 응답, 성공적인 응답, 리다이렉트, 클라이언트 오류, 그리고 서버 오류.

* `200`: 성공. 요청이 성공했다는 것을 의미합니다.
* `301`: 영구적으로 옮겨짐. 이 응답 코드는 요청된 자원의 URI가 변경되었다는 것을 의미합니다.
* `404`: 찾을 수 없음. 서버가 요청된 자원을 찾을 수 없음을 의미합니다.
함께 참고할 내용
---------

* 웹 리소스 식별
* HTTP 헤더
* HTTP 요청 메서드
* HTTP 응답 상태 코드


CONNECT - HTTP

CONNECT
=======

**HTTP `CONNECT`** 메소드는 요청한 리소스에 대해 양방향 연결을 시작하는 메소드입니다. 이는 터널을 열기 위해서 사용될 수 있습니다.

예를 들어, `CONNECT` 메소드는 SSL (HTTPS)를 사용하는 웹사이트에 접속하는데 사용될 수 있습니다. 클라이언트는 원하는 목적지와의 TCP 연결을 HTTP 프록시 서버에 요청합니다. 그러면 서버는 클라이언트를 대신하여 연결의 생성을 진행합니다. 한번 서버에 의해 연결이 수립되면, 프록시 서버는 클라이언트에 오고가는 TCP 스트림을 계속해서 프록시합니다.

`CONNECT`는 홉바이홉 메소드입니다.

|  |  |
| --- | --- |
| Request has body | No |
| Successful response has body | Yes |
| Safe | No |
| Idempotent | No |
| Cacheable | No |
| Allowed in HTML forms (en-US) | No |

문법
--
```

CONNECT www.example.com:443 HTTP/1.1
```

예제
--

일부 프록시 서버는 터널을 생성하기 위해 인증을 요구할 수 있습니다. `Proxy-Authorization` (en-US) 헤더를 참고하세요.

```http
CONNECT server.example.com:80 HTTP/1.1
Host: server.example.com:80
Proxy-Authorization: basic aGVsbG86d29ybGQ=
```

기술 사양
-----

| Specification | Title |
| --- | --- |
| RFC 7231, 섹션 4.3.6: CONNECT | Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 참고할 내용
---------

* Proxy server
* `Proxy-Authorization` (en-US)


HEAD - HTTP

HEAD
====

**HTTP `HEAD` 메서드**는 특정 리소스를 `GET` 메서드로 요청했을 때 돌아올 헤더를 요청합니다.

`HEAD` 메서드에 대한 응답은 본문을 가져선 안되며, 본문이 존재하더라도 무시해야 합니다. 그러나, `Content-Length`처럼 본문 콘텐츠를 설명하는 개체 헤더는 포함할 수 있습니다. 이 때, 개체 헤더는 비어있어야 하는 `HEAD`의 본문과는 관련이 없고, 대신 `GET` 메서드로 동일한 리소스를 요청했을 때의 본문을 설명합니다.

`HEAD` 요청의 응답이 캐시했던 이전 `GET` 메서드의 응답을 유효하지 않다고 표시할 경우, 새로운 `GET` 요청을 생성하지 않더라도 캐시를 무효화합니다.

|  |  |
| --- | --- |
| 요청에 본문 존재 | 아니오 |
| 성공 응답에 본문 존재 | 아니오 |
| 안전함 | 예 |
| 멱등성 | 예 |
| 캐시 가능 | 예 |
| HTML 양식에서 사용 가능 | 아니오 |

구문
--
```

HEAD /index.html
```

명세
--

| Specification |
| --- |
| HTTP Semantics # HEAD |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `GET`


POST - HTTP

POST
====

**HTTP `POST` 메서드**는 서버로 데이터를 전송합니다. 요청 본문의 유형은 `Content-Type` 헤더로 나타냅니다.

`PUT`과 `POST`의 차이는 멱등성으로, `PUT`은 멱등성을 가집니다. `PUT`은 한 번을 보내도, 여러 번을 연속으로 보내도 같은 효과를 보입니다. 즉, 부수 효과(side effect)가 없습니다.

`POST` 요청은 보통 HTML 양식을 통해 서버에 전송하며, 서버에 변경사항을 만듭니다. 이 경우의 콘텐츠 유형(`Content-Type`)은 *`<form>` 요소의 `enctype` 특성이나 `<input>` (en-US), `<button>`* 요소의 *`formenctype` (en-US) 특성 안에 적당한 문자열을 넣어 결정합니다.*

* `application/x-www-form-urlencoded`: &으로 분리되고, "=" 기호로 값과 키를 연결하는 key-value tuple로 인코딩되는 값입니다. 영어 알파벳이 아닌 문자들은 percent encoded 으로 인코딩됩니다. 따라서, 이 content type은 바이너리 데이터에 사용하기에는 적절치 않습니다. (바이너리 데이터에는 use `multipart/form-data` 를 사용해 주세요.)\_
* *`multipart/form-data`*
* *`text/plain`*

`POST` 요청을 HTML 양식 외의 다른 방법(`XMLHttpRequest` 등)으로 전송할 땐 요청의 본문이 어떤 형태도 취할 수 있습니다. HTTP 1.1 규격에 정의된 바와 같이, `POST`는 다음의 기능을 포함하는 균일한 메서드를 허용하도록 설계되었습니다.

* 기존 리소스에 주석달기
* 게시판, 뉴스 그룹, 메일링 리스트나 이와 유사한 시스템에 글 올리기
* 회원가입 모달로 새로운 사용자 추가하기
* 양식 전송 결과 등 데이터 블록을 데이터 처리 프로세스에 보내기
* 이어붙이기 연산을 통한 데이터베이스 확장

|  |  |
| --- | --- |
| 요청에 본문 존재 | 예 |
| 성공 응답에 본문 존재 | 예 |
| 안전함 | 아니오 |
| 멱등성 | 아니오 |
| 캐시 가능 | 신선도 정보 포함 시 |
| HTML 양식에서 사용 가능 | 예 |

구문
--
```

POST /index.html
```

예제
--

다음은 `application/x-www-form-urlencoded` 콘텐츠 유형을 사용하는 간단한 형태의 양식 제출 예시입니다.

```http
POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

say=Hi&to=Mom
```

`multipart/form-data` 콘텐츠 유형을 사용하는 예시입니다.

```http
POST /test.html HTTP/1.1
Host: example.org
Content-Type: multipart/form-data;boundary="boundary"

--boundary
Content-Disposition: form-data; name="field1"

value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"

value2
--boundary--
```

명세
--

| Specification |
| --- |
| HTTP Semantics # POST |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Content-Type`
* `Content-Disposition`
* `GET`


PUT - HTTP

PUT
===

**HTTP `PUT` 메서드**는 요청 페이로드를 사용해 새로운 리소스를 생성하거나, 대상 리소스를 나타내는 데이터를 대체합니다.

`PUT`과 `POST`의 차이는 멱등성으로, `PUT`은 멱등성을 가집니다. `PUT`은 한 번을 보내도, 여러 번을 연속으로 보내도 같은 효과를 보입니다. 즉, 부수 효과가 없습니다.

|  |  |
| --- | --- |
| 요청에 본문 존재 | 예 |
| 성공 응답에 본문 존재 | 아니오 |
| 안전함 | 아니오 |
| 멱등성 | 예 |
| 캐시 가능 | 아니오 |
| HTML 양식에서 사용 가능 | 아니오 |

구문
--
```

PUT /new.html HTTP/1.1
```

예제
--

### 요청
```

PUT /new.html HTTP/1.1
Host: example.com
Content-type: text/html
Content-length: 16

<p>New File</p>
```

### 응답

대상 리소스를 나타내는 데이터가 없고, PUT 요청이 성공적으로 하나를 새로 생성한 경우, 출처 서버는 반드시 사용자 에이전트에게 `201` (`Created`) 응답을 보내 해당 사항을 알려줘야 합니다.
```

HTTP/1.1 201 Created
Content-Location: /new.html
```

대상 리소스를 나타내는 데이터가 있고, 이를 요청에 포함된 자료에 준하여 성공적으로 수정했다면, 출처 서버는 반드시 `200` (`OK`) 또는 `204` (`No Content`) 응답을 보내 성공을 알려줘야 합니다.
```

HTTP/1.1 204 No Content
Content-Location: /existing.html
```

명세
--

| Specification |
| --- |
| HTTP Semantics # PUT |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `201`
* `204`


OPTIONS - HTTP

OPTIONS
=======

**HTTP `OPTIONS` 메서드**는 주어진 URL 또는 서버에 대해 허용된 통신 옵션을 요청합니다. 클라이언트는 이 방법으로 URL을 지정하거나 별표(`*`)를 지정하여 전체 서버를 참조할 수 있습니다.

|  |  |
| --- | --- |
| 요청에 본문이 있음 | 아니요 |
| 성공적인 응답에 본문이 있음 | 예 |
| 안전함 | 예 |
| 멱등성 | 예 |
| 캐시 가능 | 아니요 |
| HTML 폼에서 허용됨 | 아니요 |

구문
--

```http
OPTIONS /index.html HTTP/1.1
OPTIONS * HTTP/1.1
```

예제
--

### 허용된 요청 매서드 식별하기

서버가 지원하는 요청 방법을 찾으려면 아래와 같이 `curl` 명령어을 사용하여 `OPTIONS` 요청을 보내볼 수 있습니다.

```bash
curl -X OPTIONS https://example.org -i
```

그럼 응답은 허용된 메서드를 가지고 있는 `Allow` 헤더가 있습니다.

```http
HTTP/1.1 200 No Content
Allow: OPTIONS, GET, HEAD, POST
Cache-Control: max-age=604800
Date: Thu, 13 Oct 2016 11:45:00 GMT
Server: EOS (lax004/2813)
```

### CORS 사전 요청

CORS에서 사전 요청은 `OPTIONS` 메서드를 통해 전송되므로 요청을 보낼 수 있는 경우라면 서버가 응답할 수 있습니다. 이번 예제에서는 다음 매개변수에 대한 권한을 요청합니다.

* 사전 요청에서 전송되는 `Access-Control-Request-Method` 헤더는 서버에 실제 요청이 전송될 때 `POST` 메서드가 있음을 알려줍니다.
* `Access-Control-Request-Headers` 헤더는 서버에 실제 요청이 전송될 때 `X-PINGOTHER`와 `Content-Type` 헤더가 있음을 알려줍니다.

```http
OPTIONS /resources/post-here/ HTTP/1.1
Host: bar.example
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,\*/\*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
```

이제 서버는 아래와 같은 상황에서 요청을 수락할 때 응답할 수 있습니다. 이 예제에세 서버의 응답은 다음과 같습니다.

`Access-Control-Allow-Origin`

`https://foo.example` 출처는 다음을 통해 `bar.example/resources/post-here/` URL을 요청할 수 있습니다.

`Access-Control-Allow-Methods`

`POST`, `GET` 그리고 `OPTIONS`는 이 URL에 허용되는 메서드입니다. (이 헤더는 `Allow` 헤더와 유사하지만 CORS에만 사용됩니다.)

`Access-Control-Allow-Headers`

`X-PINGOTHER` 및 `Content-Type`은 URL에 대해 허용되는 요청 헤더입니다.

`Access-Control-Max-Age`

위 권한은 86,400초(1일) 동안 캐시될 수 있습니다.

```http
HTTP/1.1 200 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
```

상태 코드
-----

`200` OK와 `204` No Content 모두 허용되는 상태 코드이지만 일부 브라우저는 `204 No Content`가 실제 리소스에 적용된다고 잘못 판단하여 리소스를 가져오기 위한 다음 요청을 보내지 않습니다.

명세서
---

| Specification |
| --- |
| HTTP Semantics # OPTIONS |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Allow` 헤더
* CORS


PATCH - HTTP

PATCH
=====

**HTTP PATCH** 메소드는 리소스의 부분적인 수정을 할 때에 사용됩니다.

HTTP `PUT` 메소드는 문서 전체의 완전한 교체만을 허용합니다. 반면 `PATCH` 메소드는 `PUT` 메소드와 달리 멱등성을 가지지 않는데, 이는 동일한 patch 요청이 다른 결과를 야기할 수도 있음을 뜻합니다. 하지만 PATCH를 PUT과 같은 방식으로 사용함으로써 멱등성을 가지게 할 수도 있습니다.

`PATCH` (혹은 `PUT`)는 다른 리소스에게 부수효과(side-effects)를 일으킬 가능성이 있습니다.

서버가 `PATCH`를 지원하는지 알 수 있게끔 하기 위해, 서버는 `Allow` 리스트 혹은 `Access-Control-Allow-Methods` (for CORS) 응답 헤더를 통해 이를 명시할 수 있습니다.

PATCH가 허용되는지 확인할 수 있는 또 다른 (암묵적인)지표로 `Accept-Patch`의 존재 유무를 들 수 있는데, 이를 통해 patch 문서 양식이 서버에 받아 들여졌음을 알 수 있습니다.

|  |  |
| --- | --- |
| Request has body | Yes |
| Successful response has body | Yes |
| Safe | No |
| Idempotent | No |
| Cacheable | No |
| Allowed in HTML forms (en-US) | No |

Syntax
------
```

PATCH /file.txt HTTP/1.1
```

Example
-------

### Request

```http
PATCH /file.txt HTTP/1.1
Host: www.example.com
Content-Type: application/example
If-Match: "e0023aa4e"
Content-Length: 100

[description of changes]
```

### Response

성공적인 응답은 2xx 상태 코드를 통해서 확인할 수 있습니다.

아래의 예시에서는 `204` 응답이 사용되었는데, 이는 응답이 유의미한 body를 전달하고 있지 않기 때문입니다. {HTTPStatus("200")}} 응답에서는 body에 유의미한 데이터가 포함되어 있음을 유추할 수 있습니다.
```

HTTP/1.1 204 No Content
Content-Location: /file.txt
ETag: "e0023aa4f"
```
명세서
---

| Specification |
| --- |
| RFC 5789  |

See also
--------

* `204`
* `Allow`, `Access-Control-Allow-Methods`
* `Accept-Patch` – specifies the patch document formats accepted by the server.


GET - HTTP

GET
===

**HTTP `GET` 메서드**는 특정한 리소스를 가져오도록 요청합니다. `GET` 요청은 데이터를 가져올 때만 사용해야 합니다.

**참고:** > `GET` 요청에 본문이나 페이로드가 담겨있으면 명세에는 금지되어있지 않지만, 의미가 정의되지 않아 기존에 존재하는 구현체에게 요청을 거부당할수 있습니다. 이러한 이유로 `GET` 요청에는 본문이나 페이로드를 담지 않는 것이 바람직합니다.

|  |  |
| --- | --- |
| 요청에 본문 존재 | 아니오 |
| 성공 응답에 본문 존재 | 예 |
| 안전함 | 예 |
| 멱등성 | 예 |
| 캐시 가능 | 예 |
| HTML 양식에서 사용 가능 | 예 |

구문
--
```

GET /index.html
```

명세
--

| Specification |
| --- |
| HTTP Semantics # GET |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* HTTP 헤더
* `Range`
* `POST`


DELETE - HTTP

DELETE
======

**HTTP `DELETE` 메서드**는 지정한 리소스를 삭제합니다.

|  |  |
| --- | --- |
| 요청에 본문 존재 | May |
| 성공 응답에 본문 존재 | May |
| 안전함 | No |
| 멱등성 | Yes |
| 캐시 가능 | No |
| HTML 양식에서 사용 가능 | No |

구문
--
```

DELETE /file.html HTTP/1.1
```

예제
--

### 요청
```

DELETE /file.html HTTP/1.1
```

### 응답

`DELETE` 메서드를 성공적으로 적용한 후에 사용할 수 있는 응답 상태 코드는 다음과 같이 몇 가지가 있습니다.

* 아마도 명령을 성공적으로 수행할 것 같으나 아직은 실행하지 않은 경우 `202` (`Accepted`) 상태 코드.
* 명령을 수행했고 더 이상 제공할 정보가 없는 경우 `204` (`No Content`) 상태 코드.
* 명령을 수행했고 응답 메시지가 이후의 상태를 설명하는 경우 `200` (`OK`) 상태 코드.
```

HTTP/1.1 200 OK
Date: Wed, 21 Oct 2015 07:28:00 GMT

<html>
  <body>
    <h1>File deleted.</h1>
  </body>
</html>
```

명세
--

| Specification |
| --- |
| HTTP Semantics # DELETE |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* HTTP 상태: `200`, `202`, `204`


Accept-Patch - HTTP

Accept-Patch
============

**`Accept-Patch`** 응답 HTTP 헤더는 서버가 PATCH 요청에서 어떤 미디어 유형을 이해할 수 있는지를 알려줍니다.

메서드에 대한 응답으로 **`Accept-Patch`** 를 반환하면 Request-URI로 식별된 리소스에서 PATCH가 허용됨을 의미합니다. 두 가지 일반적인 경우가 이에 해당합니다.

지원되지 않는 미디어 유형이 포함된 패치 요청을 수신하는 서버는 `415` `Unsupported Media Type`과 하나 이상의 지원되는 미디어 유형을 참조하는 Accept-Patch 헤더로 응답할 수 있습니다.

**참고:**

* IANA 레지스트리는 공식 콘텐츠 인코딩의 전체 목록을 유지 관리합니다.
* 표준은 아니지만 다른 두 가지 콘텐츠 인코딩인 `bzip`과 `bzip2`가 사용되기도 합니다. 이들은 이 두 가지 UNIX 프로그램에서 사용하는 알고리즘을 구현합니다. 첫 번째는 특허 라이선스 문제로 인해 사용이 중단되었습니다.

|  |  |
| --- | --- |
| 헤더 유형 | Response header |
| Forbidden header name | yes |

구문
--

```http
Accept-Patch: application/example, text/example
Accept-Patch: text/example;charset=utf-8
Accept-Patch: application/merge-patch+json
```

지시어
---

없습니다.

예제
--

```http
Accept-Patch: application/example, text/example

Accept-Patch: text/example;charset=utf-8

Accept-Patch: application/merge-patch+json
```

명세서
---

| Specification |
| --- |
| RFC 5789 # section-3.1 |

브라우저 호환성
--------

브라우저 호환성은 이 헤더와 관련이 없습니다. 헤더는 서버에서 전송되며 사양은 클라이언트 동작을 정의하지 않습니다.

같이 보기
-----

* HTTP 메서드 `PATCH`
* HTTP 시맨틱 및 컨텍스트 RFC 7231, 섹션 4.3.4: PUT


Pragma - HTTP

Pragma
======

HTTP/1.0 의 **`Pragma`** 헤더는 요청-응답 체인에 다양한 영향을 줄 수 있는 구현관련 헤더이다. 이것은 HTTP/1.0 버전에서 HTTP/1.1 버전의 `Cache-Control` 헤더가 생기기 전 그것과 동일한 역할을 하는 대용 헤더로 사용되었다.

**참고:** `Pragma` 는 HTTP 응답에서 명시되지 않았던 헤더여서 일반적인 HTTP/1.1 의 `Cache-Control` 헤더의 신뢰할만한 대체재로 사용될수는 없다. 비록 그것이 응답에서 `Cache-Control` 헤더가 생략되었을 시, `Cache-Control: no-cache` 와 동일하게 효과를 주긴 하지만 말이다. `Pragma` 헤더는 HTTP/1.0 를 사용하는 클라이언트들만을 위한 비공식적인 호환성을 위해서 사용하는것이 옳다.

|  |  |
| --- | --- |
| Header type | General header, 그러나 응답 동작은 정해지지
 않아서 구현 방식에 따른다.
  |
| Forbidden header name | 아님 |
| CORS-safelisted response-header | 맞음 |

문법
--
```

Pragma: no-cache
```

디렉티브
----

no-cache

`Cache-Control: no-cache` 와 같다. 캐시가 캐시 복사본을 릴리즈 하기전에 원격 서버로 요청을 날려 유효성 검사를 강제하도록 한다.

예제
--
```

Pragma: no-cache
```

명세서
---

| Specification |
| --- |
| HTTP Caching # field.pragma |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

그외 볼것들
------

* `Cache-Control`
* `Expires`


Expect - HTTP

Expect
======

**`Expect`** HTTP 요청 헤더는 요청을 적절하게 처리하기 위해 서버가 반환할 기대값을 나타냅니다.

명세에 정의된 유일한 기대값인 `Expect: 100-continue`에 대해, 서버는 다음과 같이 응답합니다:

* `100` 헤더에 포함된 정보가, 즉시 성공으로 응답하기 충분할 때
* `417` (en-US) (Expectation Failed) 기대값을 충족하지 못했거나; 어쨌든 4xx 상태일 때

예를들어, 요청의 `Content-Length` 값이 너무 크다면 서버는 이를 거절할 수도 있습니다.

일반적인 브라우저는 `Expect` 헤더를 전송하지 않지만, cURL과 같은 몇가지 클라이언트들은 전송하는 것이 기본값입니다.

|  |  |
| --- | --- |
| Header type | Request header |
| Forbidden header name | no |

Syntax
------

현재는 "100-continue" 를 제외하고 어떤 기대값도 정의되어있지 않습니다.
```

Expect: 100-continue
```

Directives
----------

100-continue

Informs recipients that the client is about to send a (presumably large) message body in this request and wishes to receive a `100` (Continue) interim response.

Examples
--------

### Large message body

클라이언트는 `Expect` 헤더가 포함된 요청을 전송하고 메시지 바디를 전송하기 이전에 서버의 응답을 기다립니다.
```

PUT /somewhere/fun HTTP/1.1
Host: origin.example.com
Content-Type: video/h264
Content-Length: 1234567890987
Expect: 100-continue
```

이제 서버는 요청 헤더를 확인하고 {HTTPStatus("100")}} (Continue) 상태를 응답하여 클라이언트가 계속해서 메시지 바디를 전송하도록 안내하거나, `417` (en-US) (Expectation Failed) 상태를 응답하여 어떠한 기대값도 충족되지 않도록 합니다.

명세서
---

| Specification |
| --- |
| HTTP Semantics # field.expect |

Browser compatibility
---------------------

No common browsers are known to send this header.

See also
--------

* `417` (en-US) `Expectation Failed`
* `100` `Continue`


Alt-Used - HTTP

Alt-Used
========

`Alt-Used` HTTP 헤더는 `Host` HTTP 헤더 필드가 원본의 포트와 호스트를 식별하는 것처럼, 사용 중인 대체 서비스를 식별하기 위해 요청에서 사용됩니다.

이는 프로토콜이 사용 중인 후에 이 정보를 도입하는 것은 문제가 있는 것으로 입증되었기 때문에, 대체 서비스가 루프를 감지하고, 로드 밸런싱을 위해 트래픽을 구분하고, 일반적으로 트래픽의 의도된 목적지를 식별할 수 있도록 하기 위한 것입니다.

클라이언트가 요청에 대체 서비스를 사용하는 경우, `Alt-Used` HTTP 헤더를 사용하여 서버에 이를 표시할 수 있습니다.

구문
--

```http
Alt-Used: <host>:<port>
```

지시어
---

<host>

서버의 도메인 이름입니다.

<port> Optional

서버가 수신 대기 중인 TCP 포트 번호입니다.

예제
--

```http
Alt-Used: alternate.example.net
```

같이 보기
-----

* `Alt-Svc`
* `Host`


Accept-Post - HTTP

Accept-Post
===========

**`Accept-Post`** 응답 HTTP 헤더는 HTTP 포스트 요청에 대해 서버가 수락하는 미디어 유형을 알립니다.

모든 메소드에 대한 응답으로 **`Accept-Post`** 를 사용하면 요청된 리소스에서 `POST`가 허용됨을 의미합니다. 헤더의 모든 문서/미디어 형식은 해당 문서 형식이 허용됨을 추가로 나타냅니다.

예를 들어, 지원되지 않는 미디어 유형이 포함된 `POST` 요청을 수신하는 서버는 `415` `Unsupported Media Type`과 하나 이상의 지원되는 미디어 유형을 참조하는 **`Accept-Post`** 헤더를 사용하여 응답할 수 있습니다.

**참고:** IANA 레지스트리는 공식 콘텐츠 인코딩의 전체 목록을 유지 관리합니다.

|  |  |
| --- | --- |
| 헤더 유형 | 응답 헤더 |
| 금지된 헤더 이름 | 예 |

구문
--

```http
Accept-Post: <MIME\_type>/<MIME\_subtype>
Accept-Post: <MIME\_type>/\*
Accept-Post: \*/\*
```

**참고:** `Accept-Post` 헤더는 기본 설정 개념이 없다는 점(즉, `q` 인수가 없다는 점)을 제외하면 `Accept`와 동일한 방식으로 미디어 범위를 지정합니다. 이는 `Accept-Post`가 응답 헤더인 반면 `Accept`는 요청 헤더이기 때문입니다.

지시어
---

없습니다.

예제
--

```http
Accept-Post: application/example, text/example
Accept-Post: image/webp
Accept-Post: \*/\*
```

명세서
---

| Specification |
| --- |
| Linked Data Platform # header-accept-post |

브라우저 호환성
--------

브라우저 호환성은 이 헤더와 관련이 없습니다. 헤더는 서버에서 전송되며 사양은 클라이언트 동작을 정의하지 않습니다.

같이 보기
-----

* HTTP 메서드 `POST`
* HTTP 시맨틱 및 컨텍스트 RFC 7231, 섹션 4.3.3: POST


Content-Range - HTTP

Content-Range
=============

**`Content-Range`** HTTP 응답 헤더는 전체 바디 메시지에서 부분 메시지가 속한 위치를 알려줍니다.

|  |  |
| --- | --- |
| 헤더 타입 | Response header,
 Payload header |
| 금지된 헤더 이름 | 아니오 |
| CORS-safelisted
 response-header | 아니오 |
| CORS-safelisted response-header | 아니오 |

문법
--

```http
Content-Range: <unit> <range-start>-<range-end>/<size>
Content-Range: <unit> <range-start>-<range-end>/\*
Content-Range: <unit> \*/<size>
```

지시자
---

<unit>

단위는 범위를 지정합니다. 보통 `bytes`를 사용합니다.

<range-start>

범위 요청의 시작을 알려주는 정수 단위.

<range-end>

범위 요청의 끝을 알려주는 정수 단위.

<size>

문서의 총 크기(또는 모른다면 `'*'`)

예제
--

```http
Content-Range: bytes 200-1000/67589
```

명세서
---

| Specification |
| --- |
| HTTP Semantics # field.content-range |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 참고할 내용
---------

* `If-Range`
* `Range`
* `Content-Type`
* `206` `Partial Content`
* `416` `Range Not Satisfiable`


Access-Control-Allow-Headers - HTTP

Access-Control-Allow-Headers
============================

**`Access-Control-Allow-Headers`** 는 `Access-Control-Request-Headers`를 포함하는 preflight request의 응답에 사용되는 헤더로, 실제 요청때 사용할 수 있는 HTTP 헤더의 목록을 나열합니다.

요청에 `Access-Control-Request-Headers` 헤더가 포함되어 있을 경우, 이 헤더를 포함하여야 합니다.

|  |  |
| --- | --- |
| Header type | Response header |
| Forbidden header name | no |

구문
--
```

Access-Control-Allow-Headers: <header-name>[, <header-name>]*
Access-Control-Allow-Headers: *
```

지시자
---

`<header-name>`

지원하는 헤더의 이름입니다. 쉼표로 구분하여 원하는 만큼 헤더를 나열할 수 있습니다.

`*` (와일드카드)

"`*`" 값은 자격 증명이 없는 요청(쿠키 혹은 HTTP 인증 정보가 없는 요청)일 경우 특수한 와일드 카드로 처리됩니다. 자격증명을 포함하는 경우 단순히 "`*`"라는 이름을 갖는 특별한 의미가 없는 헤더로 취급됩니다. 단, `Authorization` 헤더는 와일드카드에 포함되지 않으며 명시적으로 나열해야 합니다.

예제
--

### 사용자 정의 헤더

다음은 `Access-Control-Allow-Headers` 헤더가 어떤 식으로 작성되는지에 대한 예시입니다. CORS에서 안전한 헤더외에도 X-Custom-Header라는 사용자 정의 헤더가 서버에 대한 CORS 요청에 의해 지원됨을 나타냅니다.
```

Access-Control-Allow-Headers: X-Custom-Header
```

### 여러 개의 헤더

이 예시는 여러 개의 헤더를 지정할 때 Access-Control-Allow-Headers가 어떤 식으로 작성되는지 보여줍니다.
```

Access-Control-Allow-Headers: X-Custom-Header, Upgrade-Insecure-Requests
```

### Preflight 요청 예시

사전 요청에서 `Access-Control-Allow-Headers` 이 사용된 경우의 예제를 보도록 합시다.

#### 요청

이 Preflight 요청은 Preflight 요청 헤더인 `Access-Control-Request-Method`, `Access-Control-Request-Headers` 및 `Origin`, 이 세가지 Preflight 요청 헤더를 포함하는 `OPTIONS` 요청입니다.
```

OPTIONS /resource/foo
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://foo.bar.org
```

#### 응답

만약 서버가 `DELETE` 메소드에 CORS 요청을 허용한다면 `Access-Control-Allow-Methods`에 DELETE, 그리고 다른 지원하는 메소드를 포함하여 응답합니다.
```

HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: https://foo.bar.org
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400
```

요청된 메소드가 지원되지 않으면 서버는 오류로 응답합니다.

명세
--

| Specification |
| --- |
| Fetch Standard # http-access-control-allow-headers |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 보기
-----

* `Access-Control-Allow-Origin`
* `Access-Control-Expose-Headers`
* `Access-Control-Allow-Methods`
* `Access-Control-Request-Headers`


Strict-Transport-Security - HTTP

Strict-Transport-Security
=========================

HTTP **`Strict-Transport-Security`** 응답 헤더(종종 HSTS로 축약됨)는 사이트가 HTTPS를 통해서만 접근되어야 하며 향후 HTTP를 사용하여 사이트에 접근하려는 모든 시도는 자동으로 HTTPS로 변환되어야 함을 브라우저에 알립니다.

**참고:** 처음 HTTP 연결이 여전히 중간자 공격에 취약한 서버에서 단순히 HTTP를 HTTPS(301) 리디렉션으로 구성하는 것보다 더 안전합니다.

|  |  |
| --- | --- |
| 헤더 종류 | 응답 헤더 |
| 금지된 헤더 이름 | 아니요 |

구문
--

```http
Strict-Transport-Security: max-age=<expire-time>
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains
Strict-Transport-Security: max-age=<expire-time>; includeSubDomains; preload
```

지시어
---

`max-age=<expire-time>`

HTTPS를 통해서만 사이트에 접근할 수 있음을 브라우저가 기억해야 하는 시간(초)입니다.

`includeSubDomains` Optional

이 선택적 매개변수가 지정된 경우, 이 규칙은 사이트의 모든 하위 도메인에도 적용됩니다.

`preload` Optional
비표준

자세한 내용은 Strict Transport Security 프리로딩를 참조하십시오. `preload`를 사용하는 경우 `max-age` 지시어는 `31536000`(1년) 이상이어야 하며 `includeSubDomains` 지시문이 있어야 합니다. 사양의 일부가 아닙니다.

설명
--

 웹사이트가 HTTP를 통한 연결을 수락하고 HTTPS로 리디렉션하는 경우, 방문자는 리디렉션되기 전에 먼저 사이트의 비암호화 버전과 통신할 것입니다. 예를 들어 방문자가 `http://www.foo.com/`을 입력하거나 심지어 그냥 foo.com을 입력하는 경우입니다.
 이는 중간자 공격의 기회를 만듭니다. 리디렉션을 악용하여 방문자를 원래 사이트의 보안 버전이 아닌 악의적인 사이트로 안내할 수 있습니다.

HTTP Strict Transport Security 헤더는 브라우저가 HTTP를 사용하여 사이트를 불러와서는 안 되며 대신 HTTP를 사용하여 사이트에 접근하려는 모든 시도를 HTTPS 요청으로 자동 변환해야 함을 알립니다.

**참고:** `Strict-Transport-Security` 헤더가 사이트가 HTTP를 통해서만 접근할 수 있다면 브라우저에 의해 **무시됩니다**.
 인증서 오류 없이 HTTPS를 통해 사이트에 액세스할 수 있다면 브라우저는 사이트가 HTTPS를 사용할 수 있음을 인식하고 `Strict-Transport-Security` 헤더를 준수합니다.
 브라우저는 공격자가 사이트에 대한 HTTP 연결을 가로채서 헤더를 삽입하거나 제거할 수 있으므로 이 작업을 수행합니다.

### 예제 시나리오

 공항에서 무료 Wi-Fi 액세스 포인트에 로그인하고 웹 서핑을 시작하고 온라인 뱅킹 서비스를 방문하여 잔액을 확인하고 몇 가지 청구서를 지불합니다.
 불행하게도 여러분이 사용하고 있는 액세스 포인트는 실제로 해커의 노트북이며 해커는 여러분의 원래 HTTP 요청을 가로채 실제 사이트 대신 은행 사이트의 복제본으로 리디렉션하고 있습니다. 이제 여러분의 개인 데이터가 해커에게 노출됩니다.

Strict Transport Security는 이 문제를 해결합니다. HTTPS를 사용하여 은행 웹사이트에 한 번 접근했고 은행 웹사이트에서 Strict Transport Security를 사용하는 한, 브라우저는 자동으로 HTTPS만 사용한다는 것을 알게 되어 해커가 이러한 종류의 중간자 공격을 수행하지 못하도록 방지합니다.

### 브라우저가 처리하는 방법

HTTPS를 사용하여 사이트에 처음으로 접근하고 `Strict-Transport-Security` 헤더를 반환하면 브라우저가 이 정보를 기록하고, 이후에 HTTP를 사용하여 사이트를 로드하려고 시도할 때 자동으로 HTTPS를 대신 사용합니다.

`Strict-Transport-Security` 헤더에 지정된 만료 시간이 경과하면 HTTP를 통해 사이트를 불러오려는 다음 시도는 자동으로 HTTPS를 사용하지 않고 정상적으로 진행됩니다.

 Strict-Transport-Security 헤더가 브라우저에 전달될 때마다 사이트의 만료 시간을 업데이트하기 때문에 사이트는 정보를 새로 고칠 수 있고, 만료되는 것을 방지할 수 있습니다.
 엄격 전송 보안을 비활성화해야 하는 경우 `max-age`를 0(https 연결 종료)으로 설정하면 `Strict-Transport-Security` 헤더가 즉시 만료되어 http를 통한 접근이 허용됩니다.

Strict Transport Security 프리로딩
------------------------------

 Google은 HSTS 프리로딩 서비스를 관리하고 있습니다. 지침을 따르고 도메인을 성공적으로 제출하면 브라우저가 보안 연결을 통해서만 도메인에 연결되도록 할 수 있습니다.
 서비스가 Google에서 호스팅되는 동안 모든 브라우저는 이 사전 로드 목록을 사용합니다.
 그러나 HSTS 사양의 일부가 아니므로 공식적인 것으로 취급해서는 안 됩니다.

* Chrome의 HSTS 사전 로드 목록 관련 정보: https://www.chromium.org/hsts
* Firefox HSTS 사전 로드 목록 참조: nsSTSPreloadList.inc
예제
--

현재와 미래의 모든 하위 도메인은 1년의 `max-age` 동안 HTTPS가 됩니다. 이는 HTTP를 통해서만 제공될 수 있는 페이지 또는 하위 도메인에 대한 접근을 차단합니다.

```http
Strict-Transport-Security: max-age=31536000; includeSubDomains
```

도메인에 대해 1년의 `max-age`이 허용되긴 하지만, https://hstspreload.org에 설명된 대로 권장 값은 2년입니다.

다음 예는 `max-age`를 2년으로 설정하고 Chromium, Edge, 그리고 Firefox와 같은 모든 주요 웹 브라우저의 HSTS 사전 로드 목록에 포함하는 데 반드시 필요한 사전 로드 접미사가 붙습니다.

```http
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
```

명세서
---

| Specification |
| --- |
| HTTP Strict Transport Security (HSTS) # section-6.1 |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* 블로그 포스트: HTTP Strict Transport Security has landed!
* 플로그 포스트: HTTP Strict Transport Security (force HTTPS)
* OWASP 문서: HTTP Strict Transport Security
* 위키백과: HTTP Strict Transport Security
* HSTS 프리로드 서비스
* 보안 컨텍스트로 제한된 기능


From - HTTP

From
====

**`From`** 요청 헤더는 요청한 사용자 에이전트를 제어하는 인간 사용자의 인터넷 이메일을 포함합니다.

만약 당신이 (예를 들어 크롤러와 같은) 로보틱 사용자 에이전트를 실행하고 있다면, `From` 헤더를 반드시 전송해야 하며, 로봇이 한도를 초과하거나 원하지 않으며, 유효하지 않은 요청을 전송하고 있는 경우처럼 서버 상에 문제를 일으키고 있다면 당신에게 해당 이메일로 연락이 가능해야 합니다.

**경고:** 접근 제어 혹은 인증을 위해 `From` 헤더를 사용해서는 안됩니다.

|  |  |
| --- | --- |
| Header type | Request header |
| Forbidden header name | no |

문법
--
```

From: <email>
```

디렉티브
----

<email>

기계가 사용 가능한 이메일 주소.

예제
--
```

From: webmaster@example.org
```

명세
--

| Specification |
| --- |
| HTTP Semantics # field.from |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 참고할 내용
---------

* `Host`


Range - HTTP

Range
=====

**`Range`** HTTP 요청 헤더는 서버에게 문서의 일부분만 돌려주어야 한다는 것을 알려줍니다. `Range` 헤더를 통해 여러 부분을 한번에 요청할 수 있으며, 서버는 이러한 범위에 대해 문서의 여러 부분을 돌려보내줄 것입니다. 만약 서버가 돌려 보낸다면, `206` `Partial Content`를 응답으로 사용할 것입니다. 만약 범위가 유효하지 않다면, 서버는 `416` `Range Not Satisfiable` 에러를 보낼 것입니다. 또한 서버는 `Range` 헤더를 무시하고 `200` 상태 코드와 함께 전체 문서를 돌려줄 수 있습니다.

|  |  |
| --- | --- |
| 헤더 타입 | Request header |
| Forbidden header name | 아니오 |

문법
--
```

Range: <unit>=<range-start>-
Range: <unit>=<range-start>-<range-end>
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>
Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end>
```

지시자
---

<unit>

범위를 결정하는 단위. 보통 `bytes`.

<range-start>

범위 요청의 시작 지점을 알리는 단위를 뜻하는 정수.

<range-end>

요청한 범위의 끝을 알리는 단위를 의미하는 정수. 이 값은 옵션으로 사용할 수 있으며, 생략한다면 문서의 끝부분을 요청의 끝으로 사용함.

예제
--
```

Range: bytes=200-1000, 2000-6576, 19000-
```

기술 사양
-----

| 기술 사양 | 제목 |
| --- | --- |
| RFC 7233, 섹션 3.1: Range | Hypertext Transfer Protocol (HTTP/1.1): Range Requests |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 참고할 내용
---------

* `If-Range`
* `Content-Range`
* `Content-Type`
* `206` `Partial Content`
* `416` `Range Not Satisfiable`


If-Modified-Since - HTTP

If-Modified-Since
=================

**`If-Modified-Since`** HTTP 요청 헤더는 조건부 요청으로 서버는 지정된 날짜 이후 수정 된 경우에 `200` 과 함께 요청된 리소스를 돌려 줍니다. 만약 수정되지 않는 리소스에 대한 요청시, 리소스 없이 `304` 응답을 하게 됩니다. 이전 요청의 `Last-Modified` 응답 헤더는 마지막으로 수정 한 날짜를 포함합니다.`If-Modified-Since`는 `If-Unmodified-Since` 와는 다르게 `GET` 또는 `HEAD` 에서만 쓸수 있습니다.

서버가 `If-None-Match`를 지원하지 않는 한 `If-None-Match` 를 함께 사용시 무시 됩니다.

가장 일반적인 사용예로, `ETag` 가 없는 캐시된 엔티티로 업데이트 합니다.

|  |  |
| --- | --- |
| Header type | Request header |
| Forbidden header name | no |

문법
--
```

If-Modified-Since: <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT
```

지시자
---

<day-name>

"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 또는 "Sun" 중 하나(대소문자 구분).

<day>

2 숫자의 날짜, 예: "04" 또는 "23".

<month>

"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 중 하나(대소문자 구분).

<year>

4 숫자의 연도, 예: "1990" 또는 "2016".

<hour>

2 숫자의 분, 예: "04" 또는 "59.

<minute>

2 숫자의 초, 예: "04" 또는 "59".

<second>

2 digit second number, e.g. "04" or "59".

`GMT`

그리니치 표준시. HTTP 날짜는 현지 시각이 아닌, 언제나 GMT로 표현합니다.

예제
--
```

If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
```

기술 사양
-----

| 기술 사양 | 제목 |
| --- | --- |
| RFC 7232, 섹션 3.3: If-Modified-Since | Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 참고할 내용
---------

* `ETag`
* `If-Unmodified-since`
* `If-Match` (en-US)
* `If-None-Match`
* `304` `Not Modified`


X-Forwarded-Proto - HTTP

X-Forwarded-Proto
=================

**`X-Forwarded-Proto`** (XFP) 헤더는 클라이언트가 당신의 프록시 또는 로드 밸런서에 접속하는데에 사용했던 프로토콜(HTTP 또는 HTTPS)이 무엇인지 확인하는 사실상의 표준 헤더 입니다. 당신의 서버 접근 로그들은 서버와 로드 밸런서 사이에서 사용된 프로토콜을 포함하고 있습니다. 그러나 클라이언트와 로드밸런서에 사용한 프로토콜은 포함되어 있지 않습니다. 클라이언트와 로드밸런서 간의 사용된 프로토콜을 확인하기 위해서, `X-Forwarded-Proto 요청 헤더가 사용되어 질 수 있습니다.`

이 헤더의 표준화된 버전은 HTTP `Forwarded` 헤더 입니다.

|  |  |
| --- | --- |
| Header type | Request header |
| Forbidden header name | no |

Syntax
------
```

X-Forwarded-Proto: <protocol>
```

Directives
----------

<protocol>

넘겨져야 할 프로토콜 (http 또는 https).

Examples
--------
```

X-Forwarded-Proto: https
```

그 외의 비표준 폼:
```

# Microsoft
Front-End-Https: on

X-Forwarded-Protocol: https
X-Forwarded-Ssl: on
X-Url-Scheme: https
```

Specifications
--------------

어떠한 현재의 명세에도 포함되어 있지 않습니다. 이 헤더의 표준화된 버전은 `Forwarded` 입니다..

See also
--------

* `Forwarded`
* `X-Forwarded-For`
* `X-Forwarded-Host`


Keep-Alive - HTTP

Keep-Alive
==========

**비표준:** 이 기능은 비표준이므로 실제 프로덕션에서 사용하지 마세요. 모든 사용자 환경에서 작동하지 않을 수 도 있으며, 미래에 호환성 문제가 생길 수 있습니다.

**`Keep-Alive`** 일반 헤더는 송신자가 연결에 대한 타임아웃과 요청 최대 개수를 어떻게 정했는지에 대해 알려줍니다.

**참고:** `Connection` 헤더는 이 헤더를 위해 어떤 의미든 갖도록 "keep-alive"로 설정되어야 합니다. 또한, `Connection`과 `Keep-Alive`는 HTTP/2에서 무시됩니다; 연결 관리는 해당 프로토콜 내에서 다른 메커니즘에 의해 처리됩니다.

|  |  |
| --- | --- |
| Header type | General header |
| Forbidden header name | no |

문법
--
```

Keep-Alive: parameters
```

디렉티브
----

*파라메터*

쉼표로 구분된 파라메터 목록으로, 각각 등호('=')로 구분되는 식별자와 값으로 구성됩니다. 다음은 사용 가능한 식별자들입니다:

* `timeout`: 유휴 연결이 계속 열려 있어야 하는 *최소한의* 시간(초 단위)을 가르킵니다. keep-alive TCP 메시지가 전송 계층에 설정되지 않는다면 TCP 타임아웃 이상의 타임아웃은 무시된다는 것을 알아두시기 바랍니다.
* `max`: 연결이 닫히기 이전에 전송될 수 있는 최대 요청 수를 가리킵니다. 만약 `0`이 아니라면, 해당 값은 다음 응답 내에서 다른 요청이 전송될 것이므로 비-파이프라인 연결의 경우 무시됩니다. HTTP 파이프라인은 파이프라이닝을 제한하는 용도로 해당 값을 사용할 수 있습니다.

예제
--

Keep-Alive 헤더를 포함하는 응답:
```

HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Thu, 11 Aug 2016 15:23:13 GMT
Keep-Alive: timeout=5, max=1000
Last-Modified: Mon, 25 Jul 2016 04:32:39 GMT
Server: Apache

(body)
```

명세
--

| Specification |
| --- |
| HTTP/1.1 # compatibility.with.http.1.0.persistent.connections |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

함께 참고할 내용
---------

* `Connection`
* Connection management in HTTP/1.x


Access-Control-Allow-Origin - HTTP

Access-Control-Allow-Origin
===========================

**`Access-Control-Allow-Origin`** 응답 헤더는 이 응답이 주어진 origin으로부터의 요청 코드와 공유될 수 있는지를 나타냅니다.

|  |  |
| --- | --- |
| Header type | Response header |
| Forbidden header name | no |

구문
--
```

Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
Access-Control-Allow-Origin: null
```

지시자
---

`*`

*credential*이 없는 요청들에 와일드카드로써 문자 값 "\*"이 명시될 수 있습니다. 이 값은 브라우저에 리소스에 접근하는 임의의 origin으로부터의 요청 코드를 허용함을 알립니다. 와일드카드를 credential과 함께 사용하려고 하면 오류가 발생합니다.

`<origin>`

origin을 명시합니다. 하나의 origin만 명시될 수 있습니다.

예시
--

브라우저에 리소스에 접근하는 임의의 origin으로부터의 요청을 허용한다고 알리는 응답은 다음을 포함할 것입니다:
```

Access-Control-Allow-Origin: *
```

브라우저에 `https://developer.mozilla.org`으로부터의 요청을 허용한다고 알리는 응답은 다음을 포함할 것입니다:
```

Access-Control-Allow-Origin: https://developer.mozilla.org
```

가능한 `Access-Control-Allow-Origin` 값을 허용된 origin 집합으로 제한하는 것은 요청 헤더의 `Origin`를 검사하는 서버 측 코드가 필요합니다. 이를 허용된 origin 리스트와 비교하고, `Origin` 값이 리스트에 있으면 `Access-Control-Allow-Origin` 값을 `Origin`과 동일한 값으로 설정합니다.

### CORS and caching

서버가 ("`*`" 와일드카드 외에) 명시적인 origin을 `Access-Control-Allow-Origin` 과 함께 응답으로 보내면, 응답은 값이 `Origin`인 `Vary` 응답 헤더 또한 포함해야 합니다 — 브라우저에 서버가 `Origin` 요청 헤더의 값에 따라 다르게 응답할 수 있음을 알리기 위해.
```

Access-Control-Allow-Origin: https://developer.mozilla.org
Vary: Origin
```

### Handling CORS on the server (Java example)

다음의 Java 코드는 CORS 요청 헤더를 설정합니다. 코드가 어떻게 `Access-Control-Allow-Origin` 값을 `Origin` 요청 헤더와 동일한 값을 설정하는지 알아 두십시오.

```java
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

public SimpleCORSFilter() {
    log.info("SimpleCORSFilter init");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}
```

명세서
---

| Specification |
| --- |
| Fetch Standard # http-access-control-allow-origin |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

참고
--

* `Origin`
* `Vary`
* CORS 문제를 어떻게 해결하나요?


Access-Control-Allow-Methods - HTTP

Access-Control-Allow-Methods
============================

**`Access-Control-Allow-Methods`** 헤더는 사전 요청에 대한 응답으로 리소스에 접근할 때 허용되는 메서드를 지정합니다.

|  |  |
| --- | --- |
| 헤더 타입 | 응답 헤더 |
| 금지된 헤더 이름 | no |

문법
--

```http
Access-Control-Allow-Methods: <method>, <method>, …
Access-Control-Allow-Methods: \*
```

디렉티브
----

`<method>`

허용된 HTTP 요청 메서드의 목록이며 콤마로 구분됩니다.

`*` (와일드카드)

`*`는 자격 증명이 없는 요청 (쿠키나 HTTP 인증 정보가 없는 요청)에 대해서만 특수 와일드카드 값으로 취급됩니다. 자격 증명이 있는 요청에서는 특별한 의미를 갖지 않고 단순히 "\*"라는 메서드 이름으로 취급됩니다.

예제
--

```http
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Methods: \*
```

명세
--

| Specification |
| --- |
| Fetch Standard # http-access-control-allow-methods |

브라우저 호환성
--------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

같이 보기
-----

* `Access-Control-Allow-Origin`
* `Access-Control-Expose-Headers`
* `Access-Control-Allow-Headers`
* `Access-Control-Request-Method`