HTTP Method과 django (1) - GET, POST

solee·2022년 3월 13일
0

Django

목록 보기
10/12

GET과 POST에 대해서는 자주 사용하기도 했고, 익숙하기도 하다. 그런데 이리저리 찾아다니다 보니 PATCH나 PUT처럼 내가 모르는 녀석들이 몇 있어서, 공부할 겸 정리할 겸 이것들을 사용해보려 한다.




먼저 GET과 POST에 대해 적어보자.

GET

GET Method는 아주 간단하게 생각하자면 우리가 인터넷 브라우저의 주소창에 입력해 요청을 보내는 것이 GET이다. http://www.naver.com 이라는 요청이 들어오면 서버에서 해당되는 데이터를 리턴해주는 것이다. 데이터를 변경하지 않고 단순히 요청한다.

CRUD로 보자면 C에 해당한다.

GET Method는 url로 데이터를 입력받을 수 있다.

주소창이라 하면 다들 주소창의 숫자를 바꿔본 적이 있을 것이다. 예를 들어 보자.

http://example/boardlist?page=3
http://example/board/3

이런 주소가 있다면, 리스트 페이지를 이동하다가 문득 어라? 나는 12페이지로 가고 싶다! 하면서 주소를 http://example/boardlist?page=12 처럼 수정해 진입할 수 있다. 또 게시판에서 3번 글을 보다가 어라? 나는 100번 글이 보고 싶다! 하면서 http://example/board/100 으로 수정해 진입할 수도 있다.

이렇게 데이터를 url을 이용해 받는데, 방식은 언급한 2가지다.

Query Param, Path Param

먼저 쿼리 파라미터다.

쿼리 파라미터란, 쿼리 스트링이라고도 하는데 주소 뒤에 ?key=value 형태로 데이터를 받는 것이다. 요청을 보내는 주소 뒤에 ?를 붙이고 키=값 을 보내는 것이다. 예를 들어

http://example/boardlist?searchKeyword=cat&page=3

이런 주소가 있다면, searchKeyword라는 키의 값이 cat이라는 정보와 page라는 키의 값이 3이라는 것을 알 수 있다. 어떤 게시판의 리스트를 보고 있었다면 해당 게시판에 cat을 검색한 후 3페이지를 요청했다는 의미를 유추할 수도 있다.
?key1=value1&key2=value2 이런 형식으로 여러 키=값을 보낼 때 &를 쓴다.


더 현실적인 예를 들어볼까? 구글에 cat을 검색해보자.

https://www.google.com/search?q=cat&oq=cat&aqs=chrome..69i57j69i59l2j46i199i433i465i512j46i131i199i433i465i512j0i433i512j46i199i433i465i512j0i512j0i131i433i512.480j0j15&sourceid=chrome&ie=UTF-8

엄청난 주소가 나온다! 잘 살펴보자.

https://www.google.com/search 로 요청이 들어갔다는 사실을 알 수 있다. 그리고 ?를 붙어 q라는 key에 검색어 cat이, 또 무엇인지는 알 수 없지만 oq라는 key에 cat이 들어갔다는 것을 알 수 있다. 중간은 모르겠지만 마지막 ie=UTF-8을 통해 유니코드 인코딩 방식을 알 수 있기도 하다.


이번에는 네이버 쇼핑에서 검색을 해 보자.

https://search.shopping.naver.com/search/all?query=%EC%8B%A0%EB%B0%9C&cat_id=&frm=NVSHATC

"신발"을 검색한 결과다. 한글은 인코딩되어 보이지만 크롬은 브라우저가 한글로 변환해서 보여준다. 보기 불편한 것 같아서 다시 cat을 검색했는데,

https://search.shopping.naver.com/search/all?query=cat&frm=NVSHATC&prevQuery=%EC%8B%A0%EB%B0%9C

와우!! 생각 외의 결과가 나왔다. 일단 query라는 키의 값은 cat인데, prevQuery라는 이전 검색어를 따로 저장하고 있었다. 뒤로가기를 위해서는 아닌 것 같고 데이터를 수집하기 위해서일 것 같다.

