본문 바로가기

Django and BackEnd

HTTP란?

본 내용은 책 <깔끔한 파이썬, 탄탄한 백엔드>의 4장 내용을 정리하고 살을 붙인 내용입니다. 딱히 몰라서 정리했다기보다는 그냥 정리할곳이 없어서 정리했지만, 막상 쓰다보니 모르던 부분이 많네요....;;;;;

 

----------------------------------------

 

대부분의 API 시스템은 일반적으로 HTTP 프로토콜을 기반으로 통신합니다.

 

FileZilla 와 같은 FTP 프로그램도 있어서, FTP 프로토콜을 사용하여 파일 전송에 사용하는 경우도 있지만, 웹과 관련된 기본적인 프로토콜은 HTTP 입니다.

 

 

HTTP 란 Hyper Text Transfer Protocol의 약자로서 웹 상에서 서로 다른 서버 간에 하이퍼텍스트문서, 즉 HTML을 서로 주고받을 수 있도록 만들어진 프로토콜, 즉 통신규약 입니다.

 

HTTP 에는 3가지 특징이 있는데,

 

1. 연결을 유지하지 않음(connectionless)

2. 상태를 저장하지 않음(stateless).

3. 요청(request)과 응답(response) 방식

 

위의 3가지 가 그것입니다. 거기에

4. 엔드포인트 아키텍처 패턴

 

까지 총 4개의 주제를 다룰 겁니다.

 

<1. connectionless>

 

HTTP 통신은 1회성이며, 해당 통신이 끝나면 연결을 끊어버립니다.

 

3번 항목에서 설명할 요청과 응답이 끝나면 연결이 끊기고, 새로운 요청과 응답에 대해서 새로운 연결을 생성하고 응답과 요청을 처리합니다. 예외적으로 KeppAlive 속성을 사용하면 연결을 유지할 수 있는데, 유저가 많아지면 메모리에 부담이 갈 수 있으므로 주의해야 합니다.

 

기본적으로는 연결을 유지하지 않음으로써 리소스를 확보하고 더 많은 유저에게 서비스를 제공할 수 있게 됩니다.

 

단점도 존재하는데, 모든 요청에 대해서 새로운 연결을 생성해야 하므로, 해당 작업에 부하가 걸릴 수도 있습니다.

 

연결을 유지하지 않으므로, 각각의 요청에 대해서 서버는 그 클라이언트를 식별할 수 없습니다. 따라서 연결의 1회성 덕분에 2번의 속성인 stateless가 자동적으로 만들어집니다.

 

 

<2. Stateless>

 

모든 HTTP 통신은 독립적입니다.

 

HTTP 통신에서는 과거의 통신이 현재의 통신에 영향을 주지 않으며, 현재의 통신이 미래의 통신에 영향을 주지 않습니다. 이는 상태를 저장하지 않기 때문으로, 로그인을 하건, 캐시 기록을 남기건, 게시글을 쓰건, 어떤 경우건 간에 엄밀히 말해 그러한 상태를 저장하지 않아야 합니다.

 

상태를 저장하지 않으므로, HTTP 요청에 대해서는 독립적으로 응답만 보내줘야 합니다. 이 때문에 발생하는 문제가 있는데, 로그인과 같이 상태가 필요한 경우에는 쿠키 혹은 세션을 이용하여 처리를 하게 됩니다.

 

※쿠키 :

사용자의 브라우저에 저장되는 작은 크기의 파일.

하나의 도메인당 20개까지, 최대 4KB.

HTTP는 stateless 이므로, 클라이언트에서는 필요한 모든 정보, 즉 쿠키의 정보를 다시 서버에 요청을 보낼때 사용합니다.

 

※세션:

웹서버에 저장되는 "쿠키"

사용자는 세션 ID 만을 가지고 웹 서버에 요청을 보내고, 웹 서버는 해당 세션 아이디로 쿠키를 찾아 그 정보를 사용합니다. 보안성, 성능면에서 쿠키보다 월등히 좋지만, 메모리를 많이 사용한다는 단점이 있습니다.

이러한 세션을 제공해주는 대표적인 솔루션은 Redis입니다.

 

※ Redis

Redis는 In-Memory Data-Structure Store 입니다. 단어의 의미를 하나하나 짚어보면

1. 메모리에

2. 키-값으로 구성된 자료를

3. 저장한다.

입니다.

