한빛미디어 - 리얼월드 HTTP 를 보고 작성한 글입니다.
HTTP를 데이터 상자로 본다면 통신 내용을 몇 가지로 나눌수있습니다.
- 메서드와 경로
- 헤더
- 바디
- 스테이터스 코드
1.1 HTTP의 역사
HTTP는 웹브라우저와 웹 서버가 통신하는 절차와 형식을 규정한 것
그동안 다양한 버전업이 이루어졌다고합니다.
1990년 : HTTP/0.9
1996년 : HTTP/1.0
1997년 : HTTP/1.1
2005년 : HTTP/2
초기 버전인 HTTP/0.9는 HTML 도큐먼트를 요청해서 가져오는 단순한 프로토콜 이었습니다.
RFC(Request for Comments) 는 인터넷이나 네트워크, 프로토콜, 기술 표준 등을 정의하거나 제안할 때 공개되는 문서 형식
-> 인터넷 연결, 메일 등의 동작도 모두 RFC로 정해진 규칙을 따라 만들어졌기 때문입니다.
| 구분 | IETF | IANA |
| 성격 | 기술 표준화 기구 (커뮤니티) | 번호·리소스 관리 기관 |
| 핵심 역할 | 인터넷 프로토콜 설계·표준화 | 표준에 따른 번호·이름·주소 관리 |
| 산출물 | RFC (예: TCP/IP, HTTP, TLS) | Port 번호, 프로토콜 번호, DNS 루트, IP 블록 할당 |
| 소속 | 독립적 (ISOC 산하) | ICANN 산하 |
브라우저에 특화된 기능은 W3C로 이관되었습니다.
1.1.1 테스트 에코 서버
main.go
package main
import (
"fmt"
"log"
"net/http"
"net/http/httputil"
)
func handler(w http.ResponseWriter, r *http.Request) {
dump, err := httputil.DumpRequest(r, true)
if err != nil {
http.Error(w, fmt.Sprint(err), http.StatusInternalServerError)
return
}
fmt.Println(string(dump))
fmt.Fprintf(w, "<html><body>hello</body></html>\n")
}
const addr = ":18888"
func main() {
http.HandleFunc("/", handler)
httpServer := http.Server{Addr: addr}
log.Printf("Start http listening at %s\n", addr)
log.Println(httpServer.ListenAndServe())
}
- 포트 18888에서 HTTP 서버 실행
- 클라이언트가 요청 보내면, 요청 내용을 서버 콘솔에 출력
- 클라이언트에게는 “hello”라는 간단한 HTML 응답 반환
go.mod
module http-server
go 1.21
출력결과
go run main.go

1.2 HTTP/0.9
HTTP/0.9는 단순한 프로토콜입니다.
텍스트 정보가 적힌 페이지 경로를 서버에 지정해서 해당 페이지를 가져오기만 하는 프로토콜입니다.
현재 0.9를 다룰 수 없으므로 1.0을 사용하여 테스트 합니다.
이전에 생성한 18888 포트에 curl 요청을 전달합니다.

서버로그를 확인합니다.

0.9 기능은 웹사이트의 페이지를 서버에 요청하고 그 응답으로 웹사이트 내용을 받아옵니다. (Hyper Text Transfer Protocol)
수신 후에는 서버와 연결이 끊어집니다.
요청에는 호스트이름(localhost) 또는 IP주소와 포트 번호를 지정합니다.
curl 커맨드는 호스트명과 경로가 함께 있는 URI를 사용하지만
curl http://localhost:18888/greeting
서버가 받아들이는 것은 /greeting 경로 부분 뿐입니다
-> 호스트명(localhost:18888)은 TCP 연결을 맺는 데 쓰였을 뿐, 애플리케이션 레벨 서버 코드에는 경로만 전달됩니다.
폼과 검색기능
예전 <isindex> 태그를 사용하면 텍스트 입력란이 생겨 검색이 가능했습니다.
아래와 같이 ?기호와 단어(+로 구분)을 붙여 검색요청을 보냅니다.
http://example.com/?search+word
<isindex> 태그는 없지만 URL에 검색 키워드를 부여해 요청하는 방식은 지금과 동일합니다.
아래와 같이 요청하면 됩니다.
curl --http1.0 --get --data-urlencode "search world" http://localhost:18888
생성한 서버로그에서 GET 요청 확인가능합니다.
GET /?search+world HTTP/1.0
Host: localhost:18888
Accept: */*
User-Agent: curl/8.5.0
1.3 HTTP/0.9에서 1.0으로의 여정
이전 실습명령어에서 -v 옵션을 추가해봅니다.
curl -v --http1.0 -X POST http://localhost:18888/greeting
* Host localhost:18888 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:18888...
* Connected to localhost (::1) port 18888
> POST /greeting HTTP/1.0
> Host: localhost:18888
> User-Agent: curl/8.5.0
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Date: Sat, 06 Sep 2025 06:19:22 GMT
< Content-Length: 32
< Content-Type: text/html; charset=utf-8
<
<html><body>hello</body></html>
* Closing connection
> 로 시작하는 행이 클라이언트에서 서버로 전송할 내용입니다
1.0 에서 변경사항은 아래와 같습니다.
- 요청시 메서드 추가 (GET)
- 요청시 HTTP 버전이 추가 (HTTP/1.0)
- 헤더가 추가 (Host, User-Agent, Accept)
응답코드도 확인해봅니다.
< 로 시작하는 행이 서버에서 응답으로 돌아온 내용입니다.
< HTTP/1.0 200 OK
< Date: Sat, 06 Sep 2025 06:19:22 GMT
< Content-Length: 32
< Content-Type: text/html; charset=utf-8
<
<html><body>hello</body></html>
0.9 -> 1.0 에서 변경된 점은 아래와 같습니다.
- 응답 선두에 HTTP 버전과 스테이터스 코드가 포함
- 요청과 같은 형식의 헤더가 포함
ps.
얇다고 생각했는데.. 정리할게 많네요