맨 아래로 내려가 페이지를 바꿔 보면?

https://search.shopping.naver.com/search/all?frm=NVSHATC&origQuery=cat&pagingIndex=3&pagingSize=40&productSet=total&query=cat&sort=rel×tamp=&viewType=list

pagingSize나 productSet, sort, timestamp, pagingIndex같이 예상되는 키들이 보인다. 이걸 바꿈으로써 내가 원하는 결과를 꺼낼 수도 있다.



이번에는 패쓰 파라미터를 보자. 보이는 대로 /3 처럼 숫자 자체가 어떤 정해진 값을 보내는 역할을 한다. 게시판의 글번호 3번을 보고 있는 경우가 되겠지.

http://example/board/3

이것도 예시를 들어 보자. 브리타니카 사전에서 cat을 검색하면 다음과 같은 링크를 볼 수 있다.

https://www.britannica.com/animal/cat

.com/ 뒤에 오는 <string>에 의해 어떤 요청이 들어올지가 갈린다. 만일 /cat 대신 /dog를 입력한다면 강아지에 대한 정보를 볼 수 있다. 그러면 이런 페이지 하나하나를 다 만든 것일까? 그렇지 않다. /cat이라는 요청이 오면 DB에서 고양이에 대한 데이터를 꺼내오도록 설정되어 있다.


이번에는 네이버 뉴스를 보자.

https://media.naver.com/press/437 - JTBC
https://media.naver.com/press/081 - 서울신문

/press까지의 요청 뒤에 오는 숫자<int>로 해당 값을 가진 신문사가 출력되어 나오는 것을 확인할 수 있다.




이렇게 두 가지 방식으로 GET요청에 데이터를 보낼 수 있다. 서버는 해당 데이터들을 읽어들여 적절한 데이터를 반환한다. 이런 데이터가 없는 경우에도 마찬가지로 해당 페이지에 설정된 데이터를 반환한다. 마치 https://news.naver.com/ 이라는 요청을 통해 네이버 뉴스의 메인 페이지가 뜨는 것과 같다.




POST

POST Method는 get과는 달리 링크의 데이터를 가져올 수 없다. 대신, 페이지가 내부적으로 데이터를 전송한다.

CRUD로 보면 Create에 해당한다.

POST Method는 request로 데이터를 전달받는다.

Create기 때문에, POST Method는 데이터가 필요하다. 프론트에서 어떻게 데이터를 보내는지는 아직 모르겠지만, request의 body로 데이터가 전달되어 온다. 이때 데이터는 키-값 쌍인 json형태를 가지는데, 파이썬에서 이 데이터를 활용할 때에는 동일하게 키-값 쌍을 가지는 dict로 변환해 사용한다.

생성하는 것은 아니지만 로그인을 생각해 보자. 아이디와 비밀번호를 DB에 전달해 일치하면 로그인할 수 있다. 이때 GET을 쓴다면 주소에 아이디나 비밀번호를 노출하게 된다! 또 결제같이 예민한 데이터가 노출된다면 해당 데이터를 수정해 악용할 수도 있을 것이다. 그러니 내부적으로 데이터가 움직이는 POST Method를 사용해야 한다. 물론 보안은 따로 더 해야 하지만...



아무튼, postman으로 데이터를 보낸다면 예시는 다음과 같다.

http://localhost:8000/products 라는 요청이 들어올 때, request의 body에 json형태의 데이터가 함께 전달된다. 해당 데이터를 이용해 DB에 create하게 되는 것이다.




위 두 Method는 가장 자주 쓰인다.
이제 django에서 이 메서드들을 사용해 보도록 하겠다. 사실 gs25 프로젝트에서 이미 많이 사용했지만, 정리하자는 의미에서!




GET, POST 사용하기

app 추가