Redis는 세션보다는 캐시를 저장하는데에 더 자주 사용되며, 세션의 자료를 저장하는 데에도 사용할 수 있고, celery의 메세지 브로커로 사용될 수 있다는 점이 큰 메리트인것 같습니다.

(쓸 내용이 너무 길어지므로 여기까지만 쓰고, 참고에 관련 내용의 링크를 달아두었습니다.)

 

 

<3. Request & Response>

 

HTTP 통신은 요청과 응답으로 이루어져 있습니다.

 

클라이언트가 서버에 요청을 보내면 서버는 요청을 처리한후 결과를 응답으로 보내줍니다. 최근 많이 사용하는 대부분의 프레임워크는 이러한 요청과 응답의 처리를 아주 간단한 코딩으로 끝낼 수 있도록 도와주지만, 그 내부 구조는 생각보다 단순하지 않습니다. 단순히 어떤 단어 하나를 돌려주는 응답에도 3가지의 기본 구조가 반드시 포함되어 있습니다.

 

요청(Request)에는 HTTP Method 라는 것이 있어, 해당 요청이 어떤 동작(action)을 원하는지 정의하는 부분이 있습니다. REST API 의 개념이 표준이 되어가는 지금 해당 메소드 들을 잘 아는 것은 매우 중요한 일입니다.

 

응답(Response)에는 상태코드라는 것이 있습니다. 응답의 상태를 미리 숫자로 정의해둔 것입니다. 그 유명한 404 Not Found의 404가 바로 상태코드입니다. 잘 설계된 API라면 응당 옳바른 상태코드를 돌려줌이 옳습니다.

 

기본구조와, HTTP Method, 그리고 상태코드를 하나하나 짚어보겠습니다.

 

[ 3.1. 요청과 응답의 구조. ]

 

{ 3.1.1. HTTP 요청 구조. }

 

(Request Example)

POST /payment-sync HTTP/1.1

Accept: application/json
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 83
Content-Type: application/json
Host: intropython.com
User-Agent: HTTPie/0.9.3

{
    "imp_uid": "imp_1234567890",
    "merchant_uid": "order_id_8237352",
    "status": "paid"
}

HTTP 요청 메세지는 크게 다음의 세 부분으로 구성되어 있습니다.

 

(1). Start Line:

Start Line은 그 안에서 또다시 세 부분으로 구성됩니다.

- HTTP Method : 요청이 의도하는 액션을 정의.

- Request Target : 요청이 전송되는 목표 주소. 엔드포인트.

- HTTP version: 이름 그대로 해당 요청의 HTTP 버전. (HTTP 버전은 아래의 다른 챕터에서 살명하겠습니다.)

 

 

(2). Headers:

헤더에는 HTTP 요청 그 자체에 대한 정보가 담깁니다. 자주 사용되는 정보가 따로 존재하는데 아래와 같습니다.

Host : 요청이 전송되는 target(서버측)의 URL주소를 알려주는 헤더입니다.

User-Agent : 클라이언트의 정보가 담깁니다. 웹 브라우저에 대한 정보도 담기는데, 아직도 IE 호환을 이야기하는 국내에서는 매우 중요한 정보입니다.

