Two Scoops of Django - 1. 코딩 스타일

castlemin·2022년 6월 10일
0

Two Scoops of Django

목록 보기
2/4
post-thumbnail

1. 코딩 스타일



1.1 읽기 쉬운 코드를 만드는 것이 왜 중요한가

코드는 한번 작성하면 후에도 나를 비롯한 다른 이들에 의해 여러 번 읽힌다는 특성이 있습니다.
때문에 가독성이 좋고 이해하기 쉬운 코드는 이를 읽는 개발자들의 수고를 덜고, 프로젝트 규모에 상관없이 유지 관리가 쉬워지며, 프로젝트를 개선하기 위한 작업 또한 훨씬 수월하게 합니다.
우리는 가독성 좋은 코드를 위해 다음과 같은 노력을 할 필요가 있다.

  • 축약적이거나 함축적인 변수명은 피한다.
  • 함수 인자의 이름들은 꼭 써 준다.
  • 클래스와 메서드를 문서화한다.
  • 코드에 주석은 꼭 달도록 한다.
  • 재사용 가능한 함수 또는 메서드 안에서 반복되는 코드들은 리팩터링을 해둔다.
  • 함수와 메서드는 가능한 한 작은 크기를 유지하며, 어림잡아 스크롤 없이 읽을 수 있는 길이가 적합하다.

    내가 쓴 코드를 1년 후에 봐도, 어제 작업하던 코드처럼 쉽고 빠르게 이해할 수 있을까요?




1.2 PEP 8

