[웹을 지탱하는 기술] HTTP(1)

ekil·2022년 11월 13일
0

개발도서

목록 보기
2/4
post-thumbnail

📘 책을 읽으며 알게 된 지식을 정리하고 있습니다. 현재 읽고 있는 책은 야마모토 요헤이, <웹을 지탱하는 기술> (멘토르, 2011)입니다.

📍 저작권 상 문제가 있다면 글 삭제하도록 하겠습니다. 문제가 있으면 알려주세요.

📍 간략히 정리한 것이라 실제 책을 읽어보시면 많은 도움이 될 것이라 확신합니다. 자세히 알고 싶은 내용이셨다면 책을 살펴보시는 것을 추천합니다!

📌 오늘 다룰 것은 3부 HTTP(chapter 6 ~ 7, pp.111~170)에 해당하는 내용입니다.

HTTP

1. 정의

📌 HTTP = HyperText Transfer Protocol

📍 컴퓨터에서 다루는 모든 데이터를 전송하기 위한 프로토콜

✔️ 모든 데이터 ex) HTML 등의 하이퍼텍스트, 이미지, 영상, PDF 파일, JS 프로그램 등

✔️ TCP(Transmission Control Protocol)로 특정 애플리케이션으로 데이터를 전송할 커넥션을 연결하는데, 어떤 애플리케이션으로 전송할지는 포트번호로 결정. HTTP의 포트번호80번.

2. 요청과 응답

📌 HTTP = 요청/응답형 프로토콜 (Request-Response Style Protocol), 동기형 프로토콜 (Synchronous Protocol)

-> 클라이언트가 보낸 요청을 서버에서 처리하고 응답 돌려줌, 서버에서 처리 시간 오래 걸려 응답이 늦게 돌아오더라도 클라이언트는 계속 대기함

📍 구체적인 과정

(클라이언트) DNS 이용해 URI의 호스트명 해석 -> IP 주소 얻음 -> 그 IP 주소의 TCP 80번 포트에 접속 -> HTTP 요청 전송 -> (서버) 요청 해석, 응답 전송

HTTP 메시지 - 요청 메시지 & 응답 메시지

📍 구조: 스타트 라인, 헤더, 바디 (헤더, 바디 사이엔 빈 줄이 있음)

1. 스타트 라인: 메시지의 첫 줄

  1. 요청 메시지(클라이언트 -> 서버)의 스타트 라인 = 요청 라인

    ✔️ 구성: 사용할 메서드, 요청 URI, 프로토콜 버전

    ex. GET /test HTTP/1.1

    메서드 = GET

    요청 URI = /test (경로만 쓰는 상대 URI)

    프로토콜 버전 = HTTP 1.1

    ✔️ 요청 URI는 상대 URI, 절대 URI 둘 다 가능 (프록시 요청은 절대 URI만 가능)

  2. 응답 메시지(서버 -> 클라이언트)의 스타트 라인 = Status Line

    ✔️ 구성: 프로토콜 버전, 상태 코드 (status code), 텍스트 구문

    ex. HTTP/1.1 200 OK

2. 헤더: 메시지의 두 번째 줄부터

✔️ 메시지의 메타 데이터

✔️ 이름:값 형식을 취함

✔️ 헤더 여러 개 가능, 줄 바꿈으로 서로 구분, 빈 줄을 둠으로써 헤더 종료를 표시

✔️ 생략 가능

  1. 요청 메시지의 헤더

    ex. Host: example.com

    -> 요청 URI의 호스트명을 명시하는 헤더

    (요청 라인에서 절대 URI 사용 시 Host 헤더 생략 가능)

  2. 응답 메시지의 헤더

    Content-Length (바디 길이 나타냄), Transfer-Encoding (청크 전송 나타냄), Content-Type (HTML의 MIME 미디어 타입, 문자 인코딩 방식 나타냄) 등

3. 바디: 헤더 뒤에 이어짐

✔️ 실제 데이터를 전달해야 할 때, 바디에 담음

