[Django-python]장고 웹 프레임워크 시작하기 - (4) POST 방식 및 쿠키(cookie) 이용하기

KimJiHong·2023년 9월 16일
1

Django Basics

목록 보기
4/7
post-thumbnail

지난 게시글에서 Template 설정과 간단한 GET 방식을 통한 간단한 동적 웹 앱을 구현해보았다.

이번 게시글에서는 POST 방식을 이용한 동적 웹 앱을 구현해보고, cookiesession 의 차이와 cookie 를 알아보자

현재 장고 tree

> tree

.
├─myapp
│  ├─migrations
│  │  └─__pycache__
│  ├─myapp_templates
│  └─__pycache__
└─testsite
    └─__pycache__


POST 방식을 이용한 동적 웹

간단하게 GET 방식과 POST 방식의 차이점을 알아보자.

  • GET : web 주소를 호출할 때, URL 안에 '&', '?', '=' 등 을 사용하여 필요한 데이터를 포함시켜 요청을 보내는 방식으로 POST 방식보다 처리속도가 빠른편이다.
    즉, URL 안에 데이터가 포함되어 있다. (ex. https://www.~~~~.com/?query="쿼리검색")

  • POST : 호출할 web 주소와 데이터를 나누어서 보내는 방식으로 GET 방식과 달리 URL에 데이터가 직접 노출되지 않아 상대적으로 보안성이 좋고, 데이터의 양에 제한이 없다.
    즉, URL과 데이터가 따로 전송된다. (ex. 로그인 페이지에서의 로그인)

먼저, POST 방식의 예제로 사용하기 위해 템플릿 디렉토리에 간단한 HTML 폼(form)을 작성해주자.

<!-- /myapp/myapp_templates/post_index.html -->

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>POST방식</title>
</head>
<body>

    <h1>TEST_kimjihong</h1>
    <div>안녕하세요?</div>
    
  	<!-- action 속성은 데이터가 전송될 URL 패턴을 지정.
 	지난 게시글에서의 urls.py에서 별칭(name) 파라미터-->
    <form action="{% url 'post_method' %}" method="post">
      
      	<!-- ※중요※
		장고 에서 POST 요청을 보낼 때 CSRF 보호 기능을 사용하려면,
		꼭! form 태그 내부에 이 csrf_token 태그를 포함시켜야 한다. -->
        {% csrf_token %}
      
        <div>
            <input type="text" name="text_data_input">
        </div>
        <div>
            <input type="submit" value="전송">
        </div>
    </form>
    
  	<!-- DTL(장고 템플릿 언어)의 if문.
	text_data가 있다면 endif 까지의 내용을 출력
 	즉, text_data라는 데이터(context)가 있다면 출력 -->
    {% if text_data %}
    <div>
        {{ text_data }}
    </div>
  	<!-- DTL if 문 종료 -->
    {% endif %}

</body>
</html>

HTML 소스내부에 주석을 통해서 간단하게 설명도 추가했다.

여기서 중요한 부분은, CSRF(Cross-Site Request Forgery) 보호 기능이다.
CSRF 에 대해서는 이 블로거님이 자세히 설명해주셨다.

Django 에서는 기본적으로 CSRF 공격보호를 위한 csrf_token 이 제공된다.



POST 방식을 위한 HTML 소스를 작성했으니, 이제 URL 매핑을 시작해보자!

views.py 에 아래의 함수를 추가해주자!

# myapp/views.py

def POST_index(request):
    
    # POST 방식
    if request.method == 'POST':
        data = request.POST.get("text_data_input")
        context = {'text_data' : data}

        return render(request, 'post_index.html', context)
    
    # GET 방식
    # 클라이언트로 부터 첫 request시 어떠한 데이터도 없다!
    else:
        context = { }
        
        return render(request, 'post_index.html', context)

위와 같이, 클라이언트로부터 온 request 방식이 POST 일 때, 폼 데이터 text_data_input 을 읽고, HTML에 데이터를 전송해준다.

또한, 처음 URL request시에는 클라이언트로부터 GET 방식의 요청을 받아 템플릿 소스를 응답하도록 작성해준다.

이제 urls.py 를 다음과 같이 변경하여 URL 패턴을 추가해주고, runserver 해보자

# myapp/urls.py

from django.urls import path

from . import views

urlpatterns = [
    path('<str:name>/<str:li_text>', views.index, name='index'),
    
    # URL : http://localhost:8000/myapp
    # URL 패턴명 : 'post_method'
    path('', views.POST_index, name='post_method')
]


POST method test1POST method test2

HTML 소스에서 설정한 DTL if 문도 정상적으로 작동하는 것을 볼 수 있다!




쿠키(Cookie)

우리는 POST 방식으로 데이터를 전송해봤다.

이제, Cookie 또는 Session 을 사용하여 다시 해당 URL로 들어왔을 때, 내가 전송한 데이터를 유지시킬 수 있는 방법을 알아보자.

쿠키(Cookie)와 세션(Session)의 차이

쿠키와 사용하기에 앞서 쿠키세션과의 차이를 간단하게 알아보자!

쿠키(Cookie)

  • 클라이언트(브라우저)에 저장되는 작은 텍스트 파일 (약 4KB)
  • 클라이언트가 서버에 request 를 보낼 때마다 쿠키 정보가 헤더에 포함된다!
  • 민감하지 않은 데이터를 클라이언트 측에 저장
  • 속도가 상대적으로 빠르다

세션(Session)

  • 서버에 클라이언트의 정보를 저장되고 용량제한이 없다!
  • 세션 ID로 식별하며, 클라이언트는 세션 ID를 쿠키 또는 URL 파라미터로 서버에 request
  • 로그인 상태와 같은 민감한 데이터를 서버 측에 저장
  • 속도가 상대적으로 느리다

쿠키(Cookie) 를 이용해보자!

쿠키를 사용하기 위해 새로운 URL 패턴과 views.py 를 통해 애플리케이션 로직을 수정해보자.

먼저 views.py 에 새로운 로직을 추가해보자!

# myapp/views.py
from django.shortcuts import render, redirect


def POST_index_cookies(request):
    
    # POST
    if request.method == 'POST':
        data = request.POST.get("text_data_input")

        # render가 아닌 redirect를 사용하는 이유!
        # 데이터(context)를 템플릿에 보내는것이 아닌
        # 쿠키 데이터가 HTTP 헤더에 포함된 템플릿으로
        # 이동하도록 하기 위함이다!
        # 여기서는 'using_cookies' 라는 URL 패턴 으로 이동
        response = redirect('using_cookies')
        
        # data 변수를 'text_data_cookies' 라는 이름으로
        # Cookie 에 포함
        response.set_cookie('text_data_cookies', data, max_age=30)

        return response
    
    # GET
    else:
    	# 'text_data_cookies' 라는 쿠키가 있는지 확인
        # 없다면 None 을 반환
        data = request.COOKIES.get('text_data_cookies', None)
        context = {'text_data' : data}

        return render(request, 'post_index.html', context)

위 소스에서
쿠키를 생성을 위한 메소드인 set_cookie 메소드에서 max_age 는 쿠키가 유지되는 시간을 '초' 단위로 설정할 수 있다!
위 코드에서 쿠키 유지시간은 30초로 정의했다.
만약 max_age 를 따로 명시하지 않으면 default 값인 브라우저가 종료될때까지 유지된다!

이제, urls.py 에서 URL 매핑을 추가해보자.

# myapp/urls.py

urlpatterns = [
	# ~~~
	# urlpatterns 에 url 패턴 별칭 'using_cookies' 추가
    path('cookie', views.POST_index_cookies, name='using_cookies'),
]


인코딩(encode) 및 디코딩(decode) 오류

쿠키에 대한 설정이 마무리 되었다.
서버를 실행하고 "안녕" 이라는 단어를 쿠키에 저장해보자!

UnicodeEncodeError: 'latin-1' codec can't encode characters in position 243-247: ordinal not in range(256)

우리는 위와 같이 인코딩 오류가 발생하게된다..

그 이유는, 쿠키 데이터가 latin-1 범위 내에서 인코딩되어 저장되기 때문이다.
따라서, 한글과 같은 데이터를 쿠키에 저장하기 위해 UTF-8 로 인코딩 하여 저장해야한다.

'UTF-8' 로 인코딩하는 방식

  • URL 인코딩 (urllib)
  • BASE64

나는 UTF-8 로 인코딩 하기 위한 base64 라이브러리를 사용해서 수정해봤다.

# myapp/views.py

import base64


def POST_index_cookies(request):
    
    # POST
    if request.method == 'POST':
        data = request.POST.get("text_data_input")
        
        # BASE64 인코딩 작업
        encoding_data = base64.b64encode(data.encode()).decode()

        response = redirect('using_cookies')
        response.set_cookie('text_data_cookies', encoding_data, max_age=30)

        return response
    
    # GET
    else:
        data = request.COOKIES.get('text_data_cookies', None)

		# BASE64 디코딩 작업
        if data:
            decoding_data = base64.b64decode(data).decode()

        else:
            decoding_data = ''

        context = {'text_data' : decoding_data}

        return render(request, 'post_index.html', context)

이제 다시 실행시켜보면, 쿠키가 정상적으로 save 및 load 가 되는것을 볼 수 있다.


이번 게시글에서 POST 방식을 사용한 동적 웹 과 쿠키(Cookie)를 사용하여 데이터를 유지할 수 있도록 구현해봤다.

쿠키는 자체의 용량이 작기도 하고 로그인 유지와 같은 민감한 데이터에 사용하기에는 맞지않다.
또, UTF-8 형식으로 인코딩하여 저장해야 한다.

다음 게시글에서는 세션(Session) 에 대해서 알아보자!

전체 소스코드 Github!



틀린 부분이 있다면 지적 정말 감사합니다. 바로바로 수정하겠습니다.
profile
https://h0ng.dev

0개의 댓글

관련 채용 정보