TIL #51: [Django] 수박 겉핥기 식으로 공부하다 데이고 쓰는 HTTP & CRUD

셀레스틴 허·2021년 1월 30일
3
post-thumbnail

저는 30시간 정도 버렸지만... 이 포스팅을 읽으신 분들은 1시간 안에 "아하!" 하시길 바라며...
🙏 지훈님과 저를 도와주신 모든 동기님들 감사합니다 🙏

목차

  1. HTTP Request, Response : frontend, backend 사이 주고받는 데이터 요청과 응답
  2. 백엔드는 JSON을 어떻게 처리해야 할까?
  3. urls.py, models.py , views.py 각각의 역할
  4. 클래스형 View를 써야하는 이유
  5. Restful API의 조건
  6. HTTP Request& views.py & JSON

1. HTTP Request, Response


HTTP는 HTML 문서와 같은 리소스들을 가져올 수 있도록 해주는 프로토콜이다. HTTP는 웹에서 이루어지는 모든 데이터 교환의 기초이며, 클라이언트-서버 프로토콜이기도 하다. 클라이언트-서버 프로토콜이란수신자 측에 의해 초기화되는 프로토콜을 의미한다. 하나의 완전한 문서는 택스트, 레이아웃 설명, 이미지, 비디오, 스크립트 등 불러온(fetch)한 하위 문서들로 재구성된다.

1.1) Stateless HTTP

HTTP는 전송받는 주체(사용자)와 전송하는 주체(서버)가 있다. HTTP 통신은 Stateless 즉 독립적이기 때문에 과거의 통신을 기억하지 못한다. 그러므로 매 통신마다 모든 정보를 담아서 요청을 보낸다. 이 과정을 더 쉽게 하기 위해 로그인 토큰, 브라우저의 쿠키, 로컬스토리지 같은 기술이 추가됐다.

여기서 우리가 꼭 기억해야하는 점:
프론트엔드는 백엔드에게 데이터를 요청하고 백엔드는 요청을 처리해서 응답한다.

1.2) Response Status Codes(Status line 안에 있음)

  • 200 : Ok - 벡엔드 서버에서 문제 없이 요청 처리가 이루어졌을 때 나오는 코드
  • 201 : Created - 즉 생성, 또는 수정이 성공적으로 이루어졌을 때 나오는 코드
  • 400 : Bad Request - Body 내용이 잘못됐을 때 또는 요청이 잘못됐을 때 나오는 코드.
  • 404 : Not found - 요청 URL이 존재하지 않는다는 코드
  • 500 : Internal Server Error - 서버 에러가 났을 때 나오는 코드

1.3) HTTP Request Methods

  • GET : 데이터를 서버로부터 받아올 때 사용하는 메소드
  • POST : 데이터를 수정, 생성할 때 사용하는 메소드, body안에 message또는 요청 사항이 들어가있을 확률이 높다.
  • DELETE : 데이터를 서버에서 삭제 요청을 보낼 때 쓰는 메소드
  • PUT : 서버에 있는 특정 데이트를 일괄 수정할 때 사용한다. PUT도 body안에 message또는 요청 사항이 들어가있을 확률이 높다.

1.4) 백엔드 주목... 프론트에서 보내는 데이터 타입은 JSON이다

데이터 요청을 받을 때 JSON으로 받으며, 다시 응답할 때도 JSON으로 보내야 한다.

2. 백엔드는 JSON을 어떻게 처리해야 할까?


프론트에서 받아온 데이터는 JSON 형식으로 된 문자열 형태로 넘어오기 때문에 파이썬은 이를 딕셔너리 객체로 사용하기 위해 json.loads를 사용한다. 요청 받은 데이터는 기본적으로 여러 아이템들이 들어있는 json 데이터이므로 응답할 때도 똑같이 JSON 데이터(딕셔너리 타입)로 변환해 보내줘야 한다.

시나리오 : 프론트에서 body 속에 데이터를 넣어 보내주면 ➜ 백은 해당 body 데이터를 딕셔너리 객체로 쓰기 위해 json.loads(request.body)를 이용해서 데이터를 접근한다 ➜ 그리고 다시 json 형태(딕셔너리)로 응답한다.

3. DJANGO urls.py, models.py , views.py 각각의 역할


3.1) urls.py

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로 경로 지정되어 있다.

3.1.1) Project urls.py

include()는 다른 URLconf module path(경로)도 여기에 '포함'시키는 함수다.

3.1.2) App urls.py

path()로 import한 views 클래스들을 각 .as_view()를 사용해 url 경로를 하나씩 만들어준다. .as_view()는 request를 받고 response이 가능한, 호출이 가능한 view를 반환하는 메소드다. get, post 호출해주는 기능을 as_view()가 해준다. (View)는 상속을 받는 것이다.

class SignUpView(View):

3.2) models.py

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로 테이블의 이름을 바꿔줄 수 있다.

3.2.1) DJANGO CRUD