먼저 새로운 앱을 만들고 시작해 볼까. startapp 명령어로 stores라는 앱을 생성한다. 매장의 정보에 대해 관리하면 좋겠다. 새로 앱을 생성했으니 settings.py 에 추가해 준다.

modeling 작성

이제 모델링을 작성해 주자. 매장 정보니까 주소, 전화번호 등이 필요할 것이다.

직원 수, 면적 등을 가지고, 지점장은 이전에 생성했던 Member 테이블의 id를 참조한다. 사실 Member 테이블에서는 Store의 name을 그냥 가지고 있다. 그 때에는 Store을 생성할 예정이 없었기 때문에(그렇다... 나의 작고 귀여운 gs25 프로젝트는 그때그때 하나씩 열심히 추가되는 중이다) 그런 것이 없었다. 말이 나온 김에 거기도 수정하자.

Member 테이블에서는 오히려 Store을 삭제했다. 한 점장이 여러 지점을 운영할 수 있으니까.

기존에 생성한 모델을 수정하려면, mysql에서 database를 삭제하고 새로 생성한 후, 각 app에 있는 migration 파일들(0001들)을 삭제한다. 그리고 나서 다시 makemigrations와 migrate하면 된다.

무사히 makemigrations와 migrate를 마친 것처럼 보이지만, 사실 그렇지 않다.


만났던 IMPORT ERROR

ImportError: cannot import name 'Member' from partially initialized module 
'members.models' (most likely due to a circular import)

오잉? circular import가 뭔가 싶어서 찾아봤더니 두 model이 서로를 import하면, 먼저 Member의 모델을 열었다가 Store의 모델을 import하러 가고, Store의 모델을 열었더니 Member의 모델을 import하러 가야 해서 순환하는 circular import error가 생긴다고 한다. 그래서 Member에서 Store를 import하지 않게 수정하고 나니 무사히 migrate되더라.

일단 데이터베이스를 새로 만들었으니 member를 1명 생성해 주자.


POST view 작성

이제 view를 작성해 보자. members의 view에서는 member가 가입하고 로그인할 수 있다. stores의 view에서는 GET Method로 매장 목록을 출력하고, POST Method로 store를 등록할 수 있다.

(사실 생각해보면 member로 가입하고 동시에 store까지 등록하는 게 맞을 것 같지만, 한 점장이 여러 지점을 내기 위해서 두 기능을 분리할 것이다.)

그리고 쿼리 파라미터와 패쓰 파라미터를 위해 검색 GET과 한 store의 정보를 전달하는 GET을 만들 건데, 그건 일단 등록과 전체 목록 출력을 마친 후에 아래에서 진행할 것이다.


먼저 등록을 해 보자.

먼저 request.body에서 데이터를 받아서 member가 존재하는지 확인한 후 존재한다면 해당 member_id를 점장으로 가지는 데이터를 생성한다.

url 작성

마지막으로 프로젝트의 urls.py에 앱으로 연결되도록 url을 설정해 주고, stores 앱의 urls.py에서 금방 작성한 view로 연결되도록 url을 설정한다.

일단 StoreView 하나에 POST, GET Method를 전부 작성할 예정이니 url은 따로 지정해주지 않는다. 검색 GET과 각 store의 세부사항을 볼 수 있는 GET은 다른 view에 생성할 거고.


서버 요청 보내기

postman으로 데이터를 넣어 보자.

무사히 생성되는 것을 확인할 수 있다.
출력은 리스트로 하고 싶으니 데이터를 5개정도 넣었다.




GET view 작성

아무 데이터를 원하지 않는 전체 출력 view다. GET은 postman뿐만 아니라 주소창에 입력하는 것으로 요청을 보낼 수 있으니 사이트를 캡쳐해 보았다.
json을 읽을 수 있는 크롬 익스텐션을 추가해 두었다.

오케이!




글이 너무 길어져서, GET Method에서 데이터를 전달받는 방법은 다음 포스팅에서 이어가도록 하겠다.

profile
DA DA DA

0개의 댓글