1. 라이브러리
  2. HTTP와 웹
  3. HTTP 상태 코드

업데이트됨 1개월 전

다른 모든 HTTP 상태 코드는 문장 끝의 마침표입니다. 1xx 코드는 쉼표입니다.

이 정보 응답들은 "요청을 받았습니다, 처리 중입니다, 하지만 아직 완료되지 않았습니다"라고 말합니다. 200이나 404와 달리, 1xx 응답은 HTTP 트랜잭션을 끝내지 않습니다—최종 상태 코드가 반드시 뒤따르는 중간 업데이트입니다.

직접 보는 일은 거의 없습니다. 하지만 내부에서 작동하며 HTTP의 가장 영리한 기능들을 가능하게 합니다.

100 Continue: "정말 하시겠어요?"

1GB 동영상을 업로드하려는 상황을 생각해보세요. 제출을 클릭합니다. 파일이 업로드되기 시작합니다. 30초 후, 서버가 응답합니다: 401 Unauthorized.

서버가 절대 받지 않을 데이터를 업로드하느라 대역폭과 시간을 낭비한 것입니다.

100 Continue 프로토콜이 이를 방지합니다. 전송을 확정하기 전에 HTTP가 "정말 하시겠어요?"라고 먼저 묻는 것입니다:

클라이언트가 헤더만 전송:

POST /api/upload HTTP/1.1
Host: example.com
Authorization: Bearer token123
Content-Length: 1073741824
Expect: 100-continue

서버가 헤더를 확인합니다. 토큰이 유효한가요? 이 파일을 받을 공간이 있나요? 콘텐츠 유형이 허용되나요?

모든 것이 괜찮다면:

HTTP/1.1 100 Continue

이제 클라이언트가 1GB 본문을 전송합니다.

문제가 있다면:

HTTP/1.1 401 Unauthorized

클라이언트는 본문을 전송하지 않습니다. 1기가바이트의 대역폭이 절약됩니다.

대부분의 HTTP 라이브러리는 대용량 업로드 시 이를 자동으로 처리합니다. Expect: 100-continue 헤더가 이를 작동시킵니다. 특별한 코드를 작성하지 않아도 혜택을 받습니다.

101 Switching Protocols: "다른 방식으로 이야기해요"

HTTP는 요청-응답 프로토콜입니다. 클라이언트가 묻고, 서버가 답합니다. 하지만 실시간 양방향 통신이 필요하다면 어떨까요—채팅 앱, 실시간 업데이트, 멀티플레이어 게임?

HTTP로 시작해서 다른 프로토콜로 업그레이드합니다.

클라이언트가 WebSocket 업그레이드를 요청:

GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

서버가 동의:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

이 과정이 끝나면, 연결은 더 이상 HTTP가 아닙니다. WebSocket입니다—양방향으로, 양쪽 모두 언제든지 메시지를 보낼 수 있습니다.

이 코드를 직접 작성할 일은 없습니다. WebSocket 라이브러리가 처리합니다. 하지만 WebSocket 연결 중 네트워크 인스펙터에서 101 Switching Protocols를 보게 된다면, 이제 무슨 일이 일어났는지 알 수 있습니다: HTTP가 정중하게 자리를 비켜준 것입니다.

103 Early Hints: "이것들을 미리 로드하세요"

이번엔 성능 이야기입니다. 문제는 이렇습니다:

서버가 데이터베이스를 조회하고 HTML을 렌더링하는 데 200ms가 필요합니다. 브라우저는 그 HTML을 받아 파싱하기 전까지 CSS와 JavaScript 로딩을 시작할 수 없습니다. 브라우저가 아무것도 못 하고 기다리는 200ms의 낭비입니다.

103 Early Hints는 서버가 "아직 작업 중이지만, 이것들을 미리 로드하세요"라고 말할 수 있게 합니다:

HTML이 준비되기 전에 즉시:

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style
Link: </main.js>; rel=preload; as=script

서버가 아직 데이터베이스를 조회하는 동안 브라우저는 그 리소스들을 가져오기 시작합니다.

200ms 후, 실제 응답:

HTTP/1.1 200 OK
Content-Type: text/html