Django는 MVT로 설계되어 있으며 CRUD로 작업을 중심으로 한다. CRUD는 데이터베이스의 테이블에 대해 작성, 검색, 업데이트 및 삭제 작업을 수행하는 것을 의미한다.

  • Create : 데이터베이스의 테이블에 새 항목을 만들거나 추가한다.
  • Retrieve : 기존 항목을 읽거나, 검색하거나, 또는 보거나(List View) 특정 항목(Detail View)을 세부적으로 가져온다.
  • Update : 데이터베이스에 있는 기존 항목을 업데이트하거나 수정한다.
  • Delete : 데이터베이스에 있는 기존 항목들을 삭제, 비활성 혹은 제거하한다.

3.3) views.py

Django에서 View는 MVC 속 Controller와 비슷한 역할을 한다. views.py는 request를 받고 필요한 데이터를 models.py, DB에서 가져와서 프론트에서 다시 보내준다. 프론트의 다양한 http request(GET, POST, ..etc)를 받아줘야한다.

views는 클래스형으로 짜야하며 클래스명은 해당 클래스의 기능을 바로 알 수 있도록 지어야 한다. 추상적이고 애매하면 망한다. 효율성을 위해, 경로 추적을 더 쉽게 하기 위해 동작은 명시하지 않고 오로지 명사로 클래스명을 짓는다.

3.3.1) HttpResponse, JsonResponse의 차이점

HttpResponse는 메세지 없이 status code만 필요할 때 사용하며, JsonResponse는 메세지 또는 어떤 데이터를 보내야할 때 쓴다.

4. 클래스형 View를 써야하는 이유


GET, POST 등 HTTP 메소드에 따른 처리를 메소드명으로 구분하며 효율적으로 코드를 짤 수 있다. 함수형 View와 다른게 클래스형 View는 HTTP 메소드 이름으로 메소드를 정의하면 된다. django 내부적으로 dispatch()메소드가 어떤 HTTP 메소드로 요청이 들어왔는지 알고 이를 처리해주기 때문이다.

함수형 클래스의 가장 큰 단점이 바로 request 행위마다 만들어야 한다는 것이다. 즉 클래스형 View에서는 행위를 하는 클래스를 만들면 안된다. 행위형(?) 클래스 View 구조를 짤 시 함수형 View와 차이가 없어지며 효율성이 떨어진다.

즉 전체적인 행위를 하는 클래스 하나, 그리고 세부적인 행위를 하는 클래스 하나 이렇게 따로 로직을 설계하는 것이 좋다.

5. Restful API의 조건


5.1) url 끝에 slash를 안붙인다.

REST API는 분명한 URL를 만들어 통신을 해야 하기 때문에 혼동을 주지 않도록 URL 경로의 마지막에는 슬래시(/)를 사용하지 않는다. 슬래시(/)를 사용하면 depth가 달라진다.

5.2) 행위(method)는 url에 포함하지 않는다.

⛔ 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)

5.3) GET, DELETE는 Body로 데이터를 전송하지 않는다.

6. HTTP Request& views.py & JSON


시나리오: 어느 특정 제품을 일괄 수정하고 싶은 상황 ➜ 프론트에서 HTTP Request로 일괄 수정 요청을 했으며 ➜ request.body안에 요청 내용이 담겨 있다.

6.1) 프론트에서 JSON 파일로 수정 요청이 들어오면 백엔드는 views.py 속 메소드를 어떻게 짜야 할까?

프론트와 백의 언어가 다르기 때문에 JSON이라는 언어로 서버는 교류하고 통신한다. 요청의 주체는 프론트이다. 그러나 내가 처리할 줄 아는것만 보내라고 하는게 우리으

6.1.1) json.loads

앞에서 말했다시피 프론트에서 받아온 데이터는 JSON 형식으로 된 문자열 형태로 넘어오기 때문에 파이썬은 이를 딕셔너리 객체로 사용하기 위해 json.loads를 사용한다.

수정요청 항목은 key : value 구조다. 우리는 값을 수정하고 싶기 때문에value를 접근해야 한다. dict[key]으로 각 value를 뽑을 수 있다.

views.py

models.py

여기서 if문은 url로 보낸 해당 product_id가 존재하는지(exists)에 관한 조건문이다. 만약 product_id가 없으면 400 error가 뜰 것이다.

해당 product_id가 존재한다면, 프론트에서 요청한 사항을 하나씩 변수에 담은 다음 ➜ Product의 값들을 하나씩 수정해주고 ➜ save()를 한다.

🖤 TMI 🖤
data는 딕셔너리 형태이라 []를 쓰고 Product는 객체이니 . dot notation으로 들어간다.

6.2) PYTHON runserver:

manage.py가 있는 디렉토리로 가서 runserver를 실행한다.

python manage.py runserver

6.3) HTTP Request:

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를 전송해야 한다. 같은 창에 할 수 없는 작업이다.

6.4) Request 전송 성공:

HTTP Request:

Server:

6.5) mysql 들어가서 확인하기

✅ 데이터 수정 성공! ✅

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

profile
Software Developer / 고통은 필연, 괴로움은 선택

2개의 댓글

comment-user-thumbnail
2021년 1월 31일

디테일한 글 너무 좋아요~~

1개의 답글