카테고리 없음

리얼월드 HTTP 메모

Below_zero 2026. 1. 15. 04:40

HTTP

웹 브라우저와 웹 서버가 통신하는 절차와 형식의 규정

 

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")
}

func main() {
	var httpServer http.Server
	http.HandleFunc("/", handler)

	log.Println("start http listening : 18888")
	httpServer.Addr = ":18888"
	log.Println(httpServer.ListenAndServe())

}

 

Go로 간단하게 작성된 HTTP 요청의 전체 내용을 서버 콘솔에 출력(Dump)하는 코드이다.

 

클라이언트 단에서 우리가 사버로 보낸 curl 명령어가 실제 HTTP 메시지 규격으로 변환되는 것을 직접 확인할 수 있다.

 

저 코드로 서버를 실행시킨 상태에서 http://localhost:18888로 들어가보면 간단한 hello가 출력된 웹페이지가 나온다.

 

책에서는 웹 브라우저로 접근하지 않고, curl을 통해 접근하며 실험한다.

 

 

이런 로그가 찍혀있다. 이건 웹페이지를 이용해 접속했을 때 서버측에 전달되는 http 메세지라고 보면 된다.

 

 

책에선 curl을 사용해 강제로 http 1.0을 사용하고 있다.

curl로 http1.0을 사용해 접근시 서버에 이런 로그가 찍힌다.

 

curl 커맨드에 -v 옵션을 주면 더 자세한 정보를 클라이언트 측에서 확인할 수 있었다.

 

설명하고 있는 내용은, http의 버전이 거듭되며 초기 0.9는 하나의 문서를 전송하는 기능밖에 없었지만, 

1.0 부터는

- 요청시 메서드가 추가됐고 (GET)

- 요청시 HTTP 버전이 추가됐다고 한다. (HTTP/1.0)

- 헤더또한 추가됐다(Host, User-Agent, Acceppt)

 

 

 

HTTP의 헤더는 요청과 응답 양쪽에서 사용된다.

 

우선 클라이언트 -> 서버 : User-Agent, Referer, Autorization

 

서버 -> 클라이언트 : Content-Type, Content-Length, Content-Encoding, Date

 

curl 커맨드에 옵션을 추가해 직접 사용자가 서버측으로 커스텀 헤더를 붙여서 헤더를 전달할 수 있다.

curl -H "X-Test: Hello" http://localhost:18888

이런식으로 직접 부여한 헤더가 서버에 전달된다.

 

curl에 -v 옵션을 줄 경우 클라이언트 측에서 서버의 응답 헤더도 확인할 수 있다.

 

 

MIME 타입

파일의 종류를 구분하는 문자열이다.

 

현재 웹 서버에서 HTML을 보낼 경우 서버의 응답헤더에 다음과 같은 MIME를 설정해둔다.

Content-Type: text/html; charset=utf-8

 

브라우저에서는 파일 종류를 특정할 때 Content-Type 헤더에서 지정된 MiME 타입을 사용한다.

 

 

메서드

HTTP/1.0으로 통신할 때 전송되는 GET 부분은 메서드라 불린다.

지정된 주소에 있는 리소스에 대한 조작을 서버에 지시한다. GET, HEAD, POST 등등이 있는데 HTTP 버전마다 추가되고 삭제되는 메서드가 있다.

 

스테이터스 코드

HTTP/1.0 200 << 200이 스테이터스 코드다.

세자리 숫자를 보고 서버가 어떻게 응답했는지 알 수 있다.

100번대 : 처리가 계속됨

200번대 : 성공, (자주 사용되는 200 OK : 정상 종료)

300번대 : 서버에서 클라이언트로의 명령

400번대 : 클라이언트의 요청에 오류

500번대 : 서버 내부 오류

 

리디렉트

300번대 스테이터스의 일부는 서버가 브라우저에 대해 리디렉트하도록 지시하는 스테이터스 코드다.

301 Moved Permanently : 영구적 도메인 전송, 웹사이트 이전, HTTPS

302 Found : 일시적 관리

303 See Other : 로그인 후 페이지 전환

307 Temporary

308 Moved Permanently

 

 

URL (Uniform Resource Locator)

URL은 HTTP/1.0보다 빠른 시기에 만들어졌고, 웹 시스템을 다루는한 URL과 URI(Uniform Resource Identifier)

는 같다고 한다.

 

일반적으로 자주 보는 URL은 다음과 같은 형식이다.

https://www.naver.com/index.shtml

 

스키마://사용자:패스워드@호스트명:포트/경로#프래그먼트?쿼리

  • 스키마: https
  • 호스트명: www.naver.com
  • 경로: index.shtml

스키마의 해석은 브라우저의 책임이다. 실제로 통신하는 곳은 호스트명으로 지정된 서버이고, 포트는 아파트 현관 우편함이다.

호스트명으로 찾아온 IP주소마다 65,535개의 포트가 있기 때문에 같은 주소라도 포트가 다르면 독립적으로 복수 서버를 운용해 서비스를 제공할 수 있다.

 

포트가 생략되면 스키마별 기본 포트를 사용한다. HTTP: 80, HTTPS: 443

 

다음과 같은 URL이 있다고 하자,

http://www.oreilly.co.jp/books/9784873114958/

 

アート・オブ・コミュニティ

コミュニティは、地域の貢献活動やオープンソースソフトウェア開発はもちろん、製品リリースのマーケティングなどを行う際にも大きな役割を果たします。ものやサービスへの愛情に起因

www.oreilly.co.jp

 

사람이 읽어도 의미를 유추할 수 있다. 오레일리라는 일본 사이트에 서적관련페이지, 숫자는 ISBN일 것이라고 말이다.

 

기호적인 URL보단 이렇게 사람이 읽을 수 있는 URL이 사용자에게 조금이라도 더 많은 정보를 사전에 전달할 수 있다.

 

구글의 검색 엔진도 URL에 단어가 포함된 경우 단어가 검색 순위에 조금 플러스된다고도 한다.

 

 

쿠키

웹사이트의 정보를 브라우저 쪽에 저장하는 작은 파일.

HTTP 헤더 기반으로 구현할 수 있다.

 

서버에서 클라이언트로 다음과 같이 응답헤더를 보낸다.

Set-Cookie: LAST_ACCESS_DATE=Jul/31/2016
Cookie: LAST_ACCESS_TIME=12:04

 

서버는 클라이언트에게 최종 액세스 시간과 날짜를 이런 식으로 날린다.

클라이언트는 이 값을 저장해두고, 다음번에 재방문을 할때 서버에 다음과 같은 형식으로 요청을 보낸다.

Cookie: LAST_ACCESS_DATE=Jul/31/2016
Cookie: LAST_ACCESS_TIME=12:04

 

if _, ok := r.Header["Cookie"]; ok{
	// 쿠키 보유, 재방문자
	}
else{
	// 첫 방문자
}

 

코드를 좀 많이 생략했는데 서버측에선 이런식으로 쿠키를 처리할 것이다.