저는 30시간 정도 버렸지만... 이 포스팅을 읽으신 분들은 1시간 안에 "아하!" 하시길 바라며...
🙏 지훈님과 저를 도와주신 모든 동기님들 감사합니다 🙏
HTTP는 HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 프로토콜이다. HTTP는 웹에서 이루어지는 모든 데이터 교환의 기초이며, 클라이언트-서버 프로토콜이기도 하다. 클라이언트-서버 프로토콜이란수신자 측에 의해 초기화되는 프로토콜을 의미한다. 하나의 완전한 문서는 택스트, 레이아웃 설명, 이미지, 비디오, 스크립트 등 불러온(fetch)한 하위 문서들로 재구성된다.
HTTP는 전송받는 주체(사용자)와 전송하는 주체(서버)가 있다. HTTP 통신은 Stateless 즉 독립적이기 때문에 과거의 통신을 기억하지 못한다. 그러므로 매 통신마다 모든 정보를 담아서 요청을 보낸다. 이 과정을 더 쉽게 하기 위해 로그인 토큰, 브라우저의 쿠키, 로컬스토리지 같은 기술이 추가됐다.
여기서 우리가 꼭 기억해야하는 점:
프론트엔드는 백엔드에게 데이터를 요청하고 백엔드는 요청을 처리해서 응답한다.
데이터 요청을 받을 때 JSON으로 받으며, 다시 응답할 때도 JSON으로 보내야 한다.
프론트에서 받아온 데이터는 JSON 형식으로 된 문자열 형태로 넘어오기 때문에 파이썬은 이를 딕셔너리 객체로 사용하기 위해 json.loads를 사용한다. 요청 받은 데이터는 기본적으로 여러 아이템들이 들어있는 json 데이터이므로 응답할 때도 똑같이 JSON 데이터(딕셔너리 타입)로 변환해 보내줘야 한다.
시나리오 : 프론트에서 body 속에 데이터를 넣어 보내주면 ➜ 백은 해당 body 데이터를 딕셔너리 객체로 쓰기 위해 json.loads(request.body)를 이용해서 데이터를 접근한다 ➜ 그리고 다시 json 형태(딕셔너리)로 응답한다.
main 페이지에서 각 app들과 url을 매핑해주는 곳이다.
프론트에서 요청을 보낼 때 어떤 view로 진입하고 어떤 클래스를 봐야하는지 경로를 호출해주는 곳이다. Django는 settings.py에 있는 ROOT_URLCONF
설정에 의해 해당 모듈을 바라보도록 지정되어 있다. project urls.py에서 urlpatterns라는 변수를 찾도록 설정되어 있으며 순서대로 패턴을 따라간다.
ROOT_URLCONF
안에 project urls 뿐만 아니라 app url도 같이 추가해 줄 수 있지만 이렇게 진행할 경우 리스트가 길어지며 디버깅하기 어려워진다.
그러므로 각 app에 urls.py를 하나씩 생성해서 project urls.py에서 include
를 import해 app urls.py를 땡겨 쓰는거다.
이미지 속
ROOT_URLCONF
는 project의 url로 경로 지정되어 있다.
include()
는 다른 URLconf module path(경로)도 여기에 '포함'시키는 함수다.
path()
로 import한 views 클래스들을 각 .as_view()
를 사용해 url 경로를 하나씩 만들어준다. .as_view()
는 request를 받고 response이 가능한, 호출이 가능한 view를 반환하는 메소드다. get, post 호출해주는 기능을 as_view()
가 해준다. (View)는 상속을 받는 것이다.
class SignUpView(View):
models.py은 ORM을 사용해서 데이터를 생성, 조회, 수정, 삭제하며 전체적인 구조를 작성한다. 여기서 데이터 타입(ex. ManyToMany)을 결정하며, 데이터 사이의 연관성(ex. on_delete=models.CASCADE)을 지어준다. 데이터 로직을 여기에 짜며 해당 로직을 데이터베이스에 migration한다. 바로 이 이유 때문에 urls, views도 아닌 models.py를 가장 먼저 생성한다.
models.py는 views.py가 데이터를 알아서 잘 꺼내갈 수 있도록 데이터표를 생성하는 곳이다. models.py에 있는 클래스 하나는 데이터 테이블, 그리고 그 클래스 안에 있는 항목 하나하나는 데이터 테이블의 칼럼으로 지정된다. 이 일을 바로 from django.db import models
가 알아서 자동으로 해준다.
** __str__
스페셜 메소드를 이용해 models.py 안에 만들었던 객체를 생성할 때 마다 어떻게 반환할지 명시할 수 있다.
** Meta Class로 테이블의 이름을 바꿔줄 수 있다.
Django는 MVT로 설계되어 있으며 CRUD로 작업을 중심으로 한다. CRUD는 데이터베이스의 테이블에 대해 작성, 검색, 업데이트 및 삭제 작업을 수행하는 것을 의미한다.
Django에서 View는 MVC 속 Controller와 비슷한 역할을 한다. views.py는 request를 받고 필요한 데이터를 models.py, DB에서 가져와서 프론트에서 다시 보내준다. 프론트의 다양한 http request(GET, POST, ..etc)를 받아줘야한다.
views는 클래스형으로 짜야하며 클래스명은 해당 클래스의 기능을 바로 알 수 있도록 지어야 한다. 추상적이고 애매하면 망한다. 효율성을 위해, 경로 추적을 더 쉽게 하기 위해 동작은 명시하지 않고 오로지 명사로 클래스명을 짓는다.
HttpResponse는 메세지 없이 status code만 필요할 때 사용하며, JsonResponse는 메세지 또는 어떤 데이터를 보내야할 때 쓴다.
GET, POST 등 HTTP 메소드에 따른 처리를 메소드명으로 구분하며 효율적으로 코드를 짤 수 있다. 함수형 View와 다른게 클래스형 View는 HTTP 메소드 이름으로 메소드를 정의하면 된다. django 내부적으로 dispatch()
메소드가 어떤 HTTP 메소드로 요청이 들어왔는지 알고 이를 처리해주기 때문이다.
함수형 클래스의 가장 큰 단점이 바로 request 행위마다 만들어야 한다는 것이다. 즉 클래스형 View에서는 행위를 하는 클래스
를 만들면 안된다. 행위형(?) 클래스 View
구조를 짤 시 함수형 View와 차이가 없어지며 효율성이 떨어진다.
즉 전체적인 행위를 하는 클래스 하나, 그리고 세부적인 행위를 하는 클래스 하나 이렇게 따로 로직을 설계하는 것이 좋다.
REST API는 분명한 URL를 만들어 통신을 해야 하기 때문에 혼동을 주지 않도록 URL 경로의 마지막에는 슬래시(/)를 사용하지 않는다. 슬래시(/)를 사용하면 depth가 달라진다.
⛔ POST http://example.com/products/create-drink/1 (x)
⛔ GET http://example.com/products/read-drink/1 (x)
✅ DELETE http://example.com/products/drink/1 (O)
시나리오: 어느 특정 제품을 일괄 수정하고 싶은 상황 ➜ 프론트에서 HTTP Request로 일괄 수정 요청을 했으며 ➜ request.body안에 요청 내용이 담겨 있다.
프론트와 백의 언어가 다르기 때문에 JSON이라는 언어로 서버는 교류하고 통신한다. 요청의 주체는 프론트이다. 그러나 내가 처리할 줄 아는것만 보내라고 하는게 우리으
앞에서 말했다시피 프론트에서 받아온 데이터는 JSON 형식으로 된 문자열 형태로 넘어오기 때문에 파이썬은 이를 딕셔너리 객체로 사용하기 위해 json.loads를 사용한다.
수정요청 항목은 key : value
구조다. 우리는 값을 수정하고 싶기 때문에value
를 접근해야 한다. dict[key]
으로 각 value
를 뽑을 수 있다.
여기서 if문은 url로 보낸 해당 product_id
가 존재하는지(exists)에 관한 조건문이다. 만약 product_id
가 없으면 400 error가 뜰 것이다.
해당 product_id
가 존재한다면, 프론트에서 요청한 사항을 하나씩 변수에 담은 다음 ➜ Product의 값들을 하나씩 수정해주고 ➜ save()
를 한다.
🖤 TMI 🖤
data는 딕셔너리 형태이라[]
를 쓰고 Product는 객체이니.
dot notation으로 들어간다.
manage.py가 있는 디렉토리로 가서 runserver를 실행한다.
python manage.py runserver
runserver를 실행한 다음 HTTP request + body안에 넣을 데이터를 함께 보낸다.
구조 : 메소드 / URL / body(수정 요청 내용)
http -v PUT 127.0.0.1:8000/products/drink/1 korean_name="한글 이름" english_name="eng_name" description="상 세 정 보 란" is_new = "True"
🖤 TMI 🖤
1. korean_name="한글 이름" <- 와 같이 항목들 사이에 공백있으면 안됨
2. models.py, views.py, request에 모두 오타 있으면 안됨
3. 터미널을 두 창 띄우고 하나는 runserver, 하나는 HTTP Request를 전송해야 한다. 같은 창에 할 수 없는 작업이다.
HTTP Request:
Server:
✅ 데이터 수정 성공! ✅
Reference:
https://developer.mozilla.org/ko/docs/Web/HTTP/Overview
https://my-repo.tistory.com/33
https://valuefactory.tistory.com/570
https://velog.io/@ifyouseeksoomi/Django-%EB%82%B4%EA%B0%80-%EC%9D%B4%ED%95%B4%ED%95%9C-flow-urls.py-views.py-models.py-django-shell
https://meetup.toast.com/posts/92
https://sanghaklee.tistory.com/57
디테일한 글 너무 좋아요~~