HTTP

본 글은 SW마에스트로에서 진행된 멘토링을 통해 학습의 계기를 얻어 작성한 게시글입니다.


사전 지식

웹(Web)이란

  웹이란 무엇일까? 우선 World Wide Web에 대해 알아보자. 팀 버너스리라는 사람이 처음 개념을 만들고 직접 구현했다고 하는 World Wide Web은 ‘인터넷에 연결된 사용자들이 서로의 정보를 공유할 수 있는 공간’을 의미한다. 이를 간단히 줄여서 우리가 아는 웹 페이지 주소의 앞에 붙는 WWW라고 부르며, 이를 보편적으로 우리는 웹(Web)이라고 부른다.

웹(Web)과 인터넷(Internet)의 차이

  인터넷과 웹은 같은 의미로 혼용되기도 하지만, 정의는 다르기 때문에 필자는 앞으로 구분하기 위해 노력하려고 한다. 인터넷은 컴퓨터가 서로 연결되어 통신을 주고 받는 컴퓨터끼리의 네트워크를 의미하고 컴퓨터의 네트워크, 광섬유 케이블, 무선 네트워크 등으로 구성된 하드웨어 시스템이다. 하지만 웹은 인터넷 상에서 정보가 얽혀있는 무형의 정보 네트워크를 의미하고 다양한 장치에 저장된 파일, 폴더 및 문서로 구성된 소프트웨어이다. 인터넷에서는 웹 뿐만 아니라 전자 메일과 같은 다양한 서비스가 동작하는데, 웹은 이러한 서비스 중 하나일 뿐이다.

Web의 동작 3요소

  • HTTP : 주고 받는 방식
  • HTML : 내용을 표현하는 방식
  • URL : 고유한 리소스를 표시하는 주소 방식

Web Client와 Server

image

  • 클라이언트 : 서버에서 URL로 고유한 컨텐츠(리소스)를 요청
  • 서버 : 클라이언트의 요청에 따라 적당한 문서(리소스)를 응답으로 제공
  • 프록시 : 클라이언트와 서버 사이에 존재, 캐싱, 필터링, 로드 밸런싱, 인증, 로깅 등의 다양한 기능 수행

HTTP

정의

  • WWW 상에서 클라이언트와 서버가 정보를 요청하고 받을 수 있는 프로토콜
  • HTML을 주고 받기 위한 표준
  • 주로 TCP와 UDP 방식으로 서버 80번 포트에 요청을 보냄

동작 방식

image

  1. 최초에 HTML을 요청해서 받아옴
  2. HTML에서 CSS, js, 이미지에 대한 링크 정보를 추출
  3. 추출한 정보의 URL을 이용해서 새로운 요청을 보냄
  4. 모든(또는 일부분) 웹 자원을 받아와 렌더링 시작 (참고: HTTP1.1은 파이프라인으로 동작하였으나, 2.0은 병렬처리를 통해 성능을 개선하였음)
  5. 이 과정에서 실제로는 특정 서버의 주소를 확인하기 위해서 DNS 서버가 개입함

특징

  • 비교적 간단하며 확장이 가능함
  • 상태가 없음 (stateless)
  • HTTP1 -> HTTP/1.1 -> HTTP/2 순서로 버전이 번경되었으며, 현재까지도 계속 발전하고 있는 중

HTTP Request & HTTP Response

HTTP Request 구조

image

  • 클라이언트가 특정 데이터를 받아올 수 있게끔 보내는 메시지
  • Request line과 Headers, Body로 구성됨
  • 실제로는 한 줄 마다 \r\n라는 줄바꿈 문자가 포함되어 있음
  • Header와 Body를 빈 줄로 구분하기 위해서도 \r\n 문자를 포함함

HTTP Response 구조

image

  • 요청에 따른 서버의 답변
  • Status Line과 Headers, Body로 구성됨
  • Status Line
    • 프로토콜(HTTP/1.1) : 사용되는 프로토콜과 버전
    • 상태코드 : 요청에 대한 응답 상태
    • 상태메시지 : 상태코드와 함께 전달되는 메시지
  • Request와 마찬가지로 한 줄 마다 \r\n라는 줄바꿈 문자가 포함되어 있음

HTTP Request Method

image

  REST API에서는 GET, POST, PUT, DELETE가 많이 사용된다. 이 글에서는 추가적으로 PATCH까지 다뤄보도록 하겠다. 그 전에 간단히 ‘멱등성’이라는 성질에 대해 알아보자.

멱등성

  멱등성이란 연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질을 의미한다. 이 멱등성이라는 성질을 HTTP Method에 적용하면 동일한 요청을 한 번 보내는 것과 여러번 연속으로 보내는 것이 같은 효과를 가지고, 서버의 상태도 동일하게 남을 때, HTTP Method가 멱등성을 가진다고 한다. 여기서 결과는 응답 상태코드가 아닌 서버의 상태이다.
  HTTP 스펙에 명시된 것에 의하면 GET, PUT, DELETE는 멱등성을 가져야 하지만, POST와 PATCH는 멱등성을 가지지 않도록 구현해야 한다고 한다. 그 이유는 아래 메서드를 살펴보며 같이 명시하였다.