PEP8은 파이썬 공식 스타일 가이드입니다. 장고 프로젝트의 파이썬 파일들도 이 가이드를 따르는 것 역시 좋은 선택지입니다. (https://peps.python.org/pep-0008/)
PEP8 가이드에는 다음과 같은 사항들을 포함합니다.

  • 들여쓰기는 스페이스를 4칸 이용한다.
  • 최상위 함수와 클래스 선언 사이를 구분 짓기 위해 두 줄을 띄운다.
  • 클래스 안에서 메서드들을 나누기 위해 한 줄을 띄운다.
  • 한 줄당 79글자를 넘어서는 안 된다.
  • 패키지명은 모두 소문자이며, 권장되지는 않지만 _를 사용할 수 있다.
  • 모듈명은 오직 소문자와 _로 구성되어야한다.
  • 클래스명은 CapWords 컨벤션을 따른다.
  • 변수명과 함수명은 오직 소문자만을 사용하며 구분을 위해 _를 사용한다.

vscode 등과 같은 코드편집 프로그램에 존재하는 lint 플러그인을 활용하거나, flake8을 이용하는 것도 좋은 방법입니다.
만약 참여중인 프로젝트에 기존 관례가 존재한다면 해당 관례를 따르도록 합니다.




1.3 임포트(import)에 대해

PEP8은 import를 할 때 다음과 같은 순서로 그룹을 지을 것을 제안합니다.
1. 표준 라이브러리 import
2. 연관 외부 라이브러리 import
3. 로컬 어플리케이션 또는 라이브러리에 한정된 import

그렇다면 장고 프로젝트에 이를 적용하면 어떻게 될까요?
장고 프로젝트에서 import 순서는 다음과 같습니다.
1. 표준 라이브러리 import
2. 코어 장고 import
3. 장고와 무관한 외부 앱 import
4. 프로젝트 앱 import

# 표준 라이브러리 import
from __future__ import absolute_import
from os.path import abspath
# 코어 장고 import
from django.db import models
from django.utils.translation import ugettext_lazy as _
# 서드 파티 앱 import (django_extensions는 custom extension입니다.)
from django_extensions.db.models import TimeStampedModel
# 프로젝트 앱 import (splits가 프로젝트의 app입니다.)
from splits.models import BananaSplit

(*실제로 import문에 group을 명시하기 위해 주석을 달 필요는 없습니다. 띄어쓰기를 이용하거나 그대로 line을 붙여서 작성하면 됩니다.)




1.4 명시적 성격의 상대 임포트(import) 이용하기

코드를 작성할 때 코드들을 다른 곳으로 이동시키거나 이름을 변경하거나 버전을 나누는 등의 재구성을 손쉽게 할 수 있도록 구성하는 것은 매우 중요합니다.
파이썬의 경우 명시적 상대 임포트(explicit relative import)를 통해 도움을 받을 수 있으며, 파이썬 패키지인 장고 또한 마찬가지입니다.

더 구체적인 이해를 위해서 우리는 파이썬이 제공하는 import의 종류를 알아야 할 필요가 있습니다.

type코드설명용도
절대(absolute)from core.views import FoodMixinimport할 모듈(views)의 절대적인 위치(core.views)를 지정하여 import외부패키지(앱)의 모듈을 현재 모듈에서 이용할 때
명시적 상대(explicit relative)from .models import WaffleCone같은 패키지내의 import할 모듈(WaffleCone)을 상대적인 위치(.WaffleCone)을 이용하여 import같은 패키지 내의 다른 모듈을 현재 모듈에서 이용할 때
암묵적 상대(implicit relativefrom models import WaffleCone같은 패키지내의 import할 모듈(WaffleCOne)을 특정한 위치 기입 없이 import같은 패키지 내의 다른 모듈을 현재 모듈에서 이용할 때

직관적으로 설명하면, 패키지(package)는 파이썬 파일들이 모인 집합(폴더)이고 모듈은 각각의 파이썬 파일입니다.

파이썬 3.3 버전 이후로 implicit relative import는 "기능적으로" 사용할 수 없습니다.

import의 종류를 알아보았으니 관련 예시를 살펴봅시다.

# 잘못된 예시
#cones/views.py

from django.views.generic import CreateView
# cones 패키지에 하드 코딩된 암묵적 상대 임포트가 이용되었다.
from cones.models import WaffleCone
from cones.forms import WaffleConeForm
from core.views import FoodMixin

class WaffleConeCreateView(FoodMixin, CreateView):
	model = WaffleCone
    form_class = WaffleConeForm

위의 예시는 잘못된 예시입니다.
cones 패키지 내부에 있는 views 모델에서, 동일한 cones 패키지에 있는 models와 forms 모듈을 import할 때 하드코딩된 암묵적 상대 임포트가 이용되었습니다.
물론 위와 같은 코드는 정상적으로 작동되지만, 이렇게 하드 코딩된 임포트 문들은 수정 시 모든 구문을 일일이 바꿔주어야 해 이식성 면에서나 재사용성 면에서 문제가 됩니다.

그렇다면 올바른 예시는 이를 어떻게 바꾸어야할까요?

# 올바른 예시
#cones/views.py

from django.views.generic import CreateView
# cones 패키지에 하드 코딩된 암묵적 상대 임포트가 이용되었다.
from .models import WaffleCone
from .forms import WaffleConeForm
from core.views import FoodMixin

class WaffleConeCreateView(FoodMixin, CreateView):
	model = WaffleCone
    form_class = WaffleConeForm

cones패키지(계층)를 .의 형태로 대체하여 명시적 상대 import를 이용한 임포트 문으로 바꾸었습니다. 이를 통해 기존에 존재하던 이식성과 재사용성 면에서의 문제가 해소되었습니다.




1.5 import * 는 피하자

모듈을 import 할 때에는 반드시 이를 개별적으로 import 해야합니다.
예시를 통해 자세히 살펴봅시다.

from django.forms import *
from django.db.models import *

위와 같이 import 문을 작성할 경우, 장고의 forms 라이브러리와 models 라이브러리 양쪽에서 CharField를 import하게 됩니다. 위의 경우 후에 import된 models의 CharField가 먼저 import 된 forms의 CharField를 덮어써 버립니다.
때문에 import * 형태의 임포트 문을 지양하고 개별적으로 모듈을 import해야 합니다.

from django import forms
from django.db import models

# 아래와 같이 import한 모듈을 CharField 앞에 작성함으로써 두 CharField가 구분된다.
form_CharField = forms.CharField()
model_CharField = models.CharField()

from django.forms import CharField
from django.db.models import CharField
위 예시처럼 같은 이름으로 여러 모듈을 import하는 것 역시 지양해야 합니다.




1.6 장고 코딩 스타일

1.6.1 장고 스타일 가이드라인

장고는 공식적인 코딩 스타일은 없지만 PEP8을 확장한 일반적으로 널리 통용되는 장고만의 스타일 가이드라인이 존재합니다.

해당 책은 장고 1.8v을 기준으로 작성되었고, 현재(4.0v)는 장고 공식문서에 코딩스타일이 명시되어 있습니다. 이를 읽고 공부하면 좋을 것 같습니다.
https://docs.djangoproject.com/en/4.0/internals/contributing/writing-code/coding-style/

1.6.2 URL 패턴 이름에는 대시(-) 대신 밑줄(_)을 이용한다.

해당 내용에 대해서 책의 내용을 그대로 받아들이기는 위험하다고 생각합니다.
책은 장고 1.8v를 기준으로 작성되었으나, 현재 장고는 4.0v까지 개발되었습니다.
책에서 언급된 url() 함수는 path()함수로 변경되었으며, 장고 공식문서의 예제에서 URL 패턴의 이름에 대시(-)가 사용되었습니다.

또한, 장고의 공식문서에서는 URL 패턴 이름에 제약 없이 원하는 문자열(string)을 입력해도 된다고 언급되어 있습니다. (https://docs.djangoproject.com/en/4.0/topics/http/urls/#naming-url-patterns)

때문에 진행하는 프로젝트의 컨벤션을 따르거나, 만약 프로젝트를 시작하는 경우라면 가독성에 주의를 기울여 자체적인 컨벤션을 설정하는 편이 좋을 것이라 생각됩니다.

다만, 본 책의 저자가 대시(-) 대신 밑줄(_)을 권장하는 이유는 해당 방식이 더 파이썬답고(아마 PEP8을 더 충족한다는 의미) 전반적인 통합 개발환경과 텍스트 편집기에 최적화된 스타일이기 때문이라고 합니다.

저자의 생각과 다른 대시(-) 사용에 대한 좋은 글을 첨부하며, 해당 글을 저자는 검색엔진 최적화를 위해 대시(-) 사용을 권장합니다.
(https://pyphilly.org/hyphen-and-underscores-when-use-each-django-and-python/)

URL 이름이 아닌 장고 템플릿에서 사용하는 URL pattern 이름입니다!

1.6.3 템플릿 블록 이름에 대시 대신 밑줄을 이용한다

템플릿 블록을 정의하는 이름을 만들 때 대시(-) 대신 밑줄(_)을 이용하도록 합니다.
이는 위에 언급한 URL 패턴 이름에 대시 대신 밑줄을 사용하는 이유와 같습니다.




1.7 자바스크립트, HTML, CSS 스타일 선택하기

파이썬과 달리 자바스크립트, HTML, CSS는 공식적인 스타일 가이드가 없습니다.
때문에 구글, 에어비앤비 등에서 작성한 널리 통용되는 가이드라인 중 하나를 선택하여 일관성있는 스타일로 코드를 작성함을 권장합니다.




1.8 특정 통합개별환경(IDE)이나 텍스트 편집기에 종속되는 스타일의 코딩은 지양한다.

특정 통합개발환경(IDE)의 기능이나 텍스트 편집기에 기반하여 프로젝트의 기본 뼈대와 구현을 결정하면, 다른 개발 도구를 이용하는 개발자들과 코드를 서로 이해하는데 큰 어려움을 겪게 됩니다.
때문에 메모장이나 나노(Nano)와 같은 매우 기본적인 기능의 텍스트 편집기를 이용하는 사람도 작업 내용과 코드 위치를 금방 찾을 수 있게 프로젝트 구조를 투명하고 명료하게 해주어야 합니다.

이를 돕기 위한 방법 중 하나로서 작가는 <app이름>_tags.py 와 같은 모듈 작명법을 추천합니다.




요약

이번 챕터에서 우리는 더 좋은 파이썬 및 장고 프로젝트를 위한 코딩 스타일에 대해 알아보았습니다.
다만, 책에서 다루는 장고의 버전(1.8)이 본 포스트가 작성된 2022년의 최신 버전(4.0)과 차이가 있는 것처럼 책에서 언급된 코딩스타일 역시 현재 개발사나 커뮤니티에서 권장하는 코딩스타일과 다를 수 있습니다.
때문에 책에서 다루는 코딩스타일을 무조건 정답으로 여기기보다는 선택적이고 유연하게 받아들일 필요가 있습니다.

본 책의 저자가 전달하고 싶은 가장 핵심적인 가치는, 같은 코드를 서로 다른 환경의 개발자들이 각자 다른 시기에 보더라도 그 해석이 용이한 뛰어난 가독성의 코드를 작성해야 한다는 것입니다.
코딩스타일은 절대적인 것이 아닌 이를 달성하기 위한 수단이며 같은 프로젝트를 진행하는 개발자들이 지켜야 할 규칙이 되는 겁니다.



본 포스트는 "Two Scoops of Django" 를 기반으로 작성되었습니다.
공부하며 새롭게 배운 내용 위주로 작성하여 책의 부분적인 내용만을 포함합니다.

profile
우보천리

0개의 댓글