TIL/2023.4월

TIL CORS

황소탄 2023. 4. 21. 22:33

2023.04.21 금

 

DRF를 사용하기 전 퓨어 django에서는 하나의 프로젝트에 templets 폴더에 html을 만들어 사용했지만 실제 프로젝트에는 프론트엔드와 백엔드를 분리하여 만든다고 합니다.

 

drf_week2_front라는 이름으로 폴더를 만들고 html파일과 js 파일을 만들어 줍니다. 이 폴더는 프로젝트와 무관한 새로운 폴더입니다.

drf_week2_front/index.html
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>프론트엔드</title>
    <script src="index.js"></script>  #js 파일을 사용하기 위해 사용
</head>

<body>
    <h1>프론트엔드</h1>
</body>

</html>
drf_week2_front/index.js
console.log("JS등장!") #페이지가 열리면 console창에 JS등장!을 찍어준다

라이브서버를 이용하여 연결이 잘 되었는지 확인해봅시다.

연결완료!

이제 js에서 drf 프로젝트의 articles 페이지를 불러오겠습니다.

window.onload = async function loadArticles() {
    const respons = await fetch('http://127.0.0.1:8000/articles/')

    respons_json = await respons.json()

    console.log(respons_json)
}

asyn, await 비동기식 방식에 관한 개념은 아래 링크의 글에서 너무 잘 설명해줍니다.(바로이해함)

https://kangworld.tistory.com/24

 

[C#] async await 기초 #1 : 동기 비동기 개념 이해하기

인트로 C# .NET FRAMEWORK 4.5부터 추가된 async awiat 키워드에 대해서 알아보려 한다. async awiat는 서버(ex 게임 서버 웹서버)를 구축할 때 사용되는 중요한 개념 중 하나다. 블로그에 정리하고 싶었는데

kangworld.tistory.com

fetch를 사용하여 도메인을 repons에 담아주고 json형태로 respons_json 형태로 담아 준 후 console에 출력시켜 보겠습니다.

오류가 발생합니다. CORS, Allow-Orgine가 키워드처럼 보입니다.

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

 

Cross-Origin Resource Sharing (CORS) - HTTP | MDN

Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources. CORS also relies on a mechanism by which

developer.mozilla.org

CORS가 교차 원본 리소스 공유의 약자네요.

글을 읽어보면 보안 등의 이유로 헤더에 따라 공지하지 않으면, 동일한 경로를 가지고 있지 않는 이상, 가져올 수 없다고 합니다.

사용을 위해 페이지를 가져올 django에 cors를 설정이 필요해보입니다.

django cors를 검색하여 봅시다.

https://pypi.org/project/django-cors-headers/

 

django-cors-headers

django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS).

pypi.org

 

따라가봅시다

pip을 해줍니다.

python -m pip install django-cors-headers

pip이 추가되었다면 할 것이 있죠?

pip freeze > requirements.txt

requirements.txt에 pip한 것을 추가해줍니다.

잘 들어왔습니다.

settings에 추가해줍니다.

INSTALLED_APPS = [
    ...,
    "corsheaders",
    ...,
]

마찬가지로 settings에 추가해줍니다.

단, commonMiddleware보다 위에 CorsMiddleware를 추가해주어야 합니다.

(두 개를 추가하는 것이 아니라, corsheaders...만 추가합니다.)

MIDDLEWARE = [
    ...,
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    ...,
]

다음은 보안상 허용범위?를 정하는 것 같습니다.

  • CORS_ALLOWED_ORIGINS <-같은 origins만
  • CORS_ALLOWED_ORIGIN_REGEXES <-정규표현식이 같을 때
  • CORS_ALLOW_ALL_ORIGINS <-모든 orgins에서 가능

ALL_ORGINS를 사용하겠습니다.settings 가장 아래에 적어주겠습니다.

cors 설정이 끝났습니다, drf 서버가 꺼졌다면 다시 켜고 front 라이브서버 콘솔창으로 가보겠습니다.

잘 출력됩니다.

콘솔창에서 말고, html div를 만들어 웹페이지에 찍어주겠습니다.

