TIL CORS
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에 대해서도 모르는 상태로 살아갔을 것입니다, 포기하지 않고 계속 붙잡고 알려고 머리를 쥐어뜯었기에 알게 되었고 더 나아갈 수 있었던 것 같습니다.
아마 또 새로운 것을 배울 때 많이 힘들겠죠? 포기하고 싶기도 하고 그럴 때에는 요즘 점점 더 휑해지는 머리를 쥐어뜯으며 버티고 알아가야겠다 느꼈습니다.