재미그래밍 - 투스쿱장고
by Yoonkh
재미그래밍 180122
Two Scoop of Django
모범사례로 배우는 장고 테크닉
코딩 스타일
임포트: 절대 vs 명시적 상대 vs 암묵적 상대
코드 | 임포트 타입 | 용도 |
---|---|---|
from core.views import FoodMixin | 절대 임포트 | 외부에서 임포트해서 현재 앱에서 이용할 때 |
from .models import WaffleCone | 명시적 상대 | 다른 모듈에서 임포트해서 현재 앱에서 이용할 때 |
from models import WaffleCone | 암묵적 상대 | 종종 다른 모듈에서 임포트해서 현재 앱에서 이용할 때 쓰지만 좋은 방법은 아니다. |
명시적 성격의 상대 임포트를 이용하는 습꽌을 길러야한다.
import *
는 피하기
- 다른 파이썬 모듈의 이름공간들이 현재 우리가 작업하는 모듈의 이름공간에 추가로 로딩되거나 기존 것 위에 덮여 로딩되는 일을 막기 위해서 (이는 큰 재앙을 야기한다)
URL 패턴의 이름에는 대시(-) 대신 밑줄(_)을 이용한다.
장고 앱 디자인의 황금률
제임스 베넷(장고 코어 개발자이자 릴리스 매니저)
- “좋은 장고 앱을 정의하고 개발하는 것은 더글라스 맥얼로이의 유닉스 철학을 따르는 것이다. ‘한 번에 한 가지 일을 하고 그 한 가지 일을 매우 충실히 하는 프로그램을 짜는 것이다’.”
핵심은 각 앱이 그 앱의 주어진 임무에만 집중할 수 있어야 한다는 것이다.
어떤 앱의 성격과 기능을 한 문장으로 설명할 수 없거나 그 앱을 설명하기 위해 ‘그리고/또한’이란 단어를 한 번 이상 사용해야 한다면, 이미 그 앱은 너무 커질대로 커져 이제 여러 개로 나누어야 할 때가 되었다는 것이다.
확신 없이는 앱을 확장하지 않는다!
거대한 크기의 앱 두세 개를 구성하는 것보다는 작은 앱 여러 개를 구성하는 것이 훨씬 나은 구성이라는 사실을 항상 명심하자!
함수기반 뷰를 사용할것인가 클래스기반 뷰를 사용할것인가??의 순서도!
함수기반 뷰의 모범적인 이용
함수 기반 뷰의 가이드라인
- 뷰 코드는 작을수록 좋다!
- 뷰에서 절대 코드를 반복해서 사용하지 말자
- 뷰는 프레젠테이션 로직을 처리해야 한다.
- 뷰를 가능한 한 단순하게 유지하자!
- 403, 404, 500을 처리하는 커스텀 코드를 쓰는 데 이용하자!
- 복잡하게 중첩된 if구문을 피하자
클래스 기반 뷰의 모범적인 이용
클래스 기반 뷰의 가이드라인
- 뷰 코드의 양은 적으면 적을수록 좋다
- 뷰 안에서 같은 코드를 반복적으로 이용하지 말자
- 뷰는 프레젠테이션 로직에서 관리하도록 하자. 비즈니스 로직은 모델에서 처리하자. 매우 특별한 경우에는 폼에서 처리하자.
- 뷰는 간단 명료해야 한다.
- 403, 404, 500 에러 핸들링에 클래스 기반 뷰는 이용하지 않는다. 대신 함수 기반 뷰를 이용하자.
- 믹스인은 간단 명료해야 한다.
장고 템플릿과 Jinja2
DTL의 장점
- 이용을 위해 필요한 모든 것이 이미 장고 안에 포함되어 있으며, 장고의 문서화 시스템 안에 DTL의 기능이 훌륭하게 문서화되어 있다.
- DTL + 장고 조합은 DTL + Jinja2 조합보다 더 많이 이용되면서 검증되었고 더 성숙하다.
- 대부분의 서드 파티 장고 패키지에서 DTL을 이용하고 있다. 이를 Jinja2로 변경하려면 추가적인 작업이 필요하다.
- 많은 양의 DTL 코드를 Jinja2로 변경하는 것은 상당히 큰 작업이다.
Jinja2의 장점
- 장고와 독립적으로 이용할 수 있다.
- Jinja2 문법이 파이썬 문법에 좀 더 가깝기 때문에 많은 이들에게 Jinja2 문법이 더 직관적이다.
- 일반적으로 Jinja2가 좀 더 명시적이고 명확하게 구성되어 있다.
- Jinja2에는 로직상의 임의적 제약이 덜하다.
- 우리가 직접 경험한 바와 온라인상의 벤치마크 결과에 따르면 Jinja2가 일반적으로 더 빠르다.
그렇다면 어떤 것을 택해야 하는가?
- 장고를 처음 접하는 개발자라면 DTL을 이용해야 할 것이다.
- 이미 상당한 분량의 코드를 짠 기존 프로젝트라면 특별히 성능 향상이 필요한 몇 페이지를 제외하고는 전부 DTL을 계속 이용하는 편이 나을 것이다.
- 장고에 경험이 어느 정도 있는 개발자라면 둘 다 시도해 봄으로써 DTL과 Jinja2의 장점을 모두 경험해 본 후 최종 결정을 내릴 수 있을 것이다.
테스트는 정말 거추장 스럽고 낭비일까?
오늘 날의 장고 프로젝트에 높은 수준의 품질을 요구하는 경우
- 의료 정보와 이에 관련된 업무를 처리하는 애플리케이션
- 사람들의 생명에 연관된 리소스를 제공하는 애플리케이션
- 사람들의 돈에 관련된 업무를 처리하거나 처리할 애플리케이션
단위 테스트 작성하기
각 테스트 메서드의 테스트를 한 가지씩 수행해야 한다.
테스트 메서드는 그 테스트 범위가 좁아야 한다. 하나의 단위 테스트는 절대로 여러 개의 뷰나 모델 폼 또는 한 클래스 안의 여러 메서드에 대한 테스트를 수행해서는 안된다. 대신 하나의 테스트에서는 뷰, 모델, 폼, 메서드 그리고 함수가 작동하는 데 있어서 단 하나의 기능에 대한 정의, 즉 뷰면 뷰, 모델이면 모델 식으로 하나의 기능에 대해서만 테스트가 이루어져야 한다.
뷰에 대해서는 가능하면 요청 팩터리를 이용하자.
django.test.client.RequestFactory
는 모든 뷰에 대해 해당 뷰의 첫 번째 인자로 이용할 수 있는 요청 인스턴스를 제공한다. 이는 일반 장고 테스트 클라이언트보다 독립된 환경을 제공한다. 단지 생성된 요청이 세션과 인증을 포함한 미들웨어를 지원하지 않기 때문에 테스트를 작성할 때 약간의 추가적인 작업이 필요하다는 단점이 있다.
테스트가 필요한 테스트 코드를 작성하지 말자.
테스트는 가능한 한 단순하게 작성해야 한다. 테스트 케이스 안의 코드가 복잡하거나 추상적이라면 문제가 있다는 이야기다.
같은 일을 반복하지 말라는 법칙은 테스트 케이스를 쓰는 데는 적용되지 않는다.
setUp()
메서드는 테스트 클래스의 모든 테스트 메서드에 대해 재사용이 가능한 데이터를 만드는 데 큰 도움이 된다. 하지만 때론 비슷하긴 하지만 각 테스트 메서드에 대해 각기 다른 데이터가 필요하기도 하고 종종 이러한 이유로 기능이 화려한 테스트 유틸리티를 만드는 실수에 빠지기도 한다.
픽스쳐를 너무 신뢰하지 말자.
경험적으로 우리는 픽스처(fixture)를 이용하는 것이 오히려 더 문제를 일으킬 수 있음을 배웠다. 문제는 프로젝트의 데이터가 바뀌어 감에 따라 픽스처 자체를 유지하기가 매우 어렵다는 것이다. 최신 데이터 마이그레이션에 맞추어 JSON 포맷의 파일을 수정하는 것 자체가 어려운 작업이다.
테스트의 목적은 테스트의 실패를 찾는 데 있다.
이용자들이 자신이 쓴 아이스크림 가게 평가를 수정하는 뷰가 있다고 가정하자. 고객의 로그인, 평가를 변경하고자 하는 고객의 시도, 그리고 실제로 평가를 수정했는지에 대한 확인 등이 명확한 테스트 케이스가 될 것이다. 그리고 테스트를 실행했더니 전부 다 성공에 도달했다. 물론 이는 테스트 시나리오의 일부에 불과한 것이다. 테스트 시나리오보다 예외적인 경우에 대한 테스트가 더욱 중요하다.
성공 시나리오에서의 실패는 사용자에게 불편을 야기하겠지만 바로 보고되는 사항들이다. 반면 실패 시나리오에서의 실패는 인지하지도 못하는 보안상의 문제점을 만들어 내고, 이러한 문제들이 발견되었을 때는 이미 너무 늦은 경우가 허다하다.
장고 프로젝트 배포하기
기업이나 빠르게 성장하는 스타트업의 경우 PaaS 서비스를 이용할 생각이 없다면 일반적으로 다중 서버 구성을 하게 된다.
다중 서버 구성의 예
- 데이터베이스 서버: 선택의 여지가 있다면 우리는 일반적으로 PostgreSQL을 이용한다.
- WSGI 애플리케이션 서버: 일반적으로 uWSGI나 구니콘에 Nginx를 연동하거나 아파치와 mod_wsgi를 이용한다.
모든 일시적 데이터에는 레디스를 이용하자!
레디스는 다음의 기능을 제공한다.
- 인증절차: Memcached에선 기본적으로 지원하지 않는다.
- 상태 저장: 서버가 재시작되더라도 데이터가 손실되지 않는다.
- 더 많은 데이터 타입: 더 많은 데이터 타입을 지원한다는 것은 비동기 메시지 큐로서 셀러리나 rq 등과 함께 이용할 수 있다는 의미다.
빠르게 변하는 기술
자동화 배포기술은 빠르게 변화하고 있다.
날짜 | 마일스톤 | 설정 관리 도구 상황 |
---|---|---|
2011년까지 | 아주 멀고 먼 과거 | 셰프(Chef)나 퍼핏(Puppet) 선호, CFEngine등 이용 아이폰 이전 시대 |
2012년 | 이 책 작업이 시작됨 | 셰프나 퍼핏 선호, 솔트(Salt)나 앤서블은 여전히 매우 실험적인 프로젝트 |
2013년 1월 | Two Scoop of Django 1.5 알파 | 셰프와 퍼핏이 여전히 강세. 솔트나 앤서블이 인기를 얻기 시작 |
2013년 3월 | Two Scoop of Django 1.5 최종 버전 | 도커(Docker)가 오픈 소스화됨 |
2014년 1월 | Two Scoop of Django 1.6 | 솔트와 앤서블이 안정화되고 인기를 얻음. 셰프와 퍼핏은 그다지 주목받지 못함. 도커는 실험적인 프로젝트지만 빠르게 떠오름. |
2015년 3월 | Two Scoop of Django 1.8 얼리 릴리스 | 독립 환경 제공으로 도커가 많은 배포 환경으로 이용됨. 솔트와 앤서블이 강력해짐. 셰프와 퍼핏이 급격히 하락. |
2015년 6월 | Two Scoop of Django 1.8 최종 버전 | 도커의 성숙? 새로운 기술이 대두할 것인가? |
2017년 | 장고 2.2 프로젝트 릴리스 | 어떤 도구가 개로 나타날지 아직 상상이 안됨. |
2019년 | 장고 2.6 프로젝트 릴리스 | 지금 우리가 이용하는 도구들이 CFEngine처럼 지루하고 오래된 주제가 되어 있을 것이다. |
지금 현재 나와 있는 인프라 스트럭쳐 자동화 도구
도구 | 장점 | 단점 |
---|---|---|
도커 | 변경 내용만 적용하기 때문에 배포 속도가 빠르다. 컨테이너 기술, YAML 설정 파일, 커뮤니티가 크다. 오픈소스 | 고(Go)로 작성됐다. 문제가 발생했을 때 해결과정이 아직은 복잡하다. |
솔트스택 | 푸시 모드로 주로 쓰인다. 0mq를 이용하면 매우 빠른 속도를 보여준다. 온라인에서 많은 솔트 스테이트와 예제를 제공한다. 커뮤니티가 크다. 오픈소스, 파이썬으로 작성. | 복잡하다. 문제가 생겼을 때 해결 과정이 아직은 복잡하다. |
앤서블 | 푸시 모드로 주로 쓰인다. OpenSSH 이외에 원격 서버에 데몬을 필요로 하지 않는다. 배우기가 쉽다. YAML 설정, 오픈소스, 파이썬으로 작성. | SSH를 이용할 경우 속도가 느리다. 하지만 파이어볼(Fireball)모드라는 임시 0mq 데몬을 이용할 수 있다. 문제가 생겼을 때 해결 과정이 아직은 복잡하다. |
셰프 | 다양한 레시피를 제공한다. 커뮤니티가 크다. 오픈소스. | 학습 곡선이 가파르다. 루비로 작성됐다. 레시피들도 루비로 작성된다. 너무 복잡하다. |
퍼핏 | 커뮤니티가 크다. 오픈소스. | 학습 곡선이 가파르다. 루비로 작성됐다. 커스텀 DSL로 이루어진 설정, 때론 이 커스텀 DSL 때문에 문제가 생길 수도 있다. |
Subscribe via RSS