테마
HTTP의 기초 2
HTTP의 기초에서 본 요청과 응답 메시지에서, 응답이 결과를 어떻게 알리는지 이어서 다룬다. 응답 첫 줄의 세 자리 숫자인 상태 코드(status code)와 자주 쓰는 헤더(header)를 본다. 이어서 HTTP가 요청 사이의 일을 기억하지 않는 무상태(stateless) 프로토콜(protocol)이라는 점과, 한 연결을 여러 요청에 재사용하는 방식을 정리한다.
상태 코드
상태 코드는 응답 첫 줄의 세 자리 숫자로, 첫 자리가 분류를 나타낸다. 예를 들어 3xx는 요청을 다른 주소로 다시 보내게 하는 리다이렉션(redirection)이다.
| 분류 | 뜻 | 자주 보는 코드 |
|---|---|---|
| 1xx | 정보. 처리 중 | 101 프로토콜 전환 |
| 2xx | 성공 | 200 OK, 201 생성됨, 204 본문 없음 |
| 3xx | 리다이렉션. 다른 곳을 보라 | 301 영구 이동, 302 임시 이동, 304 수정 안 됨 |
| 4xx | 클라이언트 오류 | 400, 401, 403, 404, 409, 429 |
| 5xx | 서버 오류 | 500, 502, 503, 504 |
- 101은 같은 연결을 웹소켓(WebSocket) 같은 다른 프로토콜로 바꾸자는 요청을 서버가 받아들였다는 뜻이다.
- 201 Created는
POST로 새 리소스(resource, URL이 가리키는 대상)가 만들어졌다는 뜻이고, 보통 새 리소스 위치를Location헤더에 담는다. 204 No Content는 성공했지만 돌려줄 본문이 없다는 뜻이다. - 301은 주소가 영구히 바뀌었다는 뜻이라 검색 엔진과 브라우저가 새 주소를 기억한다. 302는 잠깐만 다른 곳을 보라는 뜻이다. 304 Not Modified는 "가진 캐시(cache)를 그대로 써도 된다"는 답으로, HTTP의 응용에서 다룬다.
- 400은 요청 형식이 잘못됐다는 뜻이다. 404는 대상이 없다는 뜻이고, 409 Conflict는 이미 있는 아이디로 가입하는 것처럼 현재 리소스 상태와 충돌한다는 뜻이다. 429 Too Many Requests는 정해진 시간 안에 요청을 너무 많이 보냈다는 뜻이다.
- 500은 서버 내부의 예상 못 한 오류다. 502 Bad Gateway는 중간에서 요청을 받아 뒤쪽 서버로 넘기는 게이트웨이(gateway)나 프록시(proxy)가 뒤쪽 서버에서 잘못된 응답을 받았다는 뜻이다. 웹 서버 프로그램인 nginx 같은 프록시는 뒤쪽 서버에 연결 자체가 거부될 때도 502를 돌려준다. 503 Service Unavailable은 과부하나 점검으로 잠시 처리할 수 없다는 뜻이다. 504 Gateway Timeout은 중간 서버가 뒤쪽 서버의 응답을 제때 받지 못했다는 뜻이다.
401과 403
401 Unauthorized는 이름과 달리 "누구인지 확인되지 않았다"는 인증(authentication) 실패다. 로그인하지 않았거나 토큰(token, 로그인한 사용자임을 증명하는 문자열)이 만료된 경우이고, 올바른 인증 정보를 보내면 통과할 수 있다. 403 Forbidden은 "누구인지는 알지만 권한이 없다"는 인가(authorization) 실패다. 일반 사용자가 관리자 페이지에 들어가려는 경우처럼, 같은 신분으로 다시 보내도 결과가 같다.
자주 쓰는 헤더
| 헤더 | 방향 | 뜻 |
|---|---|---|
Host | 요청 | 요청 대상 도메인. HTTP/1.1에서 반드시 보내야 한다 |
Content-Type | 양쪽 | 본문 형식. 예: application/json |
Content-Length | 양쪽 | 본문 크기(바이트) |
Accept | 요청 | 클라이언트가 받고 싶은 형식 |
Authorization | 요청 | 인증 정보. 예: Bearer <토큰> |
User-Agent | 요청 | 요청을 보낸 프로그램(브라우저 종류 등) |
Host 헤더가 필수인 이유는 IP(Internet Protocol, 인터넷 프로토콜) 주소 하나에 여러 도메인 이름(domain name)의 사이트가 함께 올라가 있는 경우가 흔하기 때문이다. 서버는 이 헤더를 보고 어느 사이트로 온 요청인지 가른다.
무상태성
HTTP는 무상태 프로토콜이다. 서버는 앞선 요청을 기억하지 않고, 요청 하나를 그 안에 담긴 정보만으로 처리한다. 그래서 어떤 서버가 요청을 받아도 같은 결과를 낼 수 있어, 서버를 여러 대로 늘리기 쉽다. 대신 로그인 상태처럼 요청 사이에 이어져야 하는 정보는 쿠키(cookie)나 토큰에 담아 매 요청마다 다시 보내야 한다. 그 방법은 HTTP의 응용에서 다룬다.
연결 재사용
HTTP 메시지는 보통 TCP(Transmission Control Protocol, 전송 제어 프로토콜) 연결 위로 오간다. 초기 HTTP/1.0은 요청 하나마다 TCP 연결을 새로 맺고 끊었다. 연결을 맺을 때마다 핸드셰이크(handshake)로 메시지가 한 번 더 오가야 해서, 요청마다 그만큼 기다리는 시간이 늘었다. 그래서 이미지가 많은 페이지는 느려졌다.
HTTP/1.1은 지속 연결(persistent connection)을 기본으로 한다. 한 번 맺은 TCP 연결로 여러 요청과 응답을 차례로 주고받고, 어느 한쪽이 Connection: close를 보내거나 한동안 쓰이지 않을 때 닫는다. HTTP/1.0에서는 Connection: keep-alive 헤더로 따로 요청해야 했던 동작이라, 지금도 이 기능을 keep-alive라고 부르곤 한다. 버전별 차이는 TCP와 UDP와 HTTP의 응용 2로 이어진다.
면접 포인트
- "401과 403 차이는?" → 401은 인증 실패(누구인지 모름), 403은 인가 실패(알지만 권한 없음).
- "502와 504 차이는?" → 둘 다 중간 서버가 보고, 502는 뒤쪽 서버의 잘못된 응답, 504는 응답 시간 초과.
- "HTTP가 무상태인 이유와 영향은?" → 서버 확장이 쉬워지는 대신 상태는 쿠키·토큰으로 매번 실어 보낸다.
