개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

기초개념 › 네트워크

HTTP 요청

HTTP 요청은 어떻게 생긴 글인가

브라우저가 서버에 보내는 HTTP 요청은 정해진 모양의 글자 몇 줄입니다. 첫 줄(요청 줄)에는 메서드, 경로, 버전을 적습니다. 그 아래에는 "이름: 값" 꼴의 줄인 헤더를 적고, 아무 글자도 없는 빈 줄로 헤더가 끝났음을 알립니다(본문이 없는 요청은 여기서 끝납니다). 서버는 이 글을 읽어 무엇을 달라는 요청인지 압니다. 이 실습은 첫 줄, Host 줄, 마지막 빈 줄을 하나씩 바꾸거나 지워 가며 같은 서버(/hello 주소만 만들어 둔 서버)에 글자를 그대로 보내, 서버가 그 글을 요청으로 읽는지, 어떤 응답을 돌려주는지, 우리가 쓴 서버 코드까지 가는지를 봅니다. 코드 칸의 (빈 줄)은 아무 글자도 없는 줄을 눈에 보이게 적은 것입니다.

실행으로 대조 · Node.js 24.18.0의 http 서버에 열두 가지 조합의 글자를 그대로 보내 대조

이 실습에 나오는 개념

요청 줄(request line)
요청 줄은 HTTP 요청의 맨 첫 줄로, 메서드, 요청 대상(보통 경로), HTTP 버전을 공백으로 나누어 차례로 적는다. 예를 들어 GET /hello HTTP/1.1은 /hello에 대해 GET(달라는 요청)을 HTTP/1.1 규칙으로 보낸다는 뜻이다. 서버는 이 줄로 무엇을 달라는 요청인지 알아낸다. 세 칸의 모양이 맞지 않으면 서버는 그 글을 요청으로 읽지 못하고, RFC 9112는 잘못된 요청 줄에 400 응답을 돌려주도록 권한다(3.2절).
Host 헤더
Host는 요청이 어느 사이트(호스트 이름과 포트)로 온 것인지를 알리는 헤더로, 값은 localhost:8080처럼 적는다. 한 서버가 여러 사이트를 맡을 수 있어서 서버가 어느 사이트의 요청인지 구분하는 데 쓴다. RFC 9112는 클라이언트가 모든 HTTP/1.1 요청에 Host 헤더를 보내야 하고, 서버는 Host가 없는 HTTP/1.1 요청에 400(Bad Request)으로 응답해야 한다고 정한다(3.2절). Node.js의 http 모듈도 Host가 없는 요청을 애플리케이션 코드에 넘기지 않고 400으로 답한다.
HTTP 요청의 끝(빈 줄)
HTTP 요청은 요청 줄, 헤더 줄들, 아무 글자도 없는 빈 줄 순서로 쓰며, 빈 줄이 헤더가 끝났다는 표시다(RFC 9112 2.1절). 줄바꿈은 CRLF(캐리지 리턴과 줄 바꿈 두 글자)로 적는다. 서버는 이 빈 줄이 와야 요청이 끝까지 왔다고 보고 처리를 시작하므로, 빈 줄이 오지 않으면 뒤에 글자가 더 오는 줄 알고 기다린다. 본문이 있는 요청에서는 빈 줄 다음부터가 본문이다.
HTTP 상태 코드
서버가 요청을 처리한 결과를 나타내는 세 자리 숫자다. 2xx는 성공, 3xx는 다른 위치로의 이동(리다이렉션), 4xx는 클라이언트의 요청에 문제가 있음, 5xx는 서버 쪽 오류를 뜻한다. 200(성공), 201(생성됨), 400(잘못된 요청), 401(인증 필요), 403(권한 없음), 404(없음), 500(서버 오류)이 자주 쓰인다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. 브라우저 주소창에 localhost:8080/hello 주소를 입력하면, 브라우저는 서버에 연결해 아래와 같은 글자를 보냅니다. 서버는 /hello 주소만 만들어 둔 서버입니다.
  2. 서버를 이루는 Node.js가 첫 줄을 읽습니다. 읽은 글은 "GET /hello HTTP/1.1"입니다. 첫 줄(요청 줄)에는 세 가지가 차례로 적힙니다. GET은 메서드로 무엇을 하려는지(달라는 요청), /hello는 경로로 무엇에 대해서인지, HTTP/1.1은 어떤 규칙으로 쓴 글인지입니다. 세 칸이 모두 있어 요청 줄로 읽힙니다.
  3. Node.js가 다음 줄을 읽습니다. 읽은 글은 "Host: localhost:8080"입니다. "이름: 값" 꼴의 줄을 헤더라고 합니다. Host 헤더는 이 요청이 어느 사이트(주소)로 온 것인지를 알려 줍니다.
  4. Node.js가 다음 줄을 읽었더니 아무 글자도 없는 빈 줄입니다(화면의 (빈 줄)). 빈 줄은 헤더가 끝났다는 표시여서, Node.js는 요청이 끝까지 왔다고 판단합니다.
  5. Node.js가 읽은 요청에서 메서드는 GET, 경로는 /hello입니다. 모양이 맞고 Host도 있어서, Node.js가 이 요청을 우리가 쓴 서버 코드에 넘깁니다.
  6. 우리가 쓴 서버 코드가 경로를 봅니다. /hello는 만들어 둔 주소라서, 200 응답과 본문 "안녕하세요"를 만듭니다. 이 코드는 화면에 보이지 않지만, 경로가 /hello인 GET 요청에만 이렇게 답하게 만들어 두었습니다.
  7. 브라우저가 200 응답을 받습니다. 본문은 "안녕하세요"입니다.

