-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#514] 리눅스 환경변수 profile 설정
- Loading branch information
Showing
11 changed files
with
438 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
|
||
## 1장 코딩 스타일 가이드에 대하여. | ||
|
||
### 1.1 읽기 쉬운 코드를 만드는 것이 중요 | ||
|
||
한번 작성된 코드는 여러번 읽힌다. | ||
일관된 스타일로 쓴 코드는 모든 이에게 유용한 정보가 된다. | ||
|
||
- 축약적이거나 함축적인 변수명 피하기 | ||
- 함수 인자의 이름들 꼭 써주기. | ||
- 클래스와 메서드 문서화하기. | ||
- 코드에 주석 꼭 달기. | ||
- 재사용 가능한 함수 또는 메서드 안에서 반복되는 코드들은 리팩토링 해두기. | ||
- 함수와 메서드는 가능한 한 작은 크기 유지하기. | ||
- 짧게 쓰는 것보다 의미가 확실한 함수나 변수명 사용하기. | ||
|
||
### 1.2 PEP8 | ||
|
||
PEP8은 파이썬의 공식 스타일 가이드. | ||
- 들여쓰기에는 스페이스 4칸 | ||
- 최상위 함수와 클래스 선언 사이에 두 줄 띄우기 | ||
- 클래스 안에서 메서드들끼리 한 줄 띄우기 | ||
- 기존 관례는 함부로 바꾸려 하지 말자. | ||
- 79칼럼의 제약 : 코드의 이해도를 떨어뜨리지 않는 수준의 줄 길이. | ||
|
||
코드 품질을 위해 flake8 이용하기. | ||
- PyCQA 그룹이 관리하는 flake8은 프로젝트 할 때 코딩 스타일과 코드 품질, 논리적 에러를 점검하는데 유용함. | ||
|
||
### 1.3 임포트에 대해 | ||
- 장고 프로젝트에서 임포트 순서는 다음과 같다. | ||
1) 표준 라이브러리 | ||
2) 코어 장고 | ||
3) 장고와 무관한 외부 앱 | ||
4) 프로젝트 앱 | ||
|
||
|
||
### 나의 소감 | ||
그동안 혼자 코딩할 일이 많아서 코딩 스타일 같은 부분에는 전혀 신경쓰지 못했다. | ||
그냥 기능 구현만 되면 모두 패스였다. | ||
하지만 책을 읽으면서 그동안 내가 간과하고 있던 코드의 품질 부분에 대해서 다시 한 번 생각하게 되었다. | ||
|
||
|
||
이 책에서 제시하는 팁들을 실무에서도 많이 사용할 수 있으면 좋겠다. 특히 점검 도구들.. | ||
|
||
|
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
|
||
논문 데이터 정보를 수집해야하는 업무를 하게 되었다. | ||
|
||
연구실 홈페이지 업데이트하면서 기존에 데이터화되어있지 않은 논문 데이터(html 하드코딩 되어있던)을 데이터화해야 하는데.. | ||
|
||
간단하게 홈페이지에 올라가는 데이터 200개 정도라 귀찮지 않을 거라 생각해서 별로 귀찮지 않을거라 생각했는데 예상외로 하나하나 구글에 검색해서 너무 귀찮았다. | ||
|
||
그래서 올해 2월쯤에 크롤링 프로젝트 할 때 코드를 다시 찾아보게 되었다. 파이썬도 안 익숙한데 크롤링을 하게 되어 어떻게든 기한 내에 완료하긴 한 것 같은데.. | ||
10개월 후에 보니 기억이 하나도 나지 않았다..-ㅁ- | ||
|
||
셀레니움과 BeautifulSoup 관련 내용들을 다시 찾아보고있다. | ||
|
||
|
||
셀레니움에서 크롬브라우저를 직접 띄우기 때문에 크롬 드라이버가 필요하다. | ||
|
||
일단 10개월만에 다시 열어보니 셀레니움 드라이버가 실행이 되지 않았다.. | ||
|
||
|
||
``` | ||
driver = webdriver.Chrome() | ||
``` | ||
|
||
기존 코드에서 크롬 드라이버를 호출한 부분에서 에러가 나지 않았는데 다시 실행하니 에러가 났다. | ||
|
||
|
||
에러로그 | ||
> session not created: This version of ChromeDriver only supports Chrome version 81 | ||
|
||
|
||
``` | ||
def init_driver(): | ||
global driver | ||
driver = webdriver.Chrome(ChromeDriverManager().install()) | ||
print('OK') | ||
``` | ||
|
||
|
||
내가 현재 브라우저에서 사용하는 크롬 드라이버와 크롤링 파일에서 사용하는 크롬 드라이버 버전이 안 맞음. | ||
|
||
|
||
## 해결 방법 | ||
|
||
- 크롬 드라이버를 사용하는게 아니라 크롬 드라이버 매니저를 사용하면 드라이버 버전 문제가 해결된다. | ||
|
||
> | ||
pip install webdriver-manager | ||
|
||
터미널에서 웹드라이버 설치 후 | ||
|
||
> | ||
from webdriver_manager.chrome import ChromeDriverManager | ||
|
||
드라이버 매니저 패키지의 크롬 모듈의 ChromeDriverManager 함수를 임포트시킴 | ||
|
||
|
||
> driver = webdriver.Chrome(ChromeDriverManager().install()) | ||
|
||
크롬드라이버 경로를 매니저가 직접 설치할 수 있도록 지정해주면 문제 해결. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
|
||
### 1.3 임포트에 대해 | ||
PEP8은 임포트를 할 때 다음과 같은 순서로 그룹을 지을 것을 제안한다. | ||
|
||
1. 표준 라이브러리 임포트 | ||
> | ||
from math import sqrt | ||
from os.path import abspath | ||
|
||
2. 연관 외부 라이브러리 임포트 | ||
> from django_extensions.db.models import TimeStampedModel | ||
3. 로컬 애플리케이션 또는 라이브러리에 한정된 임포트 | ||
> from splits.models import BananaSplit | ||
장고 프로젝트에서 임포트 순서는 다음과 같다. | ||
1. 표준 라이브러리 임포트 | ||
2. 코어 장고 임포트 | ||
3. 장고와 무관한 외부 앱 임포트 | ||
4. 프로젝트 앱 임포트 | ||
|
||
### 1.4 명시적 성격의 상대 임포트 이용하기 | ||
코드를 작성할 때 코드들을 다른 곳으로 이동시키거나 이름을 변경하거나 버전을 나누는 등의 재구성을 손쉽게 할 수 있도록 구성하는 것은 매우 중요한 일이다. 파이썬에서는 명시적 성격의 상대 임포트(explicit relative 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 | ||
``` | ||
|
||
물론 '콘'앱 자체는 아이스크림 프로젝트에서 별 문제없이 작동한다. 하지만 하드코딩된 임포트문들은 이식성 면에서나 재사용면에서 문제가 된다. | ||
- 얼마나 디저트를 먹었는지 기록하는 앱에서 '콘'앱을 재사용하려 한다면 어떻게 해야겠는가? 이럴 경우 이름이 서로 충돌하여 이름을 변경해야 하는 경우가 생긴다. (예를 들어 장고 앱에 'snow cone'이름의 디저트가 이미 있을 경우가 되겠다.) | ||
|
||
- 어떤 이유에서 앱의 이름을 바꾸어야 할 상황이 생겼을 때는 어떻게 해야 할까? | ||
|
||
|
||
하드코딩된 임포트 문을 이용했을 때 단지 앱의 이름을 바꿈으로써 모든 것이 해결되지는 않는다. 단순히 이름을 바꾸는 것 이외에도 모든 임포트 문을 일일이 확인해서 해당 임포트 문을 수정해야 하는 번거로운 작업이 요구된다. 단순히 앞의 예제 코드에서는 일일이 임포트 구문을 바꾸는 일이 그리 어려운 일이 아니긴 하지만, 실제 우리가 프로젝트에서 만나게 되는 코드들과 앞의 예를 비교하면 앞의 예는 지극히 단순화된 경우일 뿐이다. 게다가 실제 프로젝트에서는 추가적인 유틸리티 모듈까지 잔뜩 딸려 오게 된다. 따라서 명시적 성격의 상대 임포트를 무심히 스쳐 보내서는 안 되는 것이다. 자, 이제 하드 코딩된 임포트 구문을 포함하고 있는 좋지 않은 예제를 명시적 성격의 상대 임포트를 이용한 예제로 바꿔 보자. | ||
|
||
# cones.views.py | ||
from __future__ import absolute_import | ||
from django.views.generic import CreateViw | ||
# 'cones' 패키지 상대 임포트 | ||
from .models import WaffleCone | ||
from .forms import WaffleConeForm | ||
from core.views import FoodMixin | ||
class WaffleConeCreateView(FoodMixin, CreateView): | ||
model = WaffleCone | ||
form_class = WaffleConeForm | ||
|
||
전역/외부 임포트에 대해 로컬/내부 임포트가 지니는 또 하나의 장점은 파이썬 패키지를 하나의 코드 유닛화할 수 있다는 것이다. | ||
|
||
##### from __future__import absolute_import를 이용하자 | ||
> 파이썬 3에서는 임포트 문에 큰 개선이 이루어졌다. 이러한 개선은 다행히 파이썬 2.7 버전에서 from __future__ import absolute_import 문을 통해 이전 버전으로도 호환이 가능하게 되었다. 파이썬 3을 이용하지 않더라도 이런 유용한 기능을 이용할 수 있게 되었으며 이를 통해 뒤에 설명한 상대적인 임포트문의 사용이 가능하게 된다. | ||
다음 표에서 각기 다른 파이썬 임포트 유형과 장고 프로젝트에서 언제 어떤 임포트를 사용할지 요약해보았다. | ||
|
||
from core.views import FoodMixin : 절대 임포트 , 외부에서 임포트해서 현재 앱에 사용할 때 | ||
from .models import WaffleCone : 명시적 상대, 다른 모듈에서 임포트해서 현재 앱에서 이용할 때 | ||
from models import WaffleCon : 암묵적 상대, 종종 다른 모듈에서 임포트해서 현재 앱에서 이용할 때 쓰지만 좋은 방법은 아니다. | ||
|
||
|
||
|
||
### 1.5 import * 는 피하자 | ||
|
||
우리가 짠 99%의 코드는 각 모듈을 개별적으로 임포트 하고 있다. | ||
> from django import forms | ||
from django.db import models | ||
|
||
절대 다음과 같이 하지 말자. | ||
|
||
|
||
> | ||
안티 패턴. 절대 따라하지 말 것 ! | ||
from django.forms import * | ||
from django.db.models import * | ||
|
||
그 이유는 다른 파이썬 모듈의 이름 공간들이 현재 우리가 작업하는 모듈의 이름 공간에 추가로 로딩되거나 기존 것 위에 덮여 로딩되는 일을 막기 위해서다. 이럴경우 전혀 예상치 못한 상황이 발생하거나 심각할 경우 큰 재앙이 야기되기도 한다. 이와 관련하여 특별히 예와가 되는 경우가 '5장 settings와 requirements 파일'에 나와 있다. | ||
앞의 나쁜 예를 한번 보자. 장고 폼 라이브러리와 장고 모델 라이브러리 둘 다 CharField를 가지고 있다. 이 두 라이브러리를 암묵적으로 로딩함으로써 모델 라이브러리가 폼 버전의 클래스르 ㄹ덮어써 버린다. 이러한 현상은 파이썬 내장 라이브러리와 다른 써드 파티 라이브러리들의 중요한 기능을 덮어쓰는 원인이 되기도 한다. | ||
|
||
|
||
##### 파이썬 이름 충돌 | ||
같은 이름으로 두 개의 모듈을 임포트하면 다음 경우와 같은 문제에 봉착하게 된다. | ||
> 안티패턴: 절대 따라하지 말 것 | ||
from django.forms import CharField | ||
from django.db.models import CharField | ||
|
||
import * 구문은 마치 아이스크림 가게에 아이스크림 콘 하나를 사러와서 서른한 가지 맛 전부를 무료로 맛보게 해달라는 염치 없는 손님과 같다고 볼 수 있다. 한 두 개 정도의 모듈만 이용하기 위해 전부 임포트할 필요는 없다. | ||
또한 손님이 큰 접시를 가져와 모든 종류의 아이스크림을 한 주걱씩 담아 갔다고 한다면 그 손님은 곧 그에 따른 전혀 새로운 문제에 봉착하게 될 것이다. | ||
|
||
|
||
### 명시적 성격의 상대 임포트 이용하기 | ||
|
||
코드를 작성할 때 코드들을 다른 곳으로 이동시키거나 | ||
|
||
## 2장 최적화된 장고 환경 꾸미기 | ||
|
||
### 2.1 같은 데이터베이스를 이용하라 | ||
- 많은 개발자들이 자신의 로컬 개발 환경에서 SQLite를 이용하고 실제 운영환경에서 PortgreSQL 혹은 MySQL을 이용하는 실수를 범한다. | ||
|
||
#### 2.1.1 | ||
|
||
운영환경 데이터베이스 엔진이 로컬 개발 환경 데이터베이스 엔진과 서로 다를 때, 로컬 환경에서 구동하기 위해 운영 환경 데이터베이스의 완벽한 복사본을 가져올 수 없다. | ||
|
||
물론 운영 데이터베이스에서 SQL 덤프를 해 와서 로컬 데이터베이스 환경에 이전할 수는 있다. 하지만 그렇게 데이터베이스 익스포트와 임포트를 했다고 두 개의 데이터베이스가 완전히 같은 복사본의 데이터를 가지고 있다고 볼 수는 없다. | ||
|
||
#### 2.1.2 다른 종류의 데이터베이스 사이에는 다른 성격의 필드 타입과 제약 조건이 존재한다 | ||
|
||
#### 2.3.1 픽스처는 마법을 부리지 않는다. | ||
로컬 데이터베이스와 운영 데이터베이스 사이 차이를 없애기 위해 픽스처를 쓰면 안 되냐고 반문할 수도 있을 것이다. | ||
|
||
픽스처는 단순히 하드코딩 된 간단한 데이터세트를 생성하는 데는 좋은 도구다. 때때로 개발 환경에서 이용하기 위해 운영 데이터베이스 환경에서 가짜 데이터세트를 미리 추출할 필요를 느낄 때가 있다. | ||
|
||
하지만 픽스처는 한 데이터베이스 엔진에서 다른 데이터베이스 엔진으로 큰 크기의 데이터세트를 이전하는 데는 그다지 신뢰할만한 도구가 아니다. | ||
|
||
|
||
### 2.2 pip와 virtualenv 이용하기 | ||
|
||
그간 pip와 virtualenv를 이용하지 않았다면 이 둘에 친숙해질 필요가 있다. 이 둘은 장고 프로젝트에서 사실상의 표준이고 장고를 이용하는 대부분의 회사에서 이 둘을 매우 의존적으로 이용하고 있다. | ||
|
||
pip는 파이썬 패키지 인덱스와 그 미러 사이트에서 파이썬 패키지를 가져오는 도구다. | ||
|
||
파이썬 패키지를 설치하고 관리하는 데 이용한다. easy_install과 비슷하지만 virtualenv를 지원하는 것이 핵심 기능이다. | ||
|
||
virtualenv는 파이썬 패키지 의존성을 유지할 수 있게 독립된 파이썬 환경을 제공하는 도구다. 한 개 이상의 프로젝트를 동시에 진행하고 있을 때 프로젝트마다 각각 다른버전 번호의 라이브러리들이 서로 충돌을 내고 있는 경우 이상적으로 이용할 수 잇는 도 | ||
구다. | ||
|
||
장고 1.7로 프로젝트를 하는 도중 장고 1.8로 다른 프로젝트를 동시에 해야 하는 경우를 생각해보자. | ||
|
||
- virtualenv(또는 종속성 관리를 위한 다른 대체 도구)가 없다면 두 프로젝트를 왔다 갔다 하면서 매번 장고를 재설치해야 할 것이다. | ||
- 이러한 것이 별로 대수롭지 않게 생각된다면, 실제 장고 프로젝트 하나에는 관리해야 할 최소 수십 개의 의존적인 라이브러리가 있다는 것을 상기하고 다시 한 번 생각해보기 바란다. | ||
|
||
### 2.3 pip를 이용하여 장고와 의존 패키지 설치하기 | ||
장고 공식 문서는 다양한 장고 설치 방법을 설명하고 있다. 우리가 추천하는 방법은 pip 와 requirements 파일을 이용하는 것이다. | ||
간단히 이야기하면 requirements 파일은 설치하려는 파이썬 패키지에 대한 쇼핑 목록이다. 이 파일에는 각 패키지 이름과 설치를 원하는 버전이 담겨 있다. pip를 이용해서 이 파일에 나열되어 있는 패키지들을 가상 환경(virtual envritonment)안에 설치할 수 있다. | ||
|
||
### 2.4 버전 컨트롤 시스템 이용하기 | ||
장고 프로젝트를 시작할 때 코드의 변경 내용을 기록하려면 반드시 버전 컨트롤 시스템을 이용해야 한다. | ||
|
||
여러 도구 중 깃(Git)과 머큐리얼(Mercurial)이 장고 개발자들 사이에서는 일반적으로 가장 인기있고 널리 쓰인다. | ||
|
||
버전 컨트롤 시스템을 이용한다면 단순히 로컬 카피만 이용하는 것이 아니라 백업을 위한 호스팅 서비스 또한 이용하는 것이 그 핵심이라고 할 수 있다. | ||
|
||
|
||
### 2.5 선택 사항: 동일한 환경 구성 | ||
개발자의 노트북에서 잘 동작하던 프로젝트가 운영 환경에서는 제대로 작동하지 않을 수도 있다. 로컬 개발 환경이 프로젝트의 스테이징, 테스트, 운영 환경과 똑같다면 어떨까? | ||
운영 인프라 환경이 만여 대의 서버로 구성되어 있다면 개발을 위해 또 다른 만여 대의 서버를 구성해야 하니 운영 환경과 정말 똑같은 개발 환경이란 불가능할 수도 있다. 그래서 우리가 '똑같은'이라는 말을 할 때 이를 '가능한 한 똑같은'이라고 생각하기로 하자. 그렇다면 적어도 다음 사항들에 대해서는 환경 문제를 충분히 극복할 수 있다. | ||
|
||
- 서로 다른 운영체제: 개발은 맥이나 윈도우에서 이루어지고 운영 환경으론 우분투 리눅스가 이용된다면, 장고 앱이 로컬에서 구동되는 것과 운영 환경에서 구동되는 것 사이에는 큰 차이가 있다. | ||
- 서로 다른 파이썬 셋업 : 사실대로 이야기한다면 인정하진 않겠지만 많은 개발자와 시스템관리자들이 지금 자신이 어떤 버전의 파이썬을 쓰고 있는지 때론 오판하거나 헷갈리는 경우가 있다. 왜일까? 파이썬을 제대로 설정하고 그 셋업을 완벽히 이해하는 것은 절대 쉬운 일이 아니기 때문이다. | ||
- 개발자와 개발자 간의 차이 : 큰 규모의 팀에서는 개발자들 각각의 셋업 간 차이에서 오는 문제로 인해 디버깅에 많은 시간이 소비되기도 한다. | ||
|
||
동일한 개발 환경을 구성하기 위해 가장 흔히 이용되는 방법에는 베이그런트와 버추얼박스가 있다. | ||
|
||
#### 2.5.1 베이그런트와 버추얼 박스 | ||
베이그런트는 재생산이 가능한 개발 환경을 생성, 설정, 관리하는데 쓰는 대중적인 도구다. 베이그런트의 큰 장점은 버추얼 박스(또는 다른 VM 도구들)과 쉽게 연동된다는 점이다. | ||
|
||
개발용 노트북 컴퓨터가 OS X 인데 반해 운영 프로젝트 설정은 우분투에 종속된 환경이라면 베이그런트와 프로젝트의 Vagrantfile을 이용하여 가상의 우분투 개발환경을 로컬에서 빠르게 구성하고 프로젝트를 위한 모든 패키지 설치와 세팅을 빠르게 끝낼 수 있다. | ||
|
||
- 프로젝트 개발 팀원 모두에게 똑같은 개발 환경을 제공 | ||
- 생성된 로컬 개발 환경의 설정을 스테이징, 테스트, 운영환경과 비슷하게 설정 | ||
|
||
반면 다음과 같은 단점이 있다. | ||
|
||
참고) 도커 컨테이너를 이용하여 독립 환경 만들기 | ||
|
||
도커를 이용하는 것은 VM에서 개발하는 것과 흡사하다. 단지 좀 더 가벼운 환경이라는 점 정도가 다르다. 도커 컨테이너는 호스트 운영 체제를 나눠쓰는 것이지만 컨테이너 각각이 독립된 프로세스와 메모리 영역을 쓴다. 더 나아가 AUFS(advanced multi layered unification filesystem)을 이용하는 도커는 처음부터 빌드되는 게 아니라, 기존 스냅샷과 델타(변경된 내용)으로부터 빌드되기 때문에 그 속도가 상당히 빠르다. | ||
|
||
|
||
|
||
|
||
### 2.6 요약 | ||
이번 장에서는 동일 데이터베이스 엔진을 개발 환경과 운영 환경에서 이용하는 것과 pip, virtualenv, 버전 컨트롤 시스템에 대해 알아봤다. | ||
이 도구들은 장고 프로젝트뿐 아니라 파이썬 소프트웨어 개발 전반에 걸쳐 일반적으로 이용되는 도구들이기에 반드시 익혀두어야 할 소중한 기술들이다. |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.