html 파일에가서 id가 articles인 영역을 만들어줍니다.

<div id="articles">

</div>

js파일로 돌아와서 다음 코드를 사용합니다.

    const articles = document.getElementById("articles")

    respons_json.forEach(element => {
        console.log(element.title)
    });

html에서 만든 div에는 article의 title을 출력해 줄것입니다, 그것을 위해 articles라는 변수를 미리 만들어 줍니다.

 

respons_json을 for반복문을 사용하여 console창에 출력시키는데 이 때 title만 출력시킵니다.

키:값 형태의 dict 구조이기에  for반복문을 통해 title을 출력합니다.

forEach에 다음 코드를 추가합니다.

        const newArticle = document.createElement("div")
        newArticle.innerText = element.title
        articles.appendChild(newArticle)

newArticle은 div형태를 가진 인스턴스입니다.

innerText를 이용하여 newArticle에 요소의 title을 가져옵니다.

articles에 newArticle의 요소를 추가해줍니다.

js파일의 코드를 모아보면 이렇게 되어있네요

window.onload = async function loadArticles() {
    const respons = await fetch('http://127.0.0.1:8000/articles/')

    respons_json = await respons.json()

    console.log(respons_json)

    const articles = document.getElementById("articles")

    respons_json.forEach(element => {
        const newArticle = document.createElement("div")
        newArticle.innerText = element.title
        articles.appendChild(newArticle)
    });
}

이제 잘 작동되는지 확인하기 위해 사용했던 console은 지워줍니다.

 

저장 후 라이브서버를 통해 출력이 잘 되는지 확인합니다.

title만 잘 출력됩니다.

 

느낀점

왜 갑자기 js를 사용하여 프론트쪽을 구현하고 연동을 하는 과정을 강의에서 다뤘는지 먼저 생각했습니다.

CORS에 대하여 학습하기 위해 다뤘겠죠? 

 

처음 퓨어 django를 다뤘을 때 가장 들어가기 겁났던 파일은 settings.py입니다. 

뭐 하나 잘못 건드리면 고장날 거 같고 뭐가 뭔지 모르겠고 확실히 심화 과정에 들어오면서 본격적으로 settings.py를 다루어보니, 전혀 어려운 것이 아니었습니다, 공식문서나, 구글링으로 찾아보면 다 나오니까요ㅎㅎ

 

항상 돌이켜 생각해보면, 과거에 몰라서 힘들었던 부분은 정말 별 거 아니였습니다, python에서 상속 개념을 배웠을 때, django modle과 form에 대하여 너무 힘들어했을 때 정말 별 거 아니였습니다.

html로 치면 <> <-태그에 이걸 왜 사용해야하나요? css 영역에 끝에는 ; 이것을 왜 사용해야하죠? 이 정도 질문이였습니다.

그런데 왜 그렇게 힘들었을까요?

오늘만 해도 그렇습니다. 

asyn, await 비동기식 방식에 대한 개념이 없으니 js부분을 어떻게 설명해야하지 몰라 한참을 고민했습니다, 문서나 블로그를 찾아봐도 프라미스가 뭔지, 동기식처럼 사용한다는게 무슨 말인지 이게 왜 장점이고 편리한지 그렇게 한참 찾아보다가 링크로 남긴 저 블로그를 발견했고 고민한게 무색하게 금방 이해했습니다.

 

저는 이번 캠프에 참가하여 가장 크게 느낀게 포기하지 않으면 어떤 방식으로든 해결할 수 있다는 것을 알아가는 것 같습니다. 

만약 class 상속에서 포기했으면 저는 아직도 class 상속은 물론이고 django나 drf 어쩌면 python에 대해서도 모르는 상태로 살아갔을 것입니다, 포기하지 않고 계속 붙잡고 알려고 머리를 쥐어뜯었기에 알게 되었고 더 나아갈 수 있었던 것 같습니다.

 

아마 또 새로운 것을 배울 때 많이 힘들겠죠? 포기하고 싶기도 하고 그럴 때에는 요즘 점점 더 휑해지는 머리를 쥐어뜯으며 버티고 알아가야겠다 느꼈습니다.