Accept: 해당 요청이 받을 수 있는 응답의 body 타입을 알려줍니다. MIME(Multipurpose Internet Mail Extensions) 타입이 value로 지정되고, 그 종류로는 application/json, image/jpeg 등이 있습니다. MIME에서 모든 종류를 다 받을 수 있다면 */* 로 지정하면 됩니다.

Connection: keep-alive 옵션을 여기에서 걸 수 있습니다. close라는 값을 걸면 연결이 끊기게 됩니다.

Content-Type : 요청의 body 타입을 알려줍니다. application/json, multipart/form-data 등이 여기에 사용됩니다.

Content-Length : 요청 메세지의 총 사이즈를 알려주는 헤더입니다.

 

(3). Body:

HTTP 요청 메세지에서 전송하는 데이터를 담고있는 부분입니다. 전송하는 데이터가 없다면 body 부분은 비어 있게 됩니다. 메소드와는 관계없이 데이터를 담을 수 있습니다. GET method 에도 Body를 넣을 수는 있습니다!(하지만 , 절대로 그렇게 하지 마세요.)

 

 

{ 3.1.2. HTTP 응답 구조. }

 

(Response Example)

HTTP/1.1 404 Not Found

Connection: close
Content-Length: 1573
Content-Type: text/html; charset=UTF-8
Date: Mon, 20 Aug 2018 07:59:05 GMT

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 404 (Not Found)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}

HTTP 응답 메세지 역시 크게 다음의 세 부분으로 구성되어 있습니다.

 

(1). Status Line:

Http 응답 메시지의 상태를 간략하게 요약하여 알려주는 부분입니다. 역시 3개 부분으로 구성되는데,

- HTTP version: 이름 그대로 해당 요청의 HTTP 버전. (HTTP 버전은 아래의 다른 챕터에서 살명하겠습니다.)

- Status Code: 상태코드입니다. 정해진 숫자로 나타내어 주게 됩니다.

- Status Text : Status Code의 보완 설명입니다.

 

(2). Headers:

요청의 헤더 부분과 동일합니다만, 응답에서만 사용되거나 요청에서만 사용되는 헤더가 따로 존재합니다.

예를 들어 요청의 User-Agent 헤더는 응답에서 Server 헤더로 대신 사용됩니다.

 

(3). Body:

요청의 바디와 동일하다. 전송 데이터가 없다면 비어있게 된다.

 

[ 3.2. HTTP 요청 메소드. ]

 

장고에서는 아래 메소드 들을 받아줍니다.

http 메소드는 그 종류가 다양하고 frame work 별로 다양한 배리에이션을 가집니다. 메소드들은 모두 하나의 RFC에 규정된 것이 아니기에 특히나 더더욱 그렇습니다. 스프링프레임워크를 다루다가 HttpURLConnection에서 "Invalid HTTP method : PATCH" 와 같은 에러가 뜨는 것은 그런 이유입니다.

 

아래는 DRF의 기본 라우터가 제공하는 메소드 들입니다.

{prefix}/ GET list {basename}-list
POST create
{prefix}/{url_path}/ GET, or as specified by `methods` argument `@action(detail=False)` decorated method {basename}-{url_name}
{prefix}/{lookup}/ GET retrieve {basename}-detail
PUT update
PATCH partial_update
DELETE destroy
{prefix}/{lookup}/{url_path}/ GET, or as specified by `methods` argument `@action(detail=True)` decorated method {basename}-{url_name}

DRF는 적어도 이런 면에서 자유롭습니다.

공식문서에 의하면 PUT, DELETE, PATCH 등의 메서드를 사용자가 걱정하지 않고 사용할 수 있도록 도와줍니다.

 

이렇게 사용할 수 있는 메소드 들을 하나 하나 알아보겠습니다.

 

 

- GET :

가장 기본적인 메소드입니다. 데이터의 조회에서 자주 사용됩니다.

url상에서 파라미터를 표기할 수 있습니다.

http://localhost:8000/albums/photo?topic=car&theme=warm

 

GET 방식에서 Path variable 과 Query parameter을 사용할 수 있습니다.

?와 = 그리고 & 를 사용하는 것이 Query parameter이고,

/albums/photo/ 와 같이 / 로 구분하는 것이 Path variable 입니다.

 

어떤 데이터를 식별해야 한다면 Path variable을 사용하는것이 바람직합니다.

반면 어떤 데이터를 검색하거나, 정렬해야 한다면 Query parameter를 사용하는 것이 바람직합니다.

 

- POST:

데이터의 생성, 수정, 삭제 요청을 할때 주로 사용됩니다.

RESTful API 규약에서 POST는 데이터의 생성에만 사용해야 합니다.

 

- PUT:

데이터의 생성 혹은 수정에서 사용되는 메서드 입니다.

 

※ RESTful API 에서 POST와 PUT의 차이.

책에서는 PUT을 쓰지않고 POST로 통일해서 사용하는 시스템이 많아지고 있다고 말하지만, 제 짧은 경력으로도 동의하기 힘든 면이 있습니다. 러닝커브가 있는 RESTful API를 도입하는 경우가 아니라면 그럴지도 모르겠네요...

가장 큰 차이는 멱등의 라 변역되는 idempotent 라는 개념입니다. 같은 동작을 반복하면 같은 결과가 나오는 것이 idempotent 인데, POST와 PUT은 이런면에서 다릅니다.

POST의 경우 타겟이 지정되어 있지 않습니다. PUT은 반드시 타겟이 지정되어 있지요. 따라서 같은 내용의 요청을 여러번 보낸다 가정했을때,  POST는 여러개의 데이터가 생성되고, PUT은 1개의 데이터가 생성된후 그 내용이 같은 내용이지만 업데이트 처리가 됩니다.

 

- PATCH:

데이터의 부분 수정에 사용되는 메서드입니다.

 

- DELETE:

데이터의 삭제에 사용되는 메서드입니다.

 

- HEAD:

GET 메서드와 같은 내용의 요청을 보냈을 경우에 돌아오는 응답의 헤더만을 받는 메서드입니다. 양쪽 모두 본문 내용이 비어 있어야 합니다.

 

- OPTIONS:

엔드포인트에서 허용하는 메소드들이 무엇이 있는지 알고자 하는 요청에서 사용됩니다.

 

- TRACE:

클라이언트가 송신한 리퀘스트를 그대로 반환하는 메서드입니다. XST(cross site tracing)는 전송되는 쿠키와 세션 ID를 탈취하여 권한을 얻는 방법인데, TRACE는 해당 공격에 취약하다는 단점을 가진 메소드입니다.

해당 메소드를 막아두어야 합니다.

 

 

 

[ 3.3. HTTP 응답 코드. ]

 

HTTP 응답 코드는 백 단위로 큰 분류가 됩니다. 예를 들어 200번대는 성공에 관한것. 400번대와 500번대는 에러에 관한 것들입니다.

 

아래 내용은 책의 내용보다 위키백과의 내용이 더 자세하고 알기 쉽습니다. 설명은 위키백과의 내용을 긁어와서 붙이는 정도로만 하겠습니다. (ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C)

 

 

1xx (정보): 요청을 받았으며 프로세스를 계속한다

HTTP/1.0이래로 어떤 1XX 상태 코드들도 정의 되지 않았습니다. 서버들은 1XX 응답을 실험적인 상태를 제외하고 HTTP/1.0 클라이언트(서버에 연결된 컴퓨터)로 보내면 안 됩니다!

 

2xx (성공): 요청을 성공적으로 받았으며 인식했고 수용하였다

200 클래스의 상태 코드는 클라이언트가 요청한 동작을 수신하여 이해했고 승낙했으며 성공적으로 처리했음을 가리킵니다.

- 200: 요청이 문제없이 잘 처리되었을때 반환됩니다.

 

3xx (리다이렉션): 요청 완료를 위해 추가 작업 조치가 필요하다

300 클래스의 상태 코드는 클라이언트가 추가 작업을 해야함을 나타냅니다.

- 301 Moved Permanently: URL 주소가 바뀐 경우 반환됩니다. Location 헤더에 새 주소가 포함되어 나오게 되며, 클라이언트는 redirection하게 됩니다.

 

4xx (클라이언트 오류): 요청의 문법이 잘못되었거나 요청을 처리할 수 없다

400 클래스의 상태 코드는 클라이언트에 오류가 있음을 나타냅니다.

- 400 Bad Request: 잘못된 요청인 경우 반환됩니다. 주로 파라미터가 잘못된 값들이 경우 발생합니다.

- 401 Unauthorized: 로그인이 필요한 경우 반환됩니다.

- 403 Forbidden: 해당 요청에 대한 권한이 없을경우 반환됩니다.

- 404 Not Found : 해당 요청을 보내고자 하는 URI 가 존재하지 않을 때 보내는 응답 코드입니다.

 

5xx (서버 오류): 서버가 명백히 유효한 요청에 대해 충족을 실패했다

500 클래스의 상태 코드는 서버가 유효한 요청을 명백하게 수행하지 못했음을 나타냅니다.

- 500 Internal Server Error : 서버의 처리 과정에서 사용하는 에러가 발생한 경우 반환됩니다.

- 503 Service Unavailble : 서버 과부하 혹은 폭주등의 경우에 반환됩니다.

- 504 Gateway Timeout : 응답 대기시간을 초과했을 경우 반환되는 에러입니다.

 

 

 

< 4. API Endpoint(URL) Architecture Pattern >

 

엔드포인트 구조를 구현하는 방식에는 널리 알려지고 사용되는 2가지 패턴이 있는데,

1. RESTful API

2. GraphQL

이 그것입니다.

 

GraphQL 은 페이스북이 개발해 비교적 최신에 나온 기술이며, REST 방식은 가장 널리 사용되는 중입니다.

 

 

REST API

리소스를 표현하는 URL(=path variable)로 대상을,  HTTP method로 액션을 지정하는 것이 포인트.

자기 설명력이 엄청난 장점으로 다가옵니다.

(RESTful API Example)

POST/users
{
	"name":"송은우",
	"email":"songew@gmail.com"
}

restAPI 는 내용이 정말 방대한데, 관심있는 분은 따로 찾아보시기를 권합니다. 도저히 포스팅 하나에 우겨넣을 수 잇는 분량이 아니에요...

 

GraphQL

오직 하나의 엔드포인트를 가지고, 클라이언트가 필요한 것을 그 엔트포인트에 요청하는 방식입니다.

(GraphQL Example)

POST/graphql
{
 user(id:1){
   name
     freiends{
       name
       email
     }
  }
}

페이스북에서 만들었으며, 심지어는 graphql-kr.github.io/ 이렇게 해당 규약을 설명하는 문서까지 사이트로 올려두었습니다. 다양한 binding을 제공하고, 당연히 django에서도 사용할 수 있습니다.

 

 

----------------

 

참고한 자료들.

 

도서.

bjpublic.tistory.com/317

 

깔끔한 파이썬 탄탄한 백엔드

깔끔한 파이썬 탄탄한 백엔드 부제 지금까지 없었던 백엔드 개발자를 위한 파이썬 저자 송은우 출간/배본가능일 2019년 1월 25일 정가 27,000원 페이지 416 판형 크라운판 (173 * 230) ISBN 979-11-86697-75-7

bjpublic.tistory.com

 

쿠키&세션 :

interconnection.tistory.com/74

 

쿠키와 세션 개념

쿠키와 세션은 개발자 말고도 인터넷 사용자라면 누구나 많이 들어본 단어입니다. 하지만 개념에 대해서는 많은 사람들이 헷갈려 하기에 쉽고 간단하게 정리해보려고 합니다. 일

interconnection.tistory.com

 

 

Redis

www.slideshare.net/charsyam2/redis-196314086

 

Redis

Redis, Redis Failover, Consistent Hashing, Commands, Failures

www.slideshare.net

 

 

celery

dingrr.com/blog/post/django-redis-celery-%EC%A1%B0%ED%95%A9%EC%9C%BC%EB%A1%9C-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%9E%91%EC%97%85

 

[Django] Redis, Celery 조합으로 비동기 작업 | 블로그 | 딩그르르

[Django] Redis, Celery 조합으로 비동기 작업

dingrr.com

 

 

Path variable, Query parameter

ryan-han.com/post/translated/pathvariable_queryparam/

 

[번역] Path Variable과 Query Parameter는 언제 사용해야 할까? | Integerous DevLog

[번역] Path Variable과 Query Parameter는 언제 사용해야 할까? 2019/04/23 원작자의 허락을 받고 번역한 글입니다. 원문: When Should You Use Path Variable and Query Parameter? *역자 주: Spring boot와 Vue.js로 파일럿 프로

ryan-han.com

 

POST, PUT

1ambda.github.io/javascripts/rest-api-put-vs-post/

 

REST API: Put vs Post

REST API: Put vs Post idempotent PUT 과 POST 를 이해하려면, idempotent 라는 개념의 도입이 필요하다. 한글로 직역하면 멱등의 정도 되시겠다. 수학적으로 이해하는 편이 쉬운데, f(x) = f(f(x)) 라 보면 된다.

1ambda.github.io

 

XST

itinformation.tistory.com/49

 

TRACE와 XST(Cross-site Tracing) 공격

cross site tracing (XST 공격) XST 공격이란 기본적으로 HTTP 메소드 중 하나인 TRACE메소드를 이용한 XSS기법 중 하나이다. 서버에서 TRACE 메소드를 지원하고 있을 때, 클라이언트가 서버로 TRACE 요청을 보

itinformation.tistory.com

 

응답 상태 코드

ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C

 

HTTP 상태 코드 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 아래는 HTTP(하이퍼텍스트 전송 프로토콜) 응답 상태 코드의 목록이다. IANA가 현재 공식 HTTP 상태 코드 레지스트리를 관리하고 있다. 모든 HTTP 응답 코드는 5개의

ko.wikipedia.org

 

-----------------------------

 

양이 너무 방대해서 중단점을 잡기가 힘든 포스팅이었네요;