실행 결과

코드

GET /hello HTTP/1.1
Host: localhost:8080
(빈 줄)

이 모형의 전제

서버는 Node.js 24.18.0의 http 모듈로 만든 것 하나로, GET /hello에 200과 본문 "안녕하세요"를, 그 밖의 경로에는 404를 돌려줍니다. 열두 가지 조합을 모두 127.0.0.1의 이 서버에 net 모듈로 글자 그대로 보내(줄 끝은 CRLF), 받은 응답의 상태 줄과 본문, 우리가 쓴 요청 처리 함수가 불렸는지와 그 함수가 받은 method와 url을 확인해 모형과 대조했습니다. 화면의 (빈 줄)은 아무 글자도 없는 줄을 눈에 보이게 적은 것이고, 빈 줄이 없는 조합은 마지막 줄의 줄바꿈까지만 보냈습니다. "응답 없음 (기다림)"은 글자를 보낸 뒤 1.5초 동안 응답이 한 바이트도 오지 않았다는 뜻입니다. Node.js가 언제까지 기다리다 포기하는지는 보지 않았습니다. 모양이 틀린 첫 줄(/hello)은 Node.js가 요청으로 읽지 못해 clientError 오류(HPE_INVALID_METHOD)를 내고 스스로 400을 돌려주며, 이때 뒤의 줄이 어떻든 첫 줄만 보냈을 때도 400이 왔습니다. Host가 없는 요청은 빈 줄이 와서 헤더가 끝난 뒤에, Node.js가 우리 코드를 부르기 전에 스스로 400을 돌려주고(요청 처리 함수는 불리지 않았고 clientError도 나지 않았습니다), Host 검사를 끈 서버(requireHostHeader: false)에 같은 글자를 보내면 처리 함수가 GET 요청을 받았으므로 요청 줄까지는 정상으로 읽힌 것입니다. 이것들은 이 Node.js 버전에서 관찰한 동작입니다. 문서로 확인한 것은 RFC 9112의 2.1절(메시지 형식: 요청 줄과 헤더 뒤의 빈 줄), 3절(요청 줄: 메서드, 요청 대상, 버전 세 칸), 3.2절(HTTP/1.1 요청에 Host가 없으면 서버는 400으로 응답해야 한다)과 RFC 9110의 7.2절(Host), 15.5.1절(400), 15.5.5절(404)입니다. 화면의 요청은 헤더를 Host 하나만 남긴 최소한의 모양이고, 본문이 없는 GET 요청만 다뤘습니다. 400을 돌려주는 방식은 서버마다 다를 수 있으며, 이 화면은 Node.js 서버의 동작입니다. 서버의 코드는 화면에 보이지 않습니다. 같은 주제의 세부 동작(응답의 모양, 상태 코드 전체)은 "세부 동작 실습: HTTP 메시지와 상태 코드"에서 다룹니다.

앞 실습: DNS · 다음 실습: HTTP 메서드

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요