✔️ 생략 가능

  1. 요청 메시지의 바디

    리소스 새로 작성 또는 갱신할 때, 바디에 그 내용을 담음

  2. 응답 메시지의 바디

    GET 요청이었다면 리소스의 표현(HTML 문서 등), PUT/POST라면 처리 결과(어떤 리소스가 추가/생성됐는지 알 수 있게)가 들어갈 수 있음

3. HTTP, stateless로 간결함을 챙기다

stateful <-> stateless

  • stateful = 햄버거 세트 주문 시 점원이 앞의 주문을 기억, 더 추가할 사항만 얘기하면 됨 (ex. 음료는 콜라로 할게요)

  • stateless = 점원이 앞의 주문 기억 X, 추가할 사항 있으면 이미 얘기한 뒤여도, 앞의 내용을 함께 얘기해야 함 (ex. 햄버거 세트 하나 주문할 건데, 음료는 콜라로 주세요) -> 손님이 매번 모든 주문을 반복해 얘기해야 함

  • stateless 방식에서 클라이언트는, 자기 기술적 메시지(요청 처리에 필요한 정보를 모두 포함한 메시지)를 보냄

  • 이렇게만 보면 stateful이 간결하나, 더 많은 클라이언트를 상대하기 위해 서버를 늘릴 경우 서버 시스템을 보면 stateless가 오히려 간결

  • 수많은 서버에서 모든 클라이언트의 정보(=애플리케이션 상태)를 기억, 동기화하기 어렵기 때문

✔️ 물론 stateless 방식에도 결점이 존재함! (pp.135~136, 퍼포먼스 저하, 통신 에러에 대한 대처)

📌 HTTP = stateless 프로토콜로 설계됨

-> 서버가 클라이언트의 애플리케이션 상태를 보존하지 않음

HTTP 메서드

📌 GET, POST, PUT, DELETE, HEAD, OPTIONS, TRACE, CONNECT + PATCH

📍 CRUD와 HTTP 메서드

  • C = Create = POST/PUT

  • R = Read = GET

  • U = Update = PUT

  • D = Delete = DELETE

✔️ PATCH = 리소스 일부분만 수정

POST

  1. 주로, 어떤 리소스의 서브 리소스를 작성(추가, 생성)할 때 사용

    ✔️ 현재 경로가 /list일 때, POST로 '안녕하세요'라는 서브 리소스 추가를 요청하면, /list 아래에 /list/item1 등의 경로로 새 서브 리소스를 생성해 줌

    ✔️ 추가할 내용은 요청 메시지의 바디에 담아 전달

    📍 정상적으로 서브 리소스 추가됐다면, 201 Created 상태 코드가 돌아옴

  2. 리소스에 데이터 추가할 때도 사용

    ✔️ 추가할 내용은 요청 메시지의 바디에 담아 전달

    📍 신규 리소스 생성이 아니어서, 정상적으로 데이터 추가가 됐다면 200 OK 상태 코드가 돌아옴

  3. 현존하는 메서드로 대응/실현할 수 없는 처리를 실행할 때도 사용

    ex. GET 요청 시 URI가 너무 길다면, POST 이용해 바디에 URI를 담을 수 있음

    (사용자가 검색한 키워드가 너무 길어 URI가 길어졌을 때 등)

📍 POST 메서드가 정확히 어떤 작업을 하는지는 서버의 구현에 달려있으니, 서버에서 작성해 준 API 명세서를 참고하는 것이 가장 정확!

PUT

  • 리소스를 갱신(내용을 바꿈) (정상적으로 처리됐다면 200 OK 상태 코드 또는 204 No Content 돌아옴)

    ✔️ 204 No Content = 바디에 아무것도 넣지 않을 때!

  • 아직 존재하지 않는 URI에 PUT 요청 보낼 경우, 새 리소스를 작성 (정상적으로 처리됐다면 201 Created 상태 코드 돌아옴)

POST vs PUT

  • 둘 다 리소스를 추가(생성)할 수 있음

  • POST: 새로 생성할 리소스의 URI 결정권이 서버에 있음 (클라이언트가 정할 수 음)

  • PUT: 새로 생성할 리소스의 URI 결정권이 클라이언트에 있음 (클라이언트에서 정해서 요청 보냄)

