두숟갈 스터디 - 6
무엇을 공부했나요?
이번 시간에는 지난 시간에 이어 Two Scoops of Django 8~9장 내용을 살펴보았습니다.
- 8장 함수기반 뷰와 클래스 기반 뷰
- 9장 함수 기반 뷰의 모범적인 이용
진홍님께서 8장을, 문수(미주)님께서 9장 요약 자료를 준비하였고, 남홍님께서 심화 자료를 준비하여 이번 스터디를 진행하였습니다.
이번 스터디부터 본격적으로 Django에 대해 다룬다는 느낌이 들었고, 어떻게 보면 난이도가 조금 올라간 듯 한 내용들도 보였습니다. 스터디 내 대략적으로 뷰에 대해 심도있게 살펴보았는데요. 이제 간단하게 스터디 내용들을 살펴볼까요?
8장 함수 기반 뷰와 클래스 기반 뷰
- 함수 기반 뷰와 클래스 기반 뷰를 각각 언제 이용할 것인가?
- 클래스 뷰로 구현했을 때 더 복잡해 지는 경우, 커스텀 에러 뷰들에 대해서만 함수기반 뷰 이용
- 클래스 기반 뷰나 함수 기반 뷰나 무엇을 사용해도 전혀 문제될 것은 없다.
- URLConf로부터 뷰 로직 분리하기
- 뷰와 URL의 결합은 최대한의 유연성을 제공하기 위해 느슨하게 구성되어야 한다.
- 뷰와 url 모델 사이에 단단하게 결합이 되어있으면 재사용이 어렵다.
- 같거나 비슷한 인자들이 반복되는 작업을 하지말라.
- URL들의 무한한 확장성이 파괴되어 클래스 상속이 불가능 하게 된다.
- 뷰와 URL의 결합은 최대한의 유연성을 제공하기 위해 느슨하게 구성되어야 한다.
- URLConf에서 느슨한 결합 유지하기
- 반복되는 작업 하지 않기
- 느슨한 결합
- 상속이 가능, 무한한 유연성 제공
- 가능한 한 단어
- 함수 기반 뷰를 사용해도 URLConf로부터 뷰 로직을 분리하자.
- URL 이름공간은 앱레벨 또는 인스턴스 레벨에서의 구분자(:)를 제공한다.
- URL 이름공간 이용하기 이름을 짧고 명확하고, 반복되는 작업을 피해서 작성해야 한다.
- 서드파티 라이브러리와 상호 운영성을 높이기
- URLConf에서 뷰를 문자열로 지목하지 말자
- 장고가 뷰의 함수, 클래스를 임의로 추가하여 디버그가 어려워진다.
- urlpatterns 변수의 초기값에서 공백문자열(‘’)에 대한 설명이 필요
- 뷰에서 비즈니스 로직 분리하기
- 모델 메서드, 매니저 메서드, 유틸리티 헬퍼 함수들을 이용하여 비즈니스 로직을 구현하자
- 장고의 뷰에서 표준적으로 이용되는 구조 외 비즈니스 로직은 뷰 밖으로 이동시키자.
- 장고의 뷰 함수
- 기본적으로 장고의 뷰는 HTTP를 요청하는 객체를 받아 HTTP를 응답하는 객체로 변경하는 함수이다.
# 함수로서의 장고 함수 기반 뷰
HttpResponse = view(HttpRequest)
# 수학에서 이용한 함수 식
y = f(x)
# 클래스 기반 뷰
HttpResponse = View.as_view()(HttpRequest)
- 뷰의 기본 형태들
- 함수 기반 뷰는 HTTP 메서드에 중립적이지만, 클래스 기반 뷰의 경우 HTTP 메서드의 선언이 필요하다는 것을 설명해 준다
- locals()를 뷰 콘텍스트에 이용하지 말자
- locals()를 사용하는 것은 안티 패턴이다.
- 매력적이었던 디자인이 암시적으로 변하여 뷰를 유지보수하기 복잡한 형태로 만든다
- 나쁜 예제
# 위의 함수와 아래 함수의 차이점을 찾는데 얼마나 걸리는가?
def ice_cream_store_display(request, store_id):
store = get_object_or_404(Store, id=store_id)
date = timezone.now()
return render(request, 'melted_ice_cream_report.html', locals())
def ice_cream_store_display(request, store_id):
store = get_object_or_404(Store, id=store_id)
now = timezone.now()
return render(request, 'melted_ice_cream_report.html', locals())
- 명시적인 컨텐츠를 이용한 뷰
def ice_cream_store_display(request, store_id):
return render(request, 'melted_ice_cream_report.html', dict{
'store' : get_object_or_404(Store, id=store_id),
'now' : timezone.now()
})
9장 함수 기반 뷰의 모범적인 이용
- 함수 기반 뷰의 장점
- 함수 기반 뷰의 단순함은 코드 재사용을 희생하여 나온 결과
- HttpRequest 객체 전달하기
- 편리한 데코레이터
- 간편표기벅 : 표현이나 가독성을 좋게 하기 위해 프로그래밍 언어에 추가되는 문법
# 간단한 데코레이터 템플릿
import functools
def decorator(view_func):
@functools.wraps(view_func)
def new_view_func(request, *args, **kwargs):
# 여기에서 request(HttpRequest) 객체를 수정하면 된다.
response = view_func(request, *args, **kwargs)
# 여기에서 response(HttpResponse) 객체를 수정하면 된다.
return response
return new_view_func
# sprinkles/decorators.py
from functools import wraps
from . import utils
def check_sprinkles(view_func):
"""사용자가 스프링클을 추가할 수 있는지 확인한다."""
@wraps(view_func)
def new_view_func(request, *args, *kwargs):
# request 객체를 utils.can_sprinkle()에 넣는다
request = utils.can_sprinkle(request)
# 뷰 함수를 호출
response = view_func(request, *args, *kwargs)
# HttpResponse 객체를 반환
return response
return new_view_func
# view.py
from django.shortcuts import get_object_or_494, render
from .decorators import check_sprinkles
from .models import Sprinkles
# 뷰에 데코레이터를 추가
@check_sprinkles
def sprinkle_detail(request, pk):
"""표준 상세 뷰"""
sprinkle = get_object_or_404(Sprinkle, pk=pk)
return render(request,
"sprinkles/sprinkle_detail.html",
{"sprinkle": sprinkle})
- 너무 많은 데코레이터를 사용하면 코드가 난해해지므로, 수를 제한하자.
- 자세한 스터디 자료는 github에서 확인하실 수 있습니다.
심화 내용
남홍님께서 현재 장고에서 쓰이고 있는 뷰에 대해 먼저 정리를 해주셨습니다. 이후 URL, URN, URI 등을 설명해 주셨고, Explicit이 implicit보다 을 예시와 함께 설명해 주셨습니다. 이후 Decorator(장식자)에 대해 심도 깊은 내용을 설명해 주셨습니다. 이를 통해 실제 decorator가 어떻게 쓰이고 회사에서 어떤 식으로 적용 되었으며, 실제로 사용하려면 어떻게 써야하는지 알 수 있었습니다.
어땠을까?
이제 본격적으로 스터디 내용도 어려워 지는 것 같네요. 그래도 배워가는게 많고 얻어가는게 많은 것 같아서 좋았습니다. 이런 스터디를 통해서 스스로 더 발전해 나갈 수 있는 기회를 만들 수 있었으면 좋겠네요. 앞으로 쭉 지속되는 스터디가 되길 바랍니다.