(ํ์ด์ฌ์ผ๋ก) ํ๋ก์ ํธ ์์ํ ๋ ํ์ํ ๊ฒ๋ค
ย
July. 4, 2020
@DoonDoony
๐จ Basic Project Settings
๐ณ Docker Settings
๐ Workflow Settings
๐ HOW TO START (PYTHON) PROJECT
WHAT TO MAKE
๐ฅย ย ๋ ๋ฆฝ๋ ํ์ด์ฌ ๋ฐํ์ ์ฌ์ฉ์ ์ํ ํ์ด์ฌ ๊ฐ์ํ๊ฒฝ ์ค์
๐ธย ย ์ข ๋ ์์ ์ปค๋ฐ ๋ฉ์์ง๋ฅผ ๋ง๋๋ gitmoji
๐จย ย ๋์ผํ ์ฝ๋ ์ปจ๋ฒค์ ์ ์งํฌ ์ ์๋๋ก ์ฝ๋ ํฌ๋งคํฐ
๐ ย ย ์ฌ๋ฐ๋ฅธ ์ฝ๋ ์์ฑ์ ์ํ ์ ์ ํ์ ๋ถ์๊ธฐ
๐ฆย ย ์ต์ ํจํค์ง ๋งค๋์ ๋ฅผ ํตํ ํ๋ก์ ํธ ๊ด๋ฆฌ
๐ย ย ๋ณด์/๋ฏผ๊ฐ ์ ๋ณด๋ฅผ ๋ ธ์ถํ์ง ์๊ณ ๊ด๋ฆฌ
โ๏ธย ย ์ด์ ํ๊ฒฝ ๊ฐ๊ฐ์ ์ค์ ํ์ผ ๊ด๋ฆฌ
๐ HOW TO START (PYTHON) PROJECT
WHAT TO MAKE
๐ณย ย ๋น ๋ฅธ ์จ๋ณด๋ฉ๊ณผ ์ผ๊ด๋ ๊ฐ๋ฐ ํ๊ฒฝ ๊ตฌ์ถ์ ์ํ ๋์ปค ์ค์
โ ย ย ์ต์ํ์ CI ํ๊ฒฝ ๊ตฌ์ถ
๐ย ย ์ฝ๋๋ก CD ํ๊ฒฝ ๊ด๋ฆฌํ๊ธฐ (w/ Fabric)
๐ทย ย Git tag ๊ฐ๋จํ๊ฒ ์ฌ์ฉํด๋ณด๊ธฐ
๐ฉโ๐ปย ย ์ ๋ฌด๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ฃผ๊ด์ ์ธ ์ ๋ต (Work Flow)
๐ HOW TO START (PYTHON) PROJECT
Oh, Why?
๋ค์ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค ๋ On-Boarding ๋น์ฉ์ด ์ ๊ฐ๋ฉ๋๋ค
์ฌ์ํ ๋ฌธ์ ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ๊ฒฌํ๊ณ , ์ต๋ํ ์๋์ผ๋ก ํด๊ฒฐ๋๋๋ก ํ ์ ์์ต๋๋ค
์คํ์์ค์ ํ๋ก์ ํธ ๊ตฌ์ฑ์ ๋ํด ์ดํดํ ์ ์์ต๋๋ค (์ธ์ด/ํ๋ ์์ํฌ๋ณ ์์ด)
๋ค๋ฅธ ์ฌ๋๊ณผ ํ์ ํ ๋ ๊ท์น์ ๊ฐ์ง๊ณ ์ผํ ์ ์์ต๋๋ค
๊ฐ๋ฐ/์ด์์ ๋ํ ํ์คํ ๋ฆฌ ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Oh, Why?
๋ผ๊ณ ํ๋ก์ ํธ ์ธํ ๋ง ํด๋๊ณ ๋งจ๋ ์์๋ ์ํ๋ ๋ฐฉ๋ง์ด ๊น๋ ๋ ธ์ธ 2๋ ์ฐจ๊ฐ ๋งํฉ๋๋ค
Git, Python Virtual Environment, Code Formatter, Linter, ...
๐ HOW TO START (PYTHON) PROJECT
Create Virtual Env
Pyenv ๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ํ๊ฒฝ์ ์ค์ ํด์
๐ HOW TO START (PYTHON) PROJECT
Create Virtual Env (1)
# MacOS์ ๊ธฐ๋ณธ์ผ๋ก ์ค์น๋ System Python์ ๊ธฐ์ค์ผ๋ก ์ค์น๋์ด์ผ ํฉ๋๋ค
$ python --version
Python 2.7.16
# HomeBrew๋ฅผ ์ฌ์ฉํ ์ค์น๋ ๊ถ์ฅํ์ง ์์ต๋๋ค (Dependency๋ก Python3 ๋ฐํ์์ด ์ค์น๋จ)
# pyenv-virtualenv ํ๋ฌ๊ทธ์ธ ๊ฐ์ด ์ค์น๋์ด์ ์ข์ต๋๋ค
$ curl https://pyenv.run | bash
# ์๋ PATH์ Pyenv Hook์ .zshrc์ ๋ณต๋ถํด์ฃผ์ธ์
$ cat <<EOF >> .zshrc
$ export PATH="$HOME/.pyenv/bin:$PATH"
$ eval "$(pyenv init -)"
$ eval "$(pyenv virtualenv-init -)"
$ EOF
# Reloading .zshrc
$ source ~/.zshrc
# Check pyenv installation
$ pyenv --version
pyenv 1.2.18
๐ HOW TO START (PYTHON) PROJECT
Create Virtual Env (2)
# pyenv๋ฅผ ์ฌ์ฉํด์ Python 3.8.3 ์ ์ค์นํฉ๋๋ค
$ pyenv install 3.8.3
# pyenv-virtualenv ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํด์ ํ๋ก์ ํธ์ฉ ๊ฐ์ํ๊ฒฝ์ ๋ง๋ญ๋๋ค
$ pyenv virtualenv 3.8.3 creamheroes
# ์ค์น ๊ฐ๋ฅํ pyenv์ Python ๋ฒ์ ์ ๋ค์๊ณผ ๊ฐ์ด ์กฐํํฉ๋๋ค
$ pyenv install --list
# ๋ง๋ค์๋ ๊ฐ์ํ๊ฒฝ์ ๋ค์๊ณผ ๊ฐ์ด ์ ๊ฑฐํ ์ ์์ต๋๋ค
$ pyenv uninstall creamheroes
# ์ค์นํ๋ Python ๋ฒ์ ์ ๋ค์๊ณผ ๊ฐ์ด ์ ๊ฑฐํ ์ ์์ต๋๋ค
$ pyenv uninstall 3.8.3
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ๋ฅผ ๋ง๋ค๊ณ Git ์ค์ ์ ํด๋ณด์์
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
# ๋๋ ํ ๋ฆฌ ์์ฑ
~ $ mkdir -p Tutorial/creamheroes
~ $ cd Tutorial/creamheroes
# Git ์ ์ฅ์ ๋ง๋ค๊ธฐ
~/creamheroes $ git init
# Git local config๋ก Author, Email ๊ฐ ์ค์ ํ๊ธฐ
~/creamheroes $ git config --local user.name "DoonDoony"
~/creamheroes $ git config --local user.email "cream.doondoon@gmail.com"
# .gitignore ์์ฑ (https://gitignore.io API๋ฅผ ์ฌ์ฉ)
~/creamheroes $ curl https://www.toptal.com/developers/gitignore/api/macos,python,django,pycharm,git,vim > .gitignore
# pyenv ์๋ ํ์ฑํ๋ฅผ ์ํ .python-version ํ์ผ ์์ฑ
~/creamheroes $ echo 'creamheroes' > .python-version
(creamheroes) ~/creamheroes $ python --version
Python 3.8.3
# ๋๋ ๋ค์๊ณผ ๊ฐ์ด ํ์ฑํ ํ ์ ์์
~/creamheroes $ pyenv shell creamheroes
(creamheroes) ~/creamheroes $ python --version
Python 3.8.3
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
์ฌ๊ธฐ๊น์ง ์์ ํ์ผ๋๊น Commit ํ...๊ธฐ ์ ์
์ข ๋ Commit Message ๋ฅผ ์์๊ฒ ์ ๊ธฐ ์ํด
๐ธ gitmoji ๋ฅผ ์ค์นํด๋ด์
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
# NPM Global ์ค์น๋ก gitmoji-cli ์ค์น
$ npm i -g gitmoji-cli
$ gitmoji --version
3.2.6
# ํ๋ก์ ํธ ๋๋ ํ ๋ฆฌ์์
(creamheroes) ~/creamheroes $ gitmoji --init
โ Gitmoji commit hook created successfully
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
Gitmoji ์ค์นํ์ผ๋ ์ด์ ์ง์ง๋ก ์ฒซ Commit?
Commit ์ ์ ์ฌ๋ฌ๊ฐ์ง ๋ฌธ์ ๋ฅผ ๋ฏธ๋ฆฌ ๋ฐ๊ฒฌํด์ฃผ๋
pre-commit ํ ๋ ๊ฐ์ด ์ ์ฉํด๋ด์
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
# ์์คํ
์ ์ญ์ ํ์ด์ฌ ํจํค์ง ๋งค๋์ ์ธ Poetry๋ฅผ ์ค์นํฉ๋๋ค
# NOTE: ๋ฐ๋์ ์์คํ
๊ธฐ๋ณธ Python ๋ฐํ์์ผ๋ก ์ค์นํ๋๋ก pyenv ์ค์ ์ ๋ณ๊ฒฝํด์ฃผ์ธ์
$ pyenv shell system
$ python --version
Python 2.7.16
# Poetry๋ ๊ธฐ๋ณธ Python ํจํค์ง ๋งค๋์ ์ธ pip๊ฐ ์๋๋ผ, ๊ณต์ ํํ์ด์ง์์ ๊ถ์ฅํ๋ ๋ฐฉ๋ฒ์ผ๋ก ์ค์นํฉ๋๋ค
$ curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python
$ poetry --version
Poetry version 1.0.5
# ํ์ฌ ํ๋ก์ ํธ์ Poetry๋ฅผ ํ์ฑํ ํ๊ณ pre-commit์ ์ค์นํฉ๋๋ค
$ poetry init
This command will guide you through creating your pyproject.toml config.
# ...์ดํ ์๋ต
# DevDependency๋ก ์ค์นํฉ๋๋ค
$ poetry add -D pre-commit
# pre-commit ์คํ์ ํ์ํ ํ
์ ์ค์นํฉ๋๋ค
$ pre-commit install
pre-commit installed at .git/hooks/pre-commit
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
# ์๋ ์ค์ ์ ์ถ๊ฐํด์ Commit ๋๊ธฐ ์ ์ ์๋ ํญ๋ชฉ๋ค์ ์ฒดํฌํ๋๋ก ํฉ๋๋ค
# XXX: Python ๊ด๋ จ ์ค์ ์ ์ถํ์ ์ถ๊ฐํฉ๋๋ค
(creamheroes) ~/creamheroes $ cat <<EOF >> .pre-commit-config.yaml
$ default_language_version:
$ python: python3.8
$ repos:
$ - repo: https://github.com/pre-commit/pre-commit-hooks
$ rev: v2.5.0
$ hooks:
$ - id: check-byte-order-marker
$ - id: trailing-whitespace
$ - id: end-of-file-fixer
$ - id: check-yaml
$ - id: check-added-large-files
$ EOF
# ์ต์ง๋ก pre-commit ํ
์ ๊ฑธ๋ฆฌ๊ฒ ํ๋ ค๊ณ ํ์ผ์ EOF๋ฅผ ์ง์๋ณผ๊ฒ์
$ truncate -s -1 .gitignore
# ํด๋น ๋ณ๊ฒฝ ์ฌํญ์ ์ปค๋ฐํ๋ฉด์ ์ ์์ ์ผ๋ก ๋์ํ๋์ง ํ์ธํฉ๋๋ค
(creamheroes) ~/creamheroes $ git commit
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
Trim Trailing Whitespace.................................................Passed
Fix End of Files.........................................................Failed
- hook id: end-of-file-fixer
- exit code: 1
- files were modified by this hook
Fixing .gitignore
Check Yaml...............................................................Passed
Check for added large files..............................................Passed
# ๋ค์ add ํ ๋ EOF๊ฐ ์๋์ผ๋ก ์ถ๊ฐ๋๊ฒ์ด ๋ณด์
๋๋ค
$ git add -p
$ git commit
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
์ฌ๊ธฐ๊น์ง ์์ ํ์ผ๋ ์ง์ง Commit ํ๊ณ
Github์์ ๋ฆฌ๋ชจํธ ์ ์ฅ์๋ ํ๋ ์์ฑํด๋ณผ๊ฒ์
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
๐ HOW TO START (PYTHON) PROJECT
Create Project w/ Git
# ๋ฆฌ๋ชจํธ ์ ์ฅ์๋ฅผ ๋ก์ปฌ์ ref๋ก ๋ฑ๋กํ๊ณ , ํ์ฌ๊น์ง์ ์์
๋ด์ฉ์ Push ํฉ๋๋ค
(creamheroes) ~/creamheroes $ git remote add origin https://github.com/DoonDoony/creamheroes.git
(creamheroes) ~/creamheroes $ git push origin master
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
Code Quality์ Convention์ ๋ง์ถฐ์ฃผ๋
Code Formatter, Linter, ์ ์ ๋ถ์๊ธฐ๋ฅผ ์ค์นํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
Code Formatter ์ธ black
์๋์ผ๋ก import ์์๋ฅผ ์ ๋ ฌํด์ฃผ๋ isort
์ฌ์ฉํ์ง ์๋ ๋ณ์๋ import๋ฅผ ์๋์ผ๋ก ์ ๋ฆฌํด์ฃผ๋ autoflake
PEP Guide์ ๋ง์ง ์๋ ์ฝ๋๋ฅผ ์๋ ค์ฃผ๋ flake8
๋ง์ง๋ง์ผ๋ก, ํ์ด์ฌ์ ์ ์ ํ์ ๋ถ์๊ธฐ์ธ mypy์ ์ค์นํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
# ์ค์ ์ด์์์๋ ์ฌ์ฉํ์ง ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ฏ๋ก, DevDependency๋ก์จ ์ค์นํฉ๋๋ค
(creamheroes) ~/creamheroes $ poetry add -D black isort autoflake flake8 flake8-django mypy django-stubs
# ์์ ๋๊ตฌ๋ค์ setup.cfgํ์ผ์ ์ค์ ์ ๋ฐ๋ฆ
๋๋ค. ini์ ๋น์ทํ ํ์์ผ๋ก ์์ฑํฉ๋๋ค
# https://packaging.python.org/guides/distributing-packages-using-setuptools/#setup-cfg
(creamheroes) ~/creamheroes $ cat <<EOF >> setup.cfg
[flake8]
# B = bugbear
# E = pycodestyle errors
# F = flake8 pyflakes
# W = pycodestyle warnings
# B9 = bugbear opinions,
# ISC = implicit str concat
select = B, E, F, W, B9, ISC
ignore = E203, E266, E501, W503, B305, W504
max-line-length = 120
exclude = **/migrations/*
[isort]
combine_as_imports = true
default_section = THIRDPARTY
include_trailing_comma = true
line_length = 79
multi_line_output = 5
use_parentheses = true
[mypy]
python_version = 3.8
warn_return_any = True
disallow_untyped_defs = True
ignore_missing_imports = True
plugins = mypy_django_plugin.main
[mypy.plugins.django-stubs]
django_settings_module = creamheroes.conf.settings.base
[mypy_django_plugin]
ignore_missing_settings = true
ignore_missing_model_attributes = True
[mypy-*.migrations.*]
# Django migrations should not produce any errors:
ignore_errors = True
[tool:pytest]
addopts = -v -p no:warnings --nomigrations --cov=. --no-cov-on-fail
DJANGO_SETTINGS_MODULE = creamheroes.conf.settings.test
python_paths = creamheroes
console_output_style = progress
cache_dir = .pytest_cache
EOF
# Python์ ์์ง๋ ๋ฐ์ ์ค์ด๊ธฐ ๋๋ฌธ์... ์ง๋ค ๋ฉ๋๋ก ์ค์ ํ์ผ์ ์ ์ํ๋ ๋ถ๋ถ์ด ๋ค๋ฆ
๋๋ค
# https://github.com/psf/black/issues/688
# 'black' ์ฝ๋ ํฌ๋งคํฐ๋ 'pyproject.toml' ํ์ผ์ ๊ทธ ์ค์ ์ ์ ์ํ ์ ์์ต๋๋ค
(creamheroes) ~/creamheroes $ : << 'END_COMMENT'
[tool.black]
line-length = 119
target-version = ['py38']
include = '\.pyi?$'
exclude = '''
(
/(
\.eggs # exclude a few common directories in the
| \.git # root of the project
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| \.python-version
| _build
| buck-out
| build
| dist
)/
)
'''
[build-system]
requires = ["poetry>=0.12"]
build-backend = "poetry.masonry.api"
END_COMMENT
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
์ค์ ์ ์ ์ ํ์ผ๋, ์๋ ์ธ ๊ตฐ๋ฐ์์ ์ด๊ฒ์ ์คํํ๋ฉด ์ข์๊ฒ ๊ฐ์์
ย
1. PyCharm
2. pre-commit hook
3. CI (Github Actions) ๋๊ตฌ (๋์ค์)
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
# .pre-commit-config.yaml์ ์๋ ์ค์ ๋ค์ ์ถ๊ฐํฉ๋๋ค
(creamheroes) ~/creamheroes $ cat <<EOF >> .pre-commit-config.yaml
- repo: https://github.com/python/black
rev: 19.10b0
hooks:
- id: black
- repo: local
hooks:
- id: isort
name: isort
entry: python -m isort.__main__
language: system
types: [python]
- repo: local
hooks:
- id: autoflake
name: autoflake
entry: autoflake
language: system
args: ['--in-place', '--remove-all-unused-imports']
- repo: local
hooks:
- id: flake8
name: flake8
entry: flake8
language: python
types: [python]
args: ['--config', 'setup.cfg']
- repo: local
hooks:
- id: mypy
name: mypy
entry: mypy
language: python
types: [python]
args: ['--config-file', 'setup.cfg']
EOF
๐ HOW TO START (PYTHON) PROJECT
Code Format / Lint
์์ ์ด ๋๋ฌ์ผ๋ Commit ํฉ์๋ค
.py ํ์ผ์ด Stage์ ์์ผ๋ฉด, ํ ์ ๋์ํ์ง ์์์
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
์ด์ Django Project ๋ฅผ ์์ฑํด๋ด์
์์กด์ฑ์ ์ค์นํ๊ณ , CLI๋ฅผ ํตํด ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
# ์ต์ ๋ฒ์ django๋ฅผ ์ค์นํฉ๋๋ค
(creamheroes) ~/creamheroes $ poetry add django
# django-admin์ ํตํด ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค
# ๋ฐ๋์ ๋งจ ๋ง์ง๋ง์ ํ์ฌ ๊ฒฝ๋ก์ ์ค์น๋ฅผ ์๋ฏธํ๋ ์จ์ (.) ์ ๋ถ์ฌ์ค๋๋ค
(creamheroes) ~/creamheroes $ django-admin startproject creamheroes .
(creamheroes) ~/creamheroes $ lt --level 2
Permissions Size User Date Created Name
drwxr-xr-x - doon 2020-07-04 08:32 ๏ .
drwxr-xr-x - doon 2020-07-04 08:33 โโโ ๏ creamheroes
.rw-r--r-- 0 doon 2020-07-04 08:33 โ โโโ ๎ __init__.py
.rw-r--r-- 399 doon 2020-07-04 08:33 โ โโโ ๎ asgi.py
.rw-r--r-- 3,103 doon 2020-07-04 08:33 โ โโโ ๎ settings.py
.rw-r--r-- 753 doon 2020-07-04 08:33 โ โโโ ๎ urls.py
.rw-r--r-- 399 doon 2020-07-04 08:33 โ โโโ ๎ wsgi.py
.rwxr-xr-x 631 doon 2020-07-04 08:33 โโโ ๎ manage.py
.rw-r--r-- 2,137 doon 2020-07-04 08:33 โโโ ๏
poetry.lock
.rw-r--r-- 269 doon 2020-07-04 08:32 โโโ ๏
pyproject.toml
.rw-r--r-- 269 doon 2020-07-04 08:32 โโโ ๏
setup.cfg
# settings ํ์ผ์ ์ฎ๊ฒจ์ค๋๋ค. settings ํ์ผ์ ๋ค๋ฅธ ํ๋ ์์ํฌ์ ๋น์ ํ๋ฉด...
# Lavavel์ Config ๋๋ ํ ๋ฆฌ ๋๋ Spring์ pom.xml? application.properties? ์ ๋ชจ๋ฅด๊ฒ ๋ค์
(creamheroes) ~/creamheroes $ mkdir -p creamheroes/conf/settings
(creamheroes) ~/creamheroes $ cd creamheroes
(creamheroes) ~/creamheroes/creamheroes $ mv __init__.py asgi.py settings.py urls.py wsgi.py conf/
(creamheroes) ~/creamheroes/creamheroes $ touch conf/settings/__init__.py
(creamheroes) ~/creamheroes/creamheroes $ mv conf/settings.py conf/settings/base.py
# Ripgrep ์ผ๋ก ํ์ํ ๋ถ๋ถ์ ์ฐพ์๋ฐ๊ฟ์ค๋๋ค
(creamheroes) ~/creamheroes/creamheroes $ brew install ripgrep
# GNU sed ์์๋ ๋์์ด ์กฐ๊ธ ๋ค๋ฆ
๋๋ค (sed -i 's/find/replace/g' ๋ก๋ ๊ฐ๋ฅํฉ๋๋ค)
(creamheroes) ~/creamheroes/creamheroes $ rg '\bcreamheroes.settings' -l | xargs sed -i '' 's/creamheroes.settings/creamheroes.conf.settings.base/g'
(creamheroes) ~/creamheroes/creamheroes $ rg '\bcreamheroes.urls' -l | xargs sed -i '' 's/creamheroes.urls/creamheroes.conf.urls/g'
(creamheroes) ~/creamheroes/creamheroes $ rg '\bcreamheroes.wsgi' -l | xargs sed -i '' 's/creamheroes.wsgi/creamheroes.conf.wsgi/g'
# ๊ฐ๋ฐ ์๋ฒ๊ฐ ์ ์ ๋์ ํ๋์ง ์คํํด ๋ด
๋๋ค
(creamheroes) ~/creamheroes/creamheroes $ cd ..
(creamheroes) ~/creamheroes/ $ ./manage.py runserver
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
๊ทธ๋ผ ์ด์ ํ๋ก์ ํธ ์ธํ ๋ ํ์ผ๋
Commit์ ํ ๋๊ฐ ๋๊ธด ๋ญ๊ฐ ๋ผ!
์ค์ํ ์ ๋ณด๋ฅผ ์ง์ฐ๊ณ ๊ณต๊ฐ ์ ์ฅ์์ ์ฌ๋ ค์ผ ํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
Django Settings์ SECRET_KEY๋
์ํธํ ์๋ช ๊ณผ ํด์ฌ์ ์ฌ์ฉ๋๋ salt์ ์ญํ ๋ ํฉ๋๋ค
๋ฐ๋ผ์ ๊ณต๊ฐ ์ ์ฅ์์ ๋ ธ์ถ๋๋ฉด ๋ณด์์ ์ํ์ด ์๊ธฐ์
์๋ฏธ์๋ ์์๊ฐ์ผ๋ก ๋ณ๊ฒฝํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
์ด๋ฐ ์ค์ํ ์ ๋ณด๋ .env ํ์ผ์ ์์ฑํ์ฌ ๊ด๋ฆฌํฉ๋๋ค
.env ํ์ผ์์ ๊ฐ์ ์ฝ์ด ์ฃผ์ ํด์ฃผ๋
django-environ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํ๊ณ ์ฌ์ฉํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
# django-environ ์ ์ค์นํฉ๋๋ค
(creamheroes) ~/creamheroes $ poetry add django-environ
(creamheroes) ~/creamheroes $ touch .env
(creamheroes) ~/creamheroes $ cat <<EOF >> .env
SECRET_KEY=<์ค์ SECRET_KEY>
EOF
# ๊ณต๊ฐ ์ ์ฅ์์ .env ํ์ผ ๋ํ ์ฌ๋ฆด ์ ์์ผ๋ฏ๋ก (์ด๋ฏธ .gitignore์ ๋ฑ๋ก๋์ด ์์๊ฑฐ์์)
# ์ด๋ฐ ๊ฐ๋ค์ด ํ์ํ๋ค๋ ํํธ๊ฐ ์์ด์ผ ํ์
ํ๋ ์ฌ๋์ด ๊ฐ์ ๋ฌผ์ด๋ณผ ์ ์๊ฒ ์ฃ ?
# NOTE: .env.sample ์์ ์ค์ ๊ฐ์ ๋ฐ๋์ ์ ๊ฑฐํด์ผ ํฉ๋๋ค
(creamheroes) ~/creamheroes $ cp .env .env.sample
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
# creamheroes/conf/settings/base.py
import environ # type: ignore
env = environ.Env()
environ.Env.read_env(os.environ.get("ENV_PATH"))
SECRET_KEY = env.str('SECRET_KEY', '********') # ๊ฐ์ด ์์ด๋ Default ๊ฐ์ ๋ฐ๋ฅด๊ฒ ๋ฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
ENV_PATH ๋ผ๋ ํ๊ฒฝ๋ณ์๋ ์๋๋ฐ ๐ค ์ด๋ป๊ฒ ์ ์ํ ๊น์?
direnv ๋ฅผ ์ฌ์ฉํด์, ํ๋ก์ ํธ๋ณ ํ๊ฒฝ๋ณ์๋ฅผ ๊ตฌ์ฑํ ์ ์์ด์
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
# direnv ๋ฅผ ์ค์นํฉ๋๋ค
$ brew install direnv
# direnv ํ
์ ํ์ฑํ ํด์ผ ํฉ๋๋ค
$ cat <<EOF >> ~/.zshrc
eval "$(direnv hook zsh)"
EOF
# direnv ๋ฅผ ํ์ฑํ ํ๊ธฐ ์ํด์๋ .envrc ํ์ผ์ด ํ์ํฉ๋๋ค
# .envrc ํ์ผ์ ์ฐ๋ฆฌ๊ฐ ์ค์ ํ๋ ค๋ ํ๊ฒฝ๋ณ์๋ฅผ ์ ์ํฉ๋๋ค
(creamheroes) ~/creamheroes $ touch .envrc
(creamheroes) ~/creamheroes $ cat <<EOF >> .envrc
export ENV_PATH="$PWD/.env"
EOF
direnv: error /Users/doon/Tutorial/creamheroes/.envrc is blocked. Run `direnv allow` to approve its content
# direnv ๋ฅผ ํ์ฑํ ํฉ๋๋ค
$ direnv allow .
direnv: loading ~/Tutorial/creamheroes/.envrc
direnv: export +ENV_PATH
# ํ๊ฒฝ๋ณ์๊ฐ ์ ๋ฑ๋ก๋์๋์ง ํ์ธํฉ๋๋ค
$ env | grep ENV_PATH
ENV_PATH=/Users/doon/Tutorial/creamheroes/.env
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
ํ๊ฒฝ๋ณ์๋ก ์ ์ ์ฉ๋์๋์ง๋ฅผ
Django Interactive Shell ์ ์ฌ์ฉํด์ ํ์ธํด๋ด์
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
$ ./manage.py shell
Python 3.8.3 (default, May 19 2020, 23:35:46)
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from django.conf import settings
>>> settings.SECRET_KEY
'-2u)(2#bx8+#u6&cv7k$war6#)5sts+&rb6j*#)liiyxl0l#na'
๐ HOW TO START (PYTHON) PROJECT
Start Django Project
์ด์ ์ง์ง Commit ํ๊ณ ๋ค์ Docker ๊ตฌ์ฑ์ผ๋ก ๋์ด๊ฐ๋ณด์์
Docker, CI/CD, Git tag, Workflow, Fabric...
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
Docker ๋ฅผ ์ฌ์ฉํด์ ๊ฐ๋ฐ์๋ฒ๋ฅผ
์ด์๊ณผ ๋น์ทํ ํ๊ฒฝ์์ ์คํ๋๋๋ก ์ค์ ํด๋ณด์์
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
๋จผ์ , ์ค์ ๋ก ๋ฐฐํฌ๋ Docker Image ๋ฅผ ๋ง๋ค๊ธฐ์ํด
Dockerfile ์ ์์ฑํด์ผ ํฉ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
# Docker ๊ด๋ จ๋ ํ์ผ์ ๋ค๋ฅธ ๋๋ ํ ๋ฆฌ์ ์ ๋ฆฌํ๋๊ฑธ ์ ํธํด์
(creamheroes) ~/creamheroes $ mkdir .docker
# ์ค์ ๋ก ์๋ฒ ๊ตฌ๋์์๋ ./manage.py runserver ๊ฐ ์๋ gunicorn์ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค
# Java Tomcat ๊ฐ์ ๋
์์
๋๋ค
(creamheroes) ~/creamheroes $ poetry add gunicorn
# Dockerfile ์ ์๋์ ๊ฐ์ด ์์ฑํด๋ดค์ต๋๋ค
(creamheroes) ~/creamheroes $ cat <<EOF >> .docker/Dockerfile
FROM python:3.8.3-slim AS build
RUN apt-get update -y
RUN apt-get install -y --no-install-recommends build-essential gcc
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"
RUN mkdir /code
WORKDIR /code
COPY requirements.txt .
RUN pip install -U pip
RUN pip install -r requirements.txt
FROM python:3.8.3-slim AS final
COPY --from=build /opt/venv /opt/venv
WORKDIR /code
COPY . .
ENV PATH="/opt/venv/bin:$PATH"
CMD ["gunicorn", "creamheroes.conf.wsgi", "--bind", "0.0.0.0:8000"]
EOF
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
Multi Stage Build ๋ฅผ ํ์ฉํด ์ด๋ฏธ์ง ์ฌ์ด์ฆ๋ฅผ ์ค์ด๊ณ
์บ์๋ ๋ฐ์ดํฐ๋ฅผ ์ต๋ํ ํ์ฉํ ๋น๋์๋๋ฅผ ์ฌ๋ฆฝ๋๋ค
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
Docker Image ๋ฅผ ๋น๋ํ๊ธฐ์ ์
์์ฃผ ์ธ ๊ฒ ๊ฐ์ ๋ช ๋ น์ด๋ฅผ Makefile ์ ์ ์ํด๋ณด๋ฉด
์ด๋จ๊น์์ ๐ค
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
# Makefile ์์ ์ฌ์ฉํ ๋งํ ๋ช
๋ น์ด ์ธํธ์
๋๋ค
(creamheroes) ~/creamheroes $ cat <<EOF >> Makefile
.PHONY: build
build:
@make freeze
@docker image build . -t creamheroes:v1 -f .docker/Dockerfile
.PHONY: clean
clean:
@docker image prune -f
@docker container prune -f
@docker network prune -f
@docker volume prune -f
.PHONY: destroy
destroy:
@docker container stop creamheroes || true
@make clean > /dev/null
.PHONY: freeze
freeze:
@poetry export -f requirements.txt -o requirements.txt --dev -n --without-hashes
.PHONY: log
log:
@docker container logs -f creamheroes
.PHONY: open
open:
@open http://localhost:8000
.PHONY: runserver
runserver:
@docker container run --rm -d -p 8000:8000 --name creamheroes -t creamheroes:v1
EOF
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
์ด์ ์ค์ ๋ก ์ด๋ฏธ์ง๋ฅผ ๋น๋ํ๊ณ
๋์ปค ์ด๋ฏธ์ง๋ก ๊ฐ๋ฐ์๋ฒ๊ฐ ์ ๋์ํ๋์ง
ํ ๋ฒ ํ์ธํด๋ด์ ๐ค
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
# ์ด๋ฏธ์ง ๋น๋ ์์
(creamheroes) ~/creamheroes $ make build
# ์๋ฒ ์์
(creamheroes) ~/creamheroes $ make runserver
# ๋ธ๋ผ์ฐ์ ์์ ํ์ธ
(creamheroes) ~/creamheroes $ make open
# ์๋ฒ ์ข
๋ฃ
(creamheroes) ~/creamheroes $ make destroy
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
์ฌ๊ธฐ์ ํ ๋ฒ ์ปค๋ฐํ๊ณ
์ค๋์ ์ฌ๊ธฐ๊น์ง... ๐๐ปโโ๏ธ
๐ HOW TO START (PYTHON) PROJECT
Create Docker Image
๋ค์์ ๋๋นตํ ์ผ ์์ผ๋ฉด ์ด์ด์ ์ค๋นํด ๋ณผ๊ฒ์