✔️ 서버에서 URI 결정하는 서비스 -> POST가 적절

✔️ 클라이언트가 URI 결정하는 서비스 -> PUT이 적절 (다만, 중복 방지를 위한 방법 마련해두어야 함)

📍 클라이언트에서 서버 내부 구현까지 잘 숙지하고 있는 경우가 아니라면 일반적으로는 POST 사용하는 설계가 바람직함

HTML과 GET, POST

✔️ <form> 태그 배울 때, action 속성의 값으로 'GET', 'POST' 둘 사용 가능하다고 배웠었음

📍 HTML 폼에서 지정할 수 있는 메서드는 GET, POST 둘뿐이다!

✔️ Ajax의 XMLHttpRequest 모듈 이용하면 다른 메서드도 발행 가능

✔️ Axios는 브라우저를 위해 XMLHttpRequest를 생성해준다(공식문서 참고). 그래서 다른 메서드를 사용하는 요청도 쉽게 가능한 것이었구나.

멱등성, 안전성

📌 멱등성(Idempotence)

  • 어떤 조작을 몇 번을 반복해도 결과가 동일함 (수학 용어)

  • ex. 어떤 수에 0을 곱하는 것은 몇 번을 반복해도 결과가 0으로 동일 -> 0의 곱셈은 멱등이다.

📌 안전성

  • 조작 대상인 리소스에 부작용(=Side Effect, 리소스 상태에 변화가 생기는 것)이 없음

-> 어떤 조작을 여러 번 실행해도 리소스의 상태가 변하지 않

📍 GET, HEAD: 멱등성 O, 안전성 O

📍 PUT, DELETE: 멱등성 O, 안전성 X

📍 POST: 멱등성 X, 안전성 X

(✔️ HEAD = 리소스의 헤더만 GET하는 메서드)

(OPTIONS는 리소스가 허용하는 메서드 목록을 반환하는 메서드인데, GET, HEAD와 같은 성격일 것 같다. 책의 표에는 위 다섯 가지 메서드만 나와있긴 하다.)

✔️ GET: 몇 번을 반복해도, 리소스를 수정하지 않고, 같은 결과를 반환하므로

✔️ PUT: 리소스를 갱신하므로 리소스 상태에 변화 발생하지만, 계속 그것으로 갱신하므로 결과는 동일함 (ex. 리소스를 'test2'로 갱신하는 요청을 세 번 보내도, 리소스는 'test2'로 갱신됐다는 동일한 결과 반환)

✔️ DELETE: 리소스를 삭제(=리소스 상태 변화 발생 O). 한 번 보냈을 때 삭제하고 두 번째 보내면 리소스가 존재하지 않으므로 404 Not Found 상태 코드를 반환하지만, 리소스가 삭제되어 있다는 결과는 동일하다고 보고 멱등성이 있다고 봄

=> GET, PUT, DELETE는 클라이언트에서 몇 번 중복해 요청해도 큰 문제 발생 X!

✔️ POST: 대표 기능인 서브 리소스 생성을 생각해보자. 새로운 URI를 생성하고 리소스도 생성한다. 새로운 URI의 결정권은 서버가 갖는다고 했다. -> POST 요청할 때마다 서로 다른 새로운 URI의 새 리소스를 생성한다!

  • 새것을 생성하는 것은 리소스 상태가 변하는 것이므로 안전성 X

  • 요청할 때마다 서로 다른 새 URI의 리소스가 생성되는 것이므로 늘 결과가 다름 -> 멱등성 X

(POST가 왜 PUT과 달리 멱등성이 없는지 이해하기 위해 참고한 블로그 글: HTTP 메소드의 멱등성? 그게 뭔데?)

📍 기본 사항은 위와 같음. 이를 잘 지키며 API를 설계해야 함. (GET의 안전성을 파괴하는 식으로 설계하지 말 것.)

📍 추가로 참고하면 머릿속 개념들이 더 명확해질 글: HTTP 메서드에 관해 아는 대로 설명해주세요 (블로그 글)

profile
좋아하는 일을 잘함으로써 먹고살고 싶은 프론트엔드 개발자입니다.

0개의 댓글