GET

  • 특정 리소스를 가져오도록 요청하는 메서드
  • 데이터를 가져올 때만 사용
  • CRUD 개념으로 생각하면 Read에 속함
  • URL 뒤에 데이터를 붙여보냄 (www.example.com/upper)

  GET 메서드가 멱등성을 가져야하는 이유는 어렵지 않다. GET 메서드는 특정 리소스를 가져오도록 요청하는 메서드이고, 이는 데이터를 조회하는 메서드라는 의미이다. 데이터를 조회하는 메서드가 서버의 상태를 변경할 이유가 없지 않은가? 그렇기 때문에 GET 메서드로 요청을 하더라도 서버의 상태는 동일하게 유지되고, 멱등성을 가지도록 구현해야 한다.

  여기서 만약 게시글을 조회하고, 조회수를 1 증가시키는 기능을 구현한다면 어떻게 될까? 이렇게 된다면 요청을 보낼때마다 서버의 상태는 변경되고, 멱등성을 가지지 않게 된다. 그렇기 때문에 HTTP 스펙에 부합하지 않은 구현이라고 할 수 있다. 만약 이러한 기능이 필요하다면, 조회수 컬럼의 값을 증가시키는 요청을 따로 분리하는 것이 스펙 상 바람직하다.

POST

  • 서버로 리소스를 제출하는 메서드
  • 서버 상태의 변화를 일으킴
  • 주로 새로운 리소스를 생성(Create)할 때 사용
  • URL에 붙여 쓰는 방식이 아닌 Body에 리소스를 넣어서 보냄

  POST 메서드는 서버로 리소스를 제출하여, 새로운 리소스를 생성할 때 사용되는 메서드이다. 같은 요청을 여러 번 보내면 매번 새로운 자원이 생겨날 것이고, 이는 서버의 상태가 변경되는 것을 의미한다. 그렇기 때문에 POST 메서드는 멱등성을 가지지 않는다.

PUT

  • POST와 유사하지만 연속적인 요청 시에도 동일한 결과를 가져옴
  • 기존 데이터를 교체하는 용도로 쓰임(Update)

  POST 메서드와 PUT 메서드의 차이는 멱등성의 유무이다. POST는 매번 새로운 자원을 만들지만 PUT은 해당 자원이 있다면 덮어쓰기만 한다. 즉, 요청 횟수와 관계 없이 결국 서버의 상태는 동일하다. 그래서 PUT은 멱등성을 가지는 메서드이다.

  여기서 주의할 점은 멱등성은 가지고 있더라도 상태코드는 달라질 수 있다.

  • 새로운 데이터를 생성한 경우 201(Create) 상태코드를 응답한다.
  • 기존 데이터를 덮어 쓴 경우 200(OK) 혹은 204(No Content) 상태코드를 응답한다.

만약, PUT으로 요청한 리소스가 없을 경우 새로운 리소스를 만들고, 이 경우 201 상태코드를 응답하지만, 이후 동일한 요청을 하면 이미 리소스개 존재하므로 200 혹은 204 상태코드를 응답할 것이다.

PATCH

  • 리소스의 부분적인 수정(update)를 할때 사용

  필자는 PATCH와 PUT 메서드의 차이를 이해하는 것이 정말 어려웠다. 그렇기 때문에 아래에 동작방식에 대해서 보다 더 자세하기 다루기로 하겠다. 우선 멱등성에 관해서만 살펴보자.
  PATCH 메서드는 기본적으로 멱등성을 가지지 않지만, PUT 메서드와 동일한 방식으로 구현할 경우 멱등성을 가지게 할 수 있다고 한다.

PATCH /users/1
{
  age: {
    type: $inc,
    value: 1
  }
}

변경된 리소스
{
  id: 1,
  name: "김철수",
  age: 16
}

  위의 예시와 같은 내용으로 동일한 요청을 여러번 보내게 되면, 매 요청마다 age가 1씩 증가할 것이고, 이는 멱등성을 가지지 않게 된다.

PATCH /users/1
{
  age: 20
}

변경된 리소스
{
  id: 1,
  name: "김철수",
  age: 20
}

  하지만 위와 같은 내용으로 동일한 요청을 여러번 보내게 되면, 요청을 여러번 보내더라도 같은 결과가 나올 것이다. 즉 멱등성을 가지게 할 수도 있다는 의미이다.

DELETE

  • 지정한 리소스를 삭제(delete) 요청할 때 사용

  DELETE 메서드가 멱등성을 가지는 이유도 GET 메서드와 마찬가지로 어렵지 않다. DELETE 메서드는 지정한 리소스를 삭제하는 메서드이기 때문에, 처음 요청이 오면 서버의 해당 리소스는 삭제될 것이고, 이후 DELETE 메서드 요청이 여러번 오더라도 해당 리소스는 삭제된 상태이기 때문에 서버의 상태는 변하지 않는다. 즉, 멱등성을 가진다고 할 수 있는 것이다.