<html>
  <link rel="stylesheet" href="/style.css">
  <script src="/main.js"></script>
  ...
</html>

브라우저가 HTML을 파싱할 때쯤에는 CSS와 JavaScript가 이미 로딩 중이거나—이미 완료된 상태입니다.

Early Hints는 서버 처리가 느리고 페이지에 필요한 리소스를 미리 알고 있을 때 진가를 발휘합니다. 브라우저는 그렇지 않았다면 낭비되었을 시간 동안 유용한 작업을 수행합니다.

브라우저 지원이 늘어나고 있습니다. Chrome과 Edge는 완전히 지원합니다. 103을 이해하지 못하는 브라우저는 단순히 무시합니다—아무런 문제가 없습니다.

눈에 보이지 않는 이유

애플리케이션 코드에서 1xx 응답은 보이지 않습니다:

const response = await fetch('/api/upload');
console.log(response.status); // 200, 404, 500... 100이나 103은 절대 나타나지 않음

브라우저가 더 낮은 수준에서 이를 처리합니다. fetch API는 최종 응답만 표시합니다.

WebSocket 연결은 101을 감춥니다:

const socket = new WebSocket('wss://example.com/chat');
// 프로토콜 업그레이드가 일어났습니다. 당신은 그것을 보지 못했습니다.

1xx 응답을 직접 확인하려면, 브라우저 개발자 도구(네트워크 탭의 응답 세부 정보)나 -v 옵션을 사용한 curl 같은 명령줄 도구를 활용하세요.

왜 중요한가

1xx 코드는 실제 문제를 해결합니다:

100 Continue는 실패할 업로드의 대역폭을 절약합니다. 서버가 헤더만으로 거부할 것이라면 1기가바이트를 왜 보내겠습니까?

101 Switching Protocols는 실시간 웹을 가능하게 합니다. 모든 WebSocket 연결은 여기서 시작됩니다.

103 Early Hints는 서버와 브라우저 사이의 작업을 병렬로 처리해 페이지 로딩을 더 빠르게 만듭니다.

HTTP가 우아하게 진화하는 방식도 보여줍니다. 중간 응답을 위한 카테고리를 미리 마련해둠으로써, 프로토콜은 기존 클라이언트를 깨뜨리지 않고 새로운 코드를 추가할 수 있습니다. 103을 이해하지 못하는 브라우저는 단순히 무시하고 최종 응답을 기다립니다.

직접 1xx 처리를 구현할 일은 아마 없을 것입니다. 하지만 항상 그 혜택을 받고 있습니다—모든 WebSocket 연결, 모든 대용량 업로드, 일찍 전달된 힌트 덕분에 조금 더 빨리 로딩되는 모든 페이지에서.

1xx 상태 코드에 관한 자주 묻는 질문

JavaScript 코드에서 1xx 응답이 보이지 않는 이유는?

브라우저는 fetch API나 XMLHttpRequest보다 더 낮은 수준에서 1xx 응답을 처리합니다. 이 중간 응답들은 내부적으로 처리됩니다—브라우저는 이에 따라 작동하지만(미리 지정된 리소스 로딩 시작, 본문 전송 전 대기, 프로토콜 업그레이드), 코드에는 최종 응답만 전달됩니다.

서버에서 100 Continue 처리를 직접 구현해야 하나요?

대부분의 웹 프레임워크가 자동으로 처리합니다. 대용량 업로드를 받는 서버를 처음부터 만들고 있다면, 요청 본문을 읽기 전에 Expect: 100-continue 헤더를 확인하고 적절히 응답해야 합니다. 하지만 Express, Django, Rails 같은 프레임워크는 이를 알아서 처리합니다.

최종 응답 전에 여러 개의 1xx 응답을 보낼 수 있나요?

네. 이론적으로 서버는 103 Early Hints를 보낸 뒤 100 Continue를, 그리고 마지막으로 200 OK를 보낼 수 있습니다. 하지만 실제로는 요청 하나에 중간 응답이 두 개 이상 오는 경우는 거의 없습니다.

이 페이지가 도움이 되었나요?

😔
🤨
😃