저번 글에서 기본적인 데이터 처리 기능 4가지인 Create/Read/Update/Delete에 대해서 알아보았는데 view.py 내부에 함수를 만들어보며 생기는 문제, 시각적 이미지를 알아보자.
목차
1. 사전 준비
2. Read / Create
3. redirect()
4. POST method
5. CSRF
1. 사전 준비
앞서 배웠던 경로 설정 및 base 템플릿 작성을 해보고 시작하자
- base 템플릿 작성
- bootstrap CDN 및 템플릿 추가 경로 작성
- URL 분리 및 연결
- index 페이지 작성
index 페이지 작성 순서와 같이 항상 urls -> views -> templates의 순서를 지키면서 작성하자!!
2. READ / CREATE
# READ 1(index page)
index page에서는 전체 게시글을 조회해서 출력하는데 앞서 urls는 작성해주었으므로 view 함수와 index를 작성해준다.
# CREATE
create 로직을 구현하기 위해서는 과연 몇 개의 view 함수가 필요할까?
- 사용자의 입력을 받을 페이지를 렌더링 하는 함수 1개
- "new" function
- 사용자가 입력한 데이터를 전송받아 DB에 저장하는 함수 1개
- "create" view function
new
우선 new function을 적용시켜주기 위해 url 작성을 해준다.
페이지를 렌더링하는 것이 목적이므로 "new.html"로 정보를 바로 넘겨주자.
내가 생성할 정보들의 목록을 아래와 같이 Type과 함께 작성해주고, 뒤로 가기 위한 하이퍼링크를 작성해주는데 앞서 배웠듯이 "app name:url name"으로 작성해준다.
하지만 아직 action 칸이 채워져 있지 않아 생성이 되지 않을 것이다!! 아래 create를 통하여 DB에 저장을 해주자
create
마찬가지로 항상 url부터 작성해준다.
그 이후 작성을 해주는데 데이터를 생성하는 3가지 방법 중 어떤 것을 사용하여도 괜찮으나 1번과 2번의 경우 꼭!!!! .save()를 해주어야 DB에 저장된다는 것을 잊지 말자.
또한 여기서 2번째 방법을 사용한 이유는
- 3번째와 같이 create 메서드가 더 간편해 보이지만 추후 데이터가 저장되기 전에 유효성 검사 과정을 거치게 됨
- 이때, 유효성 검사가 진행된 후에 save 메서드가 호출되는 구조를 택하기 위해서이다.
게시글을 작성한 후 확인해보자!
이제는 action을 통하여 데이터를 보낼 곳이 생겼으므로 작성이 잘 되었을 것이다.
원하는 결과가 나왔는지 index 페이지에 렌더링 하기 위하여 view 함수 내부에 return render(request, 'articles/index.html')로 수정해주었다.
하지만 index 페이지에 돌아가서 확인해보면 아래와 같은 문제가 발생한 것을 확인할 수 있다.
- 게시글 작성 후 index 페이지가 출력되지만 게시글은 조회되지 않음
- create함수에서 index.html 문서를 렌더링 해주기 위해 수정하는 과정에서 context 데이터와 함께 렌더링 하지 않았기 때문이다.
- index 페이지 url로 다시 요청을 보내면 해결된다!
- 게시글 작성 후 URL은 여전히 create에 머물러 있다.
- index view 함수를 통해 렌더링 된 것이 아니기 때문
- 즉, index view 함수의 반환 값이 아닌 단순히 index 페이지만 render 된 것이다.
3. Django shorcut function - "redirect()"
- 인자에 작성된 곳으로 요청을 보낸다.
- 사용 가능한 인자
- view name (URL pattern name)
- absolute or relative URL
# 1.
return redirect('articles:index')
# 2.
return redirect('/articles/')
- 따라서 view 함수 내부의 수정해주었던 return render(..)을 삭제하고 아래와 같이 재작성해준다.
게시글을 작성한 후에 터미널 로그를 확인하면 url이 달라진 것을 볼 수 있다.
- 동작 원리
- 클라이언트가 create url로 요청을 보냄
- create view 함수의 redirect 함수가 302 status code를 응답
- 응답받은 브라우저는 redirect 인자에 담긴 주소(index)로 사용자를 이동시키기 위해 index url로 Django에 재요청
- index page를 정상적으로 응답 받음 (200 status code)
# 참고
302 Found
- HTTP response status code 중 하나
- 해당 상태 코드를 응답받으면 브라우저는 사용자를 해당 URL의 페이지로 이동 시킴
HTTP response status code
- 클라이언트에게 특정 HTTP 요청이 성공적으로 완료되었는지 여부를 알려줌
- 응답그룹 5개
- Informational responses (1xx)
- Successful responses (2xx)
- Redirection messages (3xx)
- Client error responses (4xx)
- Server error responses (5xx)
4. POST method
HTTP method GET 재검토
- 현재는 게시글이 작성될 때 /articles/create/?title=11&content=22와 같은 URL로 요청이 보내짐
- GET은 쿼리 스트링 파라미터로 데이터를 보내기 때문에 url을 통해 데이터를 보냄
- 하지만 현재 요청은 데이터를 조회하는 것이 아닌 작성을 원하는 요청
- GET이 아닌 다른 HTTP method를 알아보기
HTTP request method
- HTTP는 request method를 정의하여, 주어진 리소스에 수행하길 원하는 행동을 나타낸다.
- GET
- 특정 리소스를 가져오도록 요청할 때 사용
- 반드시 데이터를 가져올 때만 사용해야 함
- DB에 변화를 주지 않음
- CRUD에서 R 역할을 담당
- POST
- 서버로 데이터를 전송할 때 사용
- 서버에 변경사항을 만듦
- 리소스를 생성/변경하기 위해 데이터를 HTTP body에 담아 전송
- GET의 쿼리 스트링 파라미터와 다르게 URL로 보내지지 않음
- CRUD에서 C/U/D 역할을 담당
# 적용하기
- 실제 네이버에서 로그인 부분을 확인해보면 GET이 아닌 POST를 사용하고 있는 것을 볼 수 있다.
- 검색에서 GET을 사용한 이유가 뭘까?
- 검색은 서버에 영향을 미치는 것이 아닌 특정 데이터를 조회만 하는 요청이기 때문
- 특정 페이지를 조회하는 요청을 보내는 HTML의 'a tag' 또한 GET을 사용
- GET -> POST로 코드를 변경한 후 URL을 확인해보자. 쿼리 스트링 파라미터가 없어진 것을 볼 수 있다.
- 403 Forbidden 응답을 받았지만 이는 나중에 확인하고 요청된 URL(/articles/create/)을 확인
- 개발자 도구 - NETWORK 탭 - Payload 탭의 Form-Data 확인
- 데이터의 담긴 위치가 바뀌었기 때문에 view함수에서도 수정이 필요하다.
정리
- GET은 단순히 조회하려는 경우
- POST는 서버나 DB에 변경을 요청하는 경우
# 참고
403 Forbidden
- 서버에 요청이 전달되었지만, 권한 때문에 거절되었다는 것을 의미
- 서버에 요청은 도달했으나 서버가 접근을 거부할 때 반환됨
- 즉, 게시글을 작성할 권한이 없다 -> Django 입장에서는 "작성자가 누구인지 모르기 때문에 함부로 작성할 수 없다"라는 의미
- 모델(DB)을 조작하는 것은 단순 조회와 달리 최소한의 신원 확인이 필요하기 때문
5. CSRF
- Cross-Site-Request-Forgery
- "사이트 간 요청 위조"
- 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 하여 특정 웹페이지를 보안에 취약하게 하거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법
- 실제 사례 - 2008년 옥x 개인정보 해킹 사건
- 해커가 옥x 운영자에게 CSRF 코드가 포함된 가짜 사이트가 담긴 이메일을 보냄
- 관리자는 해당 사이트에 정보를 입력하여 관련 정보가 해커에게 보내졌고, 해커는 관리자 권한을 얻어냄
CSRF 공격 방어
- "Security Token 사용 방식 (CSRF Token)"
- 사용자의 데이터에 임의의 난수 값(token)을 부여해 매 요청마다 해당 난수 값을 포함시켜 전송시키도록 함
- 이후 서버에서 요청을 받을 때마다 전달된 token 값이 유효한지 검증
- 일반적으로 데이터 변경이 가능한 POST, PATCH, DELET Method 등에 적용
- Django는 DTL에서 csrf_token 템플릿 태그를 제공
csrf_token 템플릿 태그
- 해당 ㄷ태그가 없다면 Django 서버는 요청에 대해 403 forbidden으로 응답
- 템플릿에서 내부 URL로 향하는 Post form을 사용하는 경우에 사용
- 외부 URL로 향하는 POST form에 대해서는 CSRF 토큰이 유출되어 취약성을 유발할 수 있기 때문에 사용해서는 안됨
- 태그 작성 후 확인해보면 input type이 hidden으로 작성되며 value는 Django에서 생성한 hash 값으로 설정
- 마지막으로 게시글을 작성하고 문제없이 저장되는지 확인해보자
- "csrf_token은 해당 POST 요청이 내가 보낸 것 인지를 검증하는 것"
'Back-end > Django' 카테고리의 다른 글
[Django] Form (1) | 2022.09.06 |
---|---|
[Django] CRUD_with_view_functions2 + Admin (0) | 2022.09.05 |
[Django] QuerySet API (0) | 2022.09.04 |
[Django] Model (0) | 2022.09.04 |
[Django] NameSpace (0) | 2022.09.03 |