GET vs POST

  GET 메서드와 POST 메서드가 헷갈리는 사람들이 있을 것이다. 나 역시도 웹 개발을 처음 공부할 때는 헷갈렸다. 간단히 정리하자면 GET 메서드는 URL 뒤에 쿼리스트링으로 필요한 인자를 전달하여, 필요한 데이터나 웹 페이지를 받아오는데 사용된다. POST 메서드는 Body에 값을 붙여서 보내며, 종종 서버의 상태 변화를 일으킨다.

PUT vs PATCH

  PUT 메서드와 PATCH 메서드의 공통점은 두 메서드 모두 리소스를 업데이트한다는 의미를 가진다는 것이다. 얼핏봤을 때는 두 메서드가 같은 역할을 하는 것처럼 볼 수 있겠으나 내부동작에서는 약간 차이가 있다. 우선 PUT 메서드는 리소스의 모든 것을 업데이트하고, PATCH 메서드는 리소스의 일부를 업데이트한다. 아래에서 자세히 살펴보자.

  우선 아래와 같은 회원이라는 리소스가 있다.

회원(member)1
이름 (name)홍길동
나이 (age)22
성별 (gender)M

  PUT 메서드를 통한 요청을 보내보자.

PUT /members/1
{
    name : "김철수",
    age : 18,
    gender : "M"

}
회원(member)1
이름 (name)김철수
나이 (age)18
성별 (gender)M

  회원 리소스는 위와 같이 변하게 된다.

  이번에는 이름에 대해서만 요청을 보내보자.

PUT /members/1
{
    name : "박정순"
}
회원(member)1
이름 (name)박정순
나이 (age) 
성별 (gender) 

  보내지 않은 값에 대해서는 null 값으로 변하게 된다.


  다시 아래와 같은 회원이라는 리소스가 있다.

회원(member)1
이름 (name)홍길동
나이 (age)22
성별 (gender)M

  이번에는 이름에 대해서 PATCH 요청을 보내보자.

PATCH /members/1
{
    name : "박정순"
}
회원(member)1
이름 (name)박정순
나이 (age)22
성별 (gender)M

  요청에 포함되어 있는 부분에 대해서만 변경이 된다.

멱등성을 지켜야하는 이유

  HTTP 메서드의 멱등성이라는 것은 HTTP 스펙의 규약일 뿐이기 때문에 꼭 지켜야하는 것은 아니지만, 이러한 규약들을 제대로 지키지 않는다면 해당 API의 동작을 유추하기 어려워질 것이고 이는 RESTful한 API가 아니라는 것을 의미하게 될 것이다. 이는 결과적으로 원치않는 동작을 야기할 가능성이 높아지기 때문에, 가능하면 규약을 지켜 이에 맞는 동작을 하도록 구현해야 겠다.

HTTP Response Contents

State Code

image

  • HTTP 응답 상태코드는 요청에 대한 응답이 성공적으로 되었는지 알려줌
  • 자주 쓰이는 200, 400, 500번대는 자주 봐서 익혀두도록 하자

Content-Type

  • 응답 헤더 안에 있는 Content-Type
  • 클라이언트에게 전달되는 데이터 유형을 알려줌
  • Content-Type은 MIME 타입으로 표기됨
    • MIME(Multipurpose Internet Mail Extension) 타입
      클라이언트에게 전송된 문서의 다양성을 알려주기 위한 메커니즘

MIME(Multipurpose Internet Mail Extension) 타입 (리소스 포맷)

  • 파일의 포맷 분류
  • 원래는 전자 우편을 위한 표준이었으나, 웹에서도 활용하고 있음
  • 자주 쓰이는 MIME 타입들
    • Content-Type:
    • text/plain
    • text/html
    • text/css
    • image/jpeg
    • image/png
    • audio/mpeg
    • audio/ogg
    • audio/*
    • video/mp4
    • application/octet-stream
    • multipart/mixed

URI

  • URI = URL + URN
  • 리소스를 식별하는 주소
  • URL 표준으로 시작해서 개념을 확장하여 URI를 만듦
  • 스킴:사용자이름:비번@호스트:포트/경로;패러미터?쿼리#프래그먼트
https://jinu0137:pw1234@github.com:443/jinu0137/MMT?file=sum.py#30
  • 쿼리 : 편의상 =&을 사용
  • 프래그먼트 : 클라이언트에서만 사용되며 서버측에 미치는 영향은 없음

HTTPS

  • HTTP에 Secure을 덧붙인 의미로 HTTP protocol의 암호화된 버전
  • 클라이언트와 서버 간의 모든 커뮤니케이션을 암호화하기 위하여 보통 SSL이나 TLS을 사용
  • 커넥션을 이용하여 클라이언트가 민감한 정보를 서버와 안전하게 주고 받도록 해줌
  • 예전에는 HTTP 통신을 많이 사용하였으나, 최근에는 대부분의 서비스에서 HTTPS를 사용하는 추세
  • 예전에는 HTTPS용 인증서를 받기 어려웠으나, 최근에는 무료로도 HTTPS를 적용할 수 있다고 함
    https://blog.outsider.ne.kr/1178

Reference