SlideShare a Scribd company logo
1 of 129
Download to read offline
2to3 converter를 활용한
django 프로젝트 python 버전업 삽질기
남형걸
발표자 소개
남형걸
HYPERCONNECT 백엔드 & 데이터 엔지니어
2017.05 ~ 2018.08
- API 서버 개발 (python, django)
- 데이터 파이프라인 구축 (python, scala, spark, hive, django)
- python, django, scala, spark, hive 등을 사용하(배우)면서 일하는 중
- https://github.com/namhyeongkeol
발표 소개
진행 순서
발표 소개
1. 개요 및 2to3 소개
2. 2to3 conversion 진행
3. 호환성 코드 rollback
4. DB migration 신경쓰기
5. py3 환경에서 테스트 및 디버깅
6. py3 서버 배포 및 트러블 슈팅
7. 정리
발표 소개
개요 및 2to3 소개
무엇을 했나
● Django 프로젝트의 python 버전업을 진행
● 2to3라는 python 공식 version converter 사용
● 기존에는 Django 1.9를 Python 2.7로 사용하고 있었음
● 사내 Django의 쓰임새
○ 서비스 백오피스 제공
○ Data Infra 관리
개요
진행해야 했던 이유
● 조만간의 Django 버전업을 위해서
○ django 2.0 부터는 python 2.7 을 지원하지 않는다
● python3 기능 수요가 늘어남
○ asyncronous programming 과 사용하려던 몇몇 라이브러리
● python 2.7로는 폼이 안남
○ 실력 있는 구직자가 python 2.7을 쓰는걸 보면 어떻게 느낄까?
개요개요
Error Driven Development
● 선택한 접근 방법론은 EDD
● Error-driven development is
systems development,
where everything is done in reaction to errors.
● 모든 것은 에러에 대한 대응으로 진행된다!
개요개요
EDD를 선택한 이유
● 위험해 보이지만 가장 효율적이다
● 설계 & 개발하는 것이 아니라 갈아엎는 작업에 적합
● 비용의 차이
○ 체계적인 계획과 실천 vs 일단 엎고 수습하기
개요개요
EDD에서 중요한 것들
● TODO List & Check List 관리
○ list up의 중요성은 아무리 강조해도 지나치지 않다!
● Monitoring Plan
○ 항상 action 대한 monitoring plan이 필요
● Failover Plan
○ 안정화 되기 전까지는 항상 기존 상태로 회귀 가능해야 함
개요개요
● fixer라고 부르는 unit converter들의 집합
● python에 기본 탑재 & command line 명령으로 실행
● 사용하고자 하는 fixer들만 골라서 conversion 할 수 있음
● 백업파일 생성 가능
○ git ignored 파일에 대해 유용하게 사용할 수 있음
● https://docs.python.org/2/library/2to3.html
2to3 converter
개요개요
2to3 converter
● 여러가지 옵션이 있다.
○ -f 옵션으로 사용할 fixer들을 골라서 단계적 진행
○ -w 옵션으로 백업 파일 생성 (.bak suffix로 같은 dir에 생성)
○ -d 옵션으로 doctest 가능
● default fixer들만 사용하는 것으로 정하고 -w 옵션만 사용
○ 단계를 더 나눠서 진행하기 귀찮음
○ 빨리 고치고 디버깅하는게 더 중요
개요개요
● 당연하지만 문법 에러가 있으면 에러 발생
● python2에는 없는 python3 문법이 있어도 에러 발생
○ async, await, {**{}}, ...
○ 이런 류의 코드는 잠시 지워두고 2to3를 적용한 뒤 다시 첨가해야함
○ 보통 2to3를 하게 되는 상황은
py2, py3 공존하던 상황이 py2 코드밖에 없던 상황보다 많다
2to3 converter 주의사항
개요개요
● 2to3 결과를 따로 로깅하자
○ 2to3 -w example_app >> 2to3_example_app.log 2>&1
○ 그래야 에러로 진행되지 않은 부분이 무엇인지 알 수 있음
● git ignored 파일들에 대해서도 진행하자
○ 배포할 때도 기억해야 함
2to3 converter 주의사항
개요개요
● .py 파일이 아니면 filepath를 명시해줘야 진행됨
○ 하지만 다른 언어의 경우 당연히 python 문법 에러 발생
○ 우리도 shell script 안의 python 코드 손수 고쳐주었다
● 어떤 3.x로 변환하는지 알 수 없음
○ 별 문제 없음
○ 3.0으로 변환하는 것으로 추측
2to3 converter 주의사항
개요개요
● 3rd party library에 대해서는 웬만하면 진행하지 말자
○ 3rd party 쪽에서 알아서 python 버전 호환성을 맞춰 놓기 마련
○ 2to3 커스터마이징을 하더라도 손수 진행하는게 낫다
○ 라이브러리 코드는 버전관리가 되지 않고 있을 것이고,
따라서 2to3의 변화를 롤백하기 어렵다
○ 예상치 못한 문제 발생시 대응하기 힘들고 귀찮음
2to3 converter 주의사항
개요개요
1단계 - 2to3 conversion
runserver error 없애기
2to3 conversion 진행
● 1st Phase 목표 - runserver 에러 고치기
○ py3 interpreter로 django runserver 실행시 에러발생
○ 그 때 발생하는 error 들만 없애는게 목표
○ ImportError, SyntaxError 등이 있다.
○ 2to3로 conversion을 전부 진행하면 이는 대부분 없어진다.
1st Phase1st Phase
2to3 conversion 진행
● 하다보면 branch를 매우 많이 만들게 됨
● 1st phase라는 걸 알아보기 쉽도록
branch 이름 앞부분에 숫자 1을 넣어서 표시
1st Phase
2to3 conversion 진행
● Django 프로젝트 내 app 별로 conversion 진행
○ commit도 app 별로 하나씩 하자
○ app에 속하지 않는 기타 파일들도 가장 상위 디렉토리별로 commit
1st Phase1st Phase
SyntaxError 예시 - Long
● py2 int vs long 이원화
● py3 int 일원화
int -sys.maxint-1 ~ sys.maxint
long bignum L을 붙여서 구분
int bignum L 안 붙임
1st Phase1st Phase
SyntaxError 예시 - Long
● 2to3에 의해 해결
1st Phase1st Phase
ImportError 예시 - relative import
● 모든 import statements는 absolute import로 하자
● relative import를 하고 싶다면 leading dots라는
특수 문법을 동원하여 explicit relative import를 하자
PEP 328
1st Phase1st Phase
ImportError 예시 - relative import
PEP 328
1st Phase1st Phase
ImportError 예시 - relative import
● 2to3에 의해 해결
● 하지만 3rd party library에서 이 문제가 발생하면 어떨까?
손수 해결해줘야 함!
PEP 328
1st Phase1st Phase
ImportError 예시 - umalqurra
● 3rd party library 내에서도 ImportError가 발생 가능
● 대부분 library 버전업을 진행하면 해결된다
● 하지만 간혹 많이들 사용하는 라이브러리 임에도
python 버전 호환성 대응이 안되어 있는 경우가 있다
1st Phase1st Phase
ImportError 예시 - umalqurra
hijri_date.py
py2.7 deprecated but OK
py3.6 Error
py2.7 OK
py3.6 OK
1st Phase1st Phase
2to3에 의해 새로이 생성되는 Error
● 앞서 얘기한대로 2to3 conversion은
py2와 py3가 공존하는 상황에서 진행되는 경우가 더 많다
○ 이 때문에 2to3가 새로이 발생시키는 에러가 존재
● 보통은 py-std library에 대한 import statements
○ 대개 분기문에서 에러가 발생
1st Phase1st Phase
2to3에 의해 새로이 생성되는 ImportError
before 2to3 after 2to3
py2 imap, map 이원화 map() imap()
py3 map 일원화 list(map()) map()
1st Phase1st Phase
2to3 conversion PR
● 하나의 app에 하나의 commit
○ 손수 고친 부분은 무조건 2to3가 고친 commit과 분리하여 commit
○ 손수 고친 부분이 많으면 branch도 분리해도 좋음
● 사람이 다 읽은 것 중 가장 큰 PR
○ app별로 분리해서 PR 만드시길 추천
1st Phase1st Phase
여기까지가 1st Phase
● 테스트 전 단계에서는 모든 에러를 해결한 셈
○ 일단 django 서버가 로컬에서 돌아는 감
○ 팀장님한테 어필할 수 있는 첫 단계
● 지금까지 소개한 에러 말고도 여러가지 이슈가 있을 수 있다
○ 인생의 좋은 경험이다 생각하고 열심히 수습하는거 밖에 방법이 없다
1st Phase1st Phase
2단계 - 호환성 코드 rollback
python 2, python 3 호환되는 코드는 롤백하기
py2 py3 호환성 코드만 Rollback
● 2nd Phase 목표 - 호환성 코드 rollback
● 필요없는 경우는 진행할 필요가 없다
○ 호환성 코드가 없는 경우
○ 별 문제가 없음이 확실히 확인된 경우
2nd Phase
Py-version diagram
1st Phase
1st Phase
Py2 Py3
Py3 Compatible
1st Phase
Py-version diagram
1st Phase
● py2, py3가 호환되는 코드는
그냥 놔두는게 좋지 않았을까?
● 이대로는 팀장님을 설득하기 힘듦
1st Phase
Py2 Py3
Py3 Compatible
1st Phase
Py-version diagram
1st Phase 2nd Phase
1st Phase
Py2 Py3
Py3 Compatible
Py3
Compatible
1st Phase
py2 py3 호환성 코드만 Rollback
● py2 interpreter로 실행하면 static 에러로서 상당수 나온다
● 나머지는 장대한 diff 내역을 보며 호환성코드 복구
○ 대체로 분기문, 예외처리문에 의한 import statements
○ 찾을 키워드는 six future past builtins stringIO urllib
○ 사람이니까 조금씩 놓칠 수 있음
○ 빠르게 테스트하고 고치는게 중요
2nd Phase2nd Phase
여기까지가 2nd Phase
● EDD를 본격적으로 시작하기 전에
반드시 해야할 작업이 아직 남아 있다
● DB migration!
○ 코드가 아주 많이 변경되었으니 꼭 고려해주어야 함
2nd Phase2nd Phase
3단계 - DB migration
django DB migration에서 발생가능한 이슈들 정리
● django의 makemigrations 명령을 실행
○ py3로 실행해야 함
○ 경우에 따라 무언가 마이그레이션이 생성될 수 있음
○ 바뀐것도 없는데 왜?
Django makemigrations after 2to3
3th Phase
● Django에는 각 앱 별로 migrations 파일이 존재
1. migrations 폴더 내용을 가지고 project state 만들고
2. model 파일로도 project state 만들어서
3. 둘을 비교
4. 변경사항 있으면 새로운 migration 파일을 생성
Django makemigrations
3th Phase3th Phase
py2 vs py3 - unicode, str, bytes
py2 py3
3th Phase3th Phase
from __future__ import unicode_literals
py2 py3
3th Phase3th Phase
from __future__ import unicode_literals
py2 py3
3th Phase3th Phase
● 2to3를 거쳐도 ‘PYCON’은 그대로 ‘PYCON’
○ 왜냐하면 str은 그대로 str이어야 하므로
2to3 conversion 주의사항
3th Phase3th Phase
before 2to3 after 2to3
● verbose_name, choices, validators, default 등의 값들이 문제
● 장고는 models.py에 unicode_literals를 넣어준다
Django makemigrations 주의사항
3th Phase3th Phase
● 하지만 아래와 같다면?
Django makemigrations 주의사항
3th Phase3th Phase
commonapp.utils.py
● commonapp/utils.py는 우리가 만든 파일이고
unicode_literals feature import가 없을 수 있다
● 이 경우 py2에서는 bytes py3에서는 unicode
Django makemigrations 주의사항
3th Phase3th Phase
1. py2 makemigrations bytes로 migration 생성
이런 경우 아래처럼 된다
3th Phase3th Phase
2. 2to3 conversion 코드 그대로 유지 py2 str(bytes) ➝ py3 str(unicode)
이런 경우 아래처럼 된다
3th Phase3th Phase
commonapp.utils.py
3. py3 makemigrations unicode로 migration 하나 더 생성
이런 경우 아래처럼 된다
3th Phase3th Phase
● 3rd Phase 목표 - migration 관련 발생가능한 이슈 제거
● 새롭게 생성된 migration을 어떻게 처리하나?
○ 그냥 fake migration 하고 넘어가도 된다
○ python migration 파일에서 bytes로 정의하든 unicode로 정의하든
DB에 영향 주는 부분은 없기 때문
Django makemigrations after 2to3
3th Phase3th Phase
● 이 이슈는 library에서도 발생 가능
○ django-axes가 그 예시
○ 마찬가지로 fake처리하면 된다 (in development env)
○ 하지만 git ignored 파일이므로 배포할때는 해당사항 없다
Django makemigrations after 2to3
3th Phase3th Phase
● py2로 makemigrations 실행하면?
○ 2to3를 거친 코드는 py3로만 돌릴 것이므로 아무 의미가 없음
○ 이상한 migration이 무더기로 생성됨
○ 생성되는 이유는 2to3가 migration 파일에서 아래를 지워버리기 때문
○ 정말 만에 하나 2to3를 거친 코드를 py2로 돌려야 한다면 이 또한 진행
그리고 마찬가지로 fake 처리
Django makemigrations after 2to3
3th Phase3th Phase
● migration 관련 주의사항
○ 3rd Phase까지의 완료물을 바로 master에 머지할 수는 없다!
○ 따라서 master에 머지하기 전에 co-worker들이 생성하는
migration이 중간에 끼어들 가능성이 아주 높다
○ 이를 배포전에는 renumbering 해주는 것을 절대 잊지 말자
Django makemigrations after 2to3
3th Phase3th Phase
● 여기까지가 3rd Phase 끝
○ 여기서 배포하면 테스트하지 않은 수 많은 에러가 발생
○ 그러면 배포 전에 무엇을 할 것인가?
● 이제 4th Phase
○ 프로젝트 규모가 크다면 모든 것을 다 테스트할 수 없다
○ 꼭 해야 할 것들만 추려서 테스트 진행
Start EDD?
3th Phase3th Phase
4단계 - Test & Debug
주요기능만 test하고 넘어가자
● 4th Phase 목표 - py2에서랑 똑같이 동작하도록 만들기
○ 모든 코드 모듈간 인터페이스를 py2에서와 같게 만들면 모든게 해결
○ 최소한의 수정만으로 같게 만드는 것이 중요
○ 그래야 뒤끝이 없다
● 꼭 해야 하는 최소한만 테스트 하고 넘어가자
Test & Debug
4th Phase
● 수 없이 많은 에러를 최대한 빠르게 캐치하고 트러블슈팅
○ 기록해둔 것만 서로 다른 에러 20여건
○ 상당수는 배포 이후 발견한 것들
● 특히 만나기 쉬운 에러들 소개
○ Library Issue (non-std library)
○ Python Issue (std library)
Runtime Error 소개
4th Phase4th Phase
● MacOS sierra 이상에서 발생
● 2.1.0에서 6.2.1로 업그레이드
Library Issue - ipython
4th Phase4th Phase
Library Issue - Supervisor in py3
● py2에서 Supervisor를 사용
○ process management & daemonizing
● Supervisor가 py3를 지원하지 않는다!
○ 최신 버전은 3.3.4
○ 4.0.0 버전업에서 py3 지원예정
4th Phase4th Phase
Library Issue - Circus
● py3에서는 Supervisor 대신 alternative로 circus 사용
● Supervisor보다 장점이 많다
○ configuration이 명시적이고 documentation이 더 잘되어 있음
○ stderr redirection customizing 가능
○ more developer friendly
○ advanced web interface 제공
○ circus-top 등 여러가지 강력한 monitoring feature 제공
○ 생태계가 작다는건 단점
4th Phase4th Phase
Library Issue - Circus 주의사항
5th Phase
● circusd도 같은 환경에서 실행 필요
○ copy_env, virtualenv값 반드시 정의
4th Phase4th Phase
● hive-python interface library
● pyhive[hive]==0.2.1에서
● PyHive==0.5.1로 바꿔서 해결
Library Issue - pyhive
4th Phase4th Phase
Library Issue - botocore
● AWS python SDK
● botocore==1.4.66에서
● botocore==1.9.22로 바꿔서 해결
4th Phase4th Phase
● 두 라이브러리 모두 사용
○ Unirest가 py3를 지원하지 않음
○ Requests는 py2, py3 호환
● Requests만 사용하는것으로 변경
● 두 라이브러리의 usage가 꽤 다름
○ Unirest에는 callback이 있고 Requests에는 없음
○ Response 구조도 달라서 다 대응해줘야 함
Library Issue - Unirest vs Requests
4th Phase4th Phase
● django-revproxy==0.9.13 사용하는데 아래 에러 발생
● urllib3==1.22 사용중인 것이 원인
● pip check
○ django-revproxy==0.9.13 urllib3 <1.17,>=1.12
Library Issue - django-revproxy
4th Phase4th Phase
Library Issue - django-revproxy
● 하지만 requests때문에 urllib3 다운그레이드 섣불리 못함
● pip check
○ django-revproxy==0.9.13 urllib3 <1.17,>=1.12
○ requests==2.18.4 urllib3 <1.23,>=1.21.1
● 구서버에서는 requests==2.4.2 사용
○ 이 버전은 py3에서 사용 불가능
4th Phase4th Phase
Library Issue - django-revproxy
● requests==2.14.0가 py3지원하는 가장 낮은 버전
● requests==2.14.0은 urllib3 version dependency 정보를
홈페이지를 뒤져도 찾을 수 없음!
○ EDD답게 requests==2.14.0로 일단 downgrade하고
critical feature test 진행 → 이상 없음!
4th Phase4th Phase
● cryptography를 사용해 private key 생성시 에러 발생
○ encryption할 피암호화 값은 당연히 bytes여야 함
Python Issue - encoding for encryption
4th Phase4th Phase
● cryptography를 사용해 private key 생성시 에러 발생
○ encryption할 피암호화 값은 당연히 bytes여야 함
Python Issue - encoding for encryption
4th Phase
변경전
변경후
4th Phase
● hashlib.sha512 사용할 때도 마찬가지
Python Issue - encoding for encryption
4th Phase4th Phase
● hashlib.sha512 사용할 때도 마찬가지
Python Issue - encoding for encryption
4th Phase
변경전
변경후
4th Phase
● open 함수 decode codec
○ py2 byte strings
○ py3 utf-8
○ 문제는 utf-8 codec은
0x1f 0x8b라는 gz 파일의 magic number를 decode하지
못한다!
Python Issue - read gzip by utf-8
4th Phase4th Phase
● gzip.open으로 바로 initiation해서 해결
● 물론 open 함수를 rb로 열어도 된다
Python Issue - read gzip by utf-8
4th Phase4th Phase
Python Issue - read gzip by utf-8
4th Phase
error
error
OK bytes
OK bytes
OK but str
OK bytes
4th Phase
● gzip을 사용하는 다른 코드에서도 encoding issue
Python Issue - read gzip
4th Phase
변경전
변경후
4th Phase
● gzip을 사용하는 다른 코드에서도 encoding issue
● 이를 아래처럼 고치려 했다면?
Python Issue - read gzip
4th Phase4th Phase
Python Issue - read gzip by utf-8
4th Phase
● 당연히 상기한 에러 발생!
왜냐면 gz 파일을 utf-8로 decode했으므로
● 이를 아래처럼 고치려 했다면? Error
4th Phase
● gzip을 read할 때 말고 write할 때도 encoding 이슈 발생
Python Issue - write gzip
4th Phase
json obj newfilegzip file
read & parsing by str write with wb mode
4th Phase
● gzip을 read할 때 말고 write할 때도 encoding 이슈 발생
Python Issue - write gzip
4th Phase
json obj newfilegzip file
read & parsing by str write with wt mode
변경전
변경후
4th Phase
● Mysql Bit(1) Field에 대해 django cursor로 SQL select 쿼리를 call하면
○ b‘True’, b‘False’ 가 아닌
○ b‘x00’, b‘x01’ 를 return
Python Issue - Mysql Bit(1) edge case
4th Phase4th Phase
● Mysql Bit(1) Field에 대해 django cursor로 SQL select 쿼리를 call하면
○ b‘True’, b‘False’ 가 아닌
○ b‘x00’, b‘x01’ 를 return
● 그래서 다음과 같은 함수를 사용해야 했다
Python Issue - Mysql Bit(1) edge case
4th Phase4th Phase
● Mysql Bit(1) Field에 대해 django cursor로 SQL select 쿼리를 call하면
○ b‘True’, b‘False’ 가 아닌
○ b‘x00’, b‘x01’ 를 return
● 그래서 다음과 같은 함수를 사용해야 했다
● 하지만 이는 에러나기 딱 좋은 사용법
Python Issue - Mysql Bit(1) edge case
4th Phase4th Phase
● py2에서는 str, bytes가 똑같아 b‘x00’가 들어올 때 정상동작
● py3에서는 str, bytes가 달라서 b‘x00’가 들어와도 True 리턴!
○ 이 때문에 수많은 False여야 할 데이터가 True로 저장
○ Exception 발생이 아니니까 온갖 에러가 다 발생하고서야 알아챔
Python Issue - Mysql Bit(1) edge case
4th Phase4th Phase
● py2에서는 str, bytes가 똑같아 b‘x00’가 들어올 때 정상동작
● py3에서는 str, bytes가 달라서 b‘x00’가 들어와도 True 리턴!
○ 이 때문에 수많은 False여야 할 데이터가 True로 저장
○ Exception 발생이 아니니까 온갖 에러가 다 발생하고서야 알아챔
● 근데 더 문제는 이 함수의 사용처
Python Issue - Mysql Bit(1) edge case
4th Phase4th Phase
Python Issue - Mysql Bit(1) edge case
4th Phase
before 2to3
● 데이터 적재 전 전처리 하는 함수
● b‘x00’을 False로 바꾸는 작업 등을 했던 것
● 문제는 두번째 if 조건이 bytes가 아니라 str
● 물론 py2에선 str == bytes 이므로 이상 무
4th Phase
Python Issue - Mysql Bit(1) edge case
4th Phase
before 2to3 after 2to3
4th Phase
Python Issue - Mysql Bit(1) edge case
4th Phase
after 2to3
● py3에선 str != bytes
● 따라서 더 이상 조건문의 의도대로 되지 않음
● 조건문의 위치까지 공교롭게도
convert_to_boolean이
quote_or_null 보다 먼저
4th Phase
Python Issue - Mysql Bit(1) edge case
4th Phase
after 2to3
● 조건문의 위치까지 공교롭게도
convert_to_boolean이
quote_or_null 보다 먼저
● 온갖 스트링이 다 True가 됨
after 2to3
4th Phase
● 만약 b‘x00’, b‘x01’ 대신 b‘False’, b‘True’였다면?
○ eval(value) 사용으로 py2, py3에서 모두 문제 없이 동작
● 조건문 고쳐서 해결
Python Issue - Mysql Bit(1) edge case
4th Phase4th Phase
● __unicode__ vs __str__
○ py2에선 __unicode__만 정의해둬도 print를 할 때
__str__ 정의된 것처럼 실행 (bytes로 return)
○ py3에선 str == unicode 이므로 그렇지 않음
○ py3는 그래서 __str__ 함수를 따로 만들어주어야 함
Python Issue - __unicode__ vs __str__
4th Phase
4th Phase4th Phase
● django decorator 중
python_2_unicode_compatible라는 것 존재
○ py3에서 __str__을 unicode return 하도록 정의하면
○ py2에서 __str__ returns bytes, __unicode__ returns unicode
○ 이를 이용해 py2, 3 공존 가능
Python Issue - __unicode__ vs __str__
4th Phase
4th Phase4th Phase
● django orm .count
○ py2에서는 .count > 0 도 가능
○ py3에서는 .count() > 0 만 가능
Python Issue - Comparison
4th Phase
4th Phase4th Phase
Python Issue - Comparison
4th Phase
4th Phase
● NoneType Comparison
○ py2
○ py3
4th Phase
● django dispatcher의 request
○ requests.body가 bytes 타입!
○ str vs bytes 문제 발생하기 좋음
Python Issue - 여러가지 위험요소들
4th Phase4th Phase
● 나눗셈 변화
○ py2
○ py3
Python Issue - 여러가지 위험요소들
4th Phase4th Phase
● __cmp__ deprecated
○ py2에는 class 내의 __cmp__ 함수로 compare함수 정의 가능
○ py3에는 __cmp__ 없음
○ __lt__, __le__, __gt__, __ge__, __eq__, __ne__ 각각 정의해줘야 함
Python Issue - 여러가지 위험요소들
4th Phase4th Phase
● Exception 구조 변화 - message 없어짐
○ py2
○ py3
Python Issue - 여러가지 위험요소들
4th Phase4th Phase
● flush() 함수 사용할 필요 없어짐
● py2에서는 5초뒤 한꺼번에 0, 1, 2, 3, 4
● py3에서는 1초에 한번씩 0, 1, 2, 3, 4
● py2에서 의도한대로 출력하려면
주석처리된 flush함수 사용해야 함
Python Issue - 여러가지 위험요소들
4th Phase4th Phase
● 여기까지가 4th Phase 끝
○ 여기에 소개된 에러들 중 상당수는 배포 이후에 만남
○ EDD의 현장 기록들
Test & Debug
3th Phase3th Phase
5단계 - Deploy
배포한 이후에도 에러를 많이 만날 수 있음
● 주요 테스트를 끝내고 이제 서버를 새로 띄우자
● py2 서버는 바로 내리지 말고 안정화 될 때까지 상비
● server migration todo list 다섯 가지
배포
crontab
supervisor & circus
django 외 다른 nginx servers
batch job
cache & message queue
5th Phase
배포 흐름에 따른 Branch 관리
1. new server 구축
2. 상기한 5가지 migration 작업 진행 및 트러블 슈팅하며 안정화
3. branch feature/5-phase-deploy-for-py2 from master
merge feature/5-phase-deploy-for-py3 into master
4. 배포 branch 변경
5th Phase
new server feature/5-phase-deploy-for-py3
old server master
5th Phase
new server master
old server feature/5-phase-deploy-for-py2
5th Phase
crontab migration
● crontab task들은 진행전 체크할 것이 많다
○ 구 서버 system timezone은 어디인가
○ 여러번 재실행해도 되는 task인가
○ 아무때나 재실행해도 되는 task인가
5th Phase5th Phase
crontab migration
● crontab task들은 진행전 체크할 것이 많다
○ 구 서버 system timezone은 어디인가 → KST
○ 여러번 재실행해도 되는 task인가 → 그런 것도 있고 아닌 것도 있다
○ 아무때나 재실행해도 되는 task인가 → 그런 것도 있고 아닌 것도 있다
5th Phase5th Phase
crontab migration
● 실서버 테스트 할 수 있는건 즉각 테스트 및 migration
● 테스트 불가능하면 테스트 환경에서 테스트
○ 하루 정해진 횟수, 정해진 시간에만 실행되도록 조건부 migration 진행
5th Phase5th Phase
crontab migration
● timezone UTC에서 KST로 변경 및 crontab 재시작
5th Phase5th Phase
crontab migration
● timezone UTC에서 KST로 변경 및 crontab 재시작
● 이를 해주지 않으면?
○ timing depend한 cron job에서 문제 발생
5th Phase5th Phase
crontab migration
● 만약 system time을 변경하지 않은걸 나중에서야 발견했다면?
○ 늦게라도 timezone 바꾸고
하루에 한 번씩만 돌아가야 하는 task들 정리
○ KST(target timezone) 기준으로
하루 한 번씩만 돌아가도록 조건부 migration
5th Phase5th Phase
django 외 다른 nginx servers
● 에러날 경우 구 서버에 proxy 해주는게 방법
5th Phase5th Phase
● crontab이 아니더라도 여러가지 batch job이 돌아갈 수 있다
○ data engineering을 한다면 특히 많을 수밖에
● 이를 하나하나 새로운 서버로 옮기는걸 잊지 말자
○ airflow를 사용하는데 일부 batch job이 서버 이전 작업에서 누락되어
구서버에서 돌아가는 문제를 겪음
○ py2, py3 환경이 아예 다르기 때문에 큰 문제 발생 가능
Batch Job
5th Phase5th Phase
● cache와 message queue도 py3 서버용 새로 구축
○ cache, MQ의 python interface protocol이 달라질 수 있다
cache & message queue
5th Phase5th Phase
● django cache를 사용하다 보니 이 에러 발생
● py2 서버와 py3 서버 모두 운용할 때 발생
● 이게 뭘까?
unsupported pickle protocol: 4
5th Phase5th Phase
● pickle은 python의 serialization 모듈 이름
○ pickling == serialization, unpickling == deserialization
○ py2.7는 protocol 2
○ py3.6은 protocol 4
unsupported pickle protocol: 4
5th Phase5th Phase
● py2 서버와 py3 서버가 cache를 공유하면서 발생한 것
○ py3에서 protocol 4로 pickling해서 cache에 set data
○ py2에서 protocol 2로 해당 data를 unpickling할 때 발생
○ 각 서버에서 서로 다른 cache를 사용하도록 따로 설정해줘야 함
unsupported pickle protocol: 4
5th Phase5th Phase
● gitignore 된 파일들의 python version
● py3 코드가 py2 interpreter로 돌아가는 경우
○ 반대의 경우도 존재
주요 이슈들의 contexts
5th Phase5th Phase
● python 버전업 문제도 많지만 서버 migration 문제도 아주 많다
● 심오한 기술적인 문제보다 human error가 훨씬 많이 발생
○ 작업이 잘못된다거나, 누락된다거나, 멈춘다거나 등등
● system entropy 관리 문제가 human error의 근본 원인
○ 항상 간단한 List up을 하는 것이 문제 해결의 시작!
주요 이슈들의 contexts
5th Phase5th Phase
정리
● 기본적으로 여섯 가지 branch를 만들자
● 앞의 1 ~ 4단계 개별로 하나씩
Git branch 관리방법
정리
● 기본적으로 여섯 가지 branch를 만들자
● 앞의 1 ~ 4단계 개별로 하나씩
● 이전 단계의 브랜치의 변경사항이 생기면
○ 뒤 단계 브랜치들에는 바로바로 merge!
Git branch 관리방법
정리정리
● 추가적으로 배포용 브랜치 두 개
○ 하나는 py3 베타테스트 용도, 다른 하나는 py2 백업 용도
○ py2 백업 브랜치는 django 서버가 두 종류라면 무조건 있어야
한다!
Git branch 관리방법
정리정리
● py2, py3 공생시키기 vs py3로 갈아 엎기
○ porting에 어려움이 있는게 아니라면 후자가 낫다
○ 처음 시작하는 프로젝트는 무조건 python3로 개발하자
○ py2가 필요한 부분이 분리가능하다면 레포를 분리
○ 그래도 해야 한다면?
Py2, Py3 공생시키기
정리정리
Py2, Py3 공생시키기
● future, six 사용하기
● py2, py3의 차이점들 이해하기
● 추천자료
○ 김태환, Python 2 와 3 공존하기, pycon 2017,
https://www.pycon.kr/2017/program/151
○ Ed Schofield, Writing Python 2-3 compatible code, python-future,
http://python-future.org/compatible_idioms.html
정리정리
● EDD가 효율적인 이유?
○ 계획 세우는 비용을 아낄 수 있어서
○ 보통은 테스트 & 디버깅 한 번 만에 해결이 돼서
○ 목표에 바로 도달할 수 있어서
소감
정리정리
● 하다보니 그냥 한 번에 에러가 나서 서버가 바로
죽어주는게 차라리 고마웠다.
○ 데이터가 바뀌거나 무결성 깨져서 나중에야 그걸 알게되고
뒷수습하는 일이 더 힘들었음
소감
정리정리
● 2to3 conversion을 안전하고 빠르게 하려면?
○ 첫 째도 list up, 둘 째도 list up
○ list up이 한계가 있다면
의존성 관리를 사람이 하지 말고 코드에게 시키는 것만으로도
어느 정도 개선됨
소감
정리정리
● 좋았던 점
○ Pycon 2018 발표
○ asyncio 사용 중
○ ipython 추가기능, 여러가지 django extension들 사용
○ django 버전업 가능
○ 버전업하고 팀내 신규 입사자 6명
소감
정리정리
● Kristjan Wager, Error-driven Software Development,
http://errordrivendevelopment.blogspot.com/2009/06/error-driven-software-development.html
● 김태환, Python 2 와 3 공존하기, pycon 2017,
https://www.pycon.kr/2017/program/151
● Ed Schofield, Writing Python 2-3 compatible code, python-future,
http://python-future.org/compatible_idioms.html
● Timothy Bramlett, Strings Bytes and Unicode in Python 2 and 3,
https://timothybramlett.com/Strings_Bytes_and_Unicode_in_Python_2_and_3.html
● python, Standard Encodings, Python Library Reference
https://docs.python.org/2.4/lib/standard-encodings.html
참고 문헌
정리정리
감사합니다

More Related Content

Similar to Pycon korea - 2018 2to3 converter를 활용한 django 프로젝트 python 버전업 삽질기

200720 바이오협회 생물정보학 파이썬 강의
200720 바이오협회 생물정보학 파이썬 강의 200720 바이오협회 생물정보학 파이썬 강의
200720 바이오협회 생물정보학 파이썬 강의 Joohyun Han
 
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화Jae-yeol Lee
 
파이썬을 배워야하는 이유 발표자료 - 김연수
파이썬을 배워야하는 이유 발표자료 - 김연수파이썬을 배워야하는 이유 발표자료 - 김연수
파이썬을 배워야하는 이유 발표자료 - 김연수Yeon Soo Kim
 
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영Tae Young Lee
 
7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기
7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기
7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기Young-Ho Cha
 
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅Youngmin Koo
 
[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기
[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기
[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기PgDay.Seoul
 
141103 최창원 파이썬 확장 프로그래밍
141103 최창원 파이썬 확장 프로그래밍141103 최창원 파이썬 확장 프로그래밍
141103 최창원 파이썬 확장 프로그래밍Changwon Choe
 
[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기Minho Lee
 
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) 파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) Tae Young Lee
 
하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기Mijeong Park
 
2019스마트국토엑스포-20190808-mago3D기술워크샵
2019스마트국토엑스포-20190808-mago3D기술워크샵2019스마트국토엑스포-20190808-mago3D기술워크샵
2019스마트국토엑스포-20190808-mago3D기술워크샵Gaia3D,Inc.
 
2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain전 민규
 
Introduction to Golang v2
Introduction to Golang v2Introduction to Golang v2
Introduction to Golang v2Hyejong
 
Git 더하기 GitHub(Git클라이언트 활용) / Getting started with git+github
Git 더하기 GitHub(Git클라이언트 활용) / Getting started with git+githubGit 더하기 GitHub(Git클라이언트 활용) / Getting started with git+github
Git 더하기 GitHub(Git클라이언트 활용) / Getting started with git+githubJunyoung Lee
 
git의 브렌치 관리 방법
git의 브렌치 관리 방법git의 브렌치 관리 방법
git의 브렌치 관리 방법은아 정
 
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)Tae Young Lee
 
[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기
[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기
[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기CONNECT FOUNDATION
 
알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기Han Lee
 

Similar to Pycon korea - 2018 2to3 converter를 활용한 django 프로젝트 python 버전업 삽질기 (20)

200720 바이오협회 생물정보학 파이썬 강의
200720 바이오협회 생물정보학 파이썬 강의 200720 바이오협회 생물정보학 파이썬 강의
200720 바이오협회 생물정보학 파이썬 강의
 
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
Github + Heroku + Circle CI 를 이용한 Django Application 배포 자동화
 
파이썬을 배워야하는 이유 발표자료 - 김연수
파이썬을 배워야하는 이유 발표자료 - 김연수파이썬을 배워야하는 이유 발표자료 - 김연수
파이썬을 배워야하는 이유 발표자료 - 김연수
 
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
2016317 파이썬기초_파이썬_다중설치부터_Jupyter를이용한프로그래밍_이태영
 
7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기
7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기
7급 공무원도 쉽게 따라하는 프로파일링 도구 만들기
 
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
GDB와 strace로 Hang 걸린 Python Process 원격 디버깅
 
[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기
[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기
[Pgday.Seoul 2020] 포스트그레스큐엘 자국어화 이야기
 
141103 최창원 파이썬 확장 프로그래밍
141103 최창원 파이썬 확장 프로그래밍141103 최창원 파이썬 확장 프로그래밍
141103 최창원 파이썬 확장 프로그래밍
 
[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기[DS Meetup] iPad로 가벼운 분석환경 구축해보기
[DS Meetup] iPad로 가벼운 분석환경 구축해보기
 
Anatomy of an android
Anatomy of an androidAnatomy of an android
Anatomy of an android
 
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영) 파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
파이썬 데이터과학 레벨1 - 초보자를 위한 데이터분석, 데이터시각화 (2020년 이태영)
 
하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기하드웨어 스타트업의 소프트웨어 이야기
하드웨어 스타트업의 소프트웨어 이야기
 
2019스마트국토엑스포-20190808-mago3D기술워크샵
2019스마트국토엑스포-20190808-mago3D기술워크샵2019스마트국토엑스포-20190808-mago3D기술워크샵
2019스마트국토엑스포-20190808-mago3D기술워크샵
 
2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain2. klaytn developer meetup #2 univ chain
2. klaytn developer meetup #2 univ chain
 
Introduction to Golang v2
Introduction to Golang v2Introduction to Golang v2
Introduction to Golang v2
 
Git 더하기 GitHub(Git클라이언트 활용) / Getting started with git+github
Git 더하기 GitHub(Git클라이언트 활용) / Getting started with git+githubGit 더하기 GitHub(Git클라이언트 활용) / Getting started with git+github
Git 더하기 GitHub(Git클라이언트 활용) / Getting started with git+github
 
git의 브렌치 관리 방법
git의 브렌치 관리 방법git의 브렌치 관리 방법
git의 브렌치 관리 방법
 
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)
파이썬 데이터과학 1일차 - 초보자를 위한 데이터분석, 데이터시각화 (이태영)
 
[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기
[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기
[부스트캠프 Tech Talk] 최재필_P 스테이지에서 Git으로 협업하기
 
알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기알고리즘 시각화 라이브러리 ipytracer 개발기
알고리즘 시각화 라이브러리 ipytracer 개발기
 

Recently uploaded

MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionKim Daeun
 
Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Wonjun Hwang
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)Tae Young Lee
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Wonjun Hwang
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Kim Daeun
 
캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스
 

Recently uploaded (6)

MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
 
Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)Merge (Kitworks Team Study 이성수 발표자료 240426)
Merge (Kitworks Team Study 이성수 발표자료 240426)
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)
 
Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)Console API (Kitworks Team Study 백혜인 발표자료)
Console API (Kitworks Team Study 백혜인 발표자료)
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
 
캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차
 

Pycon korea - 2018 2to3 converter를 활용한 django 프로젝트 python 버전업 삽질기

  • 1. 2to3 converter를 활용한 django 프로젝트 python 버전업 삽질기 남형걸
  • 2. 발표자 소개 남형걸 HYPERCONNECT 백엔드 & 데이터 엔지니어 2017.05 ~ 2018.08 - API 서버 개발 (python, django) - 데이터 파이프라인 구축 (python, scala, spark, hive, django) - python, django, scala, spark, hive 등을 사용하(배우)면서 일하는 중 - https://github.com/namhyeongkeol 발표 소개
  • 3. 진행 순서 발표 소개 1. 개요 및 2to3 소개 2. 2to3 conversion 진행 3. 호환성 코드 rollback 4. DB migration 신경쓰기 5. py3 환경에서 테스트 및 디버깅 6. py3 서버 배포 및 트러블 슈팅 7. 정리 발표 소개
  • 5. 무엇을 했나 ● Django 프로젝트의 python 버전업을 진행 ● 2to3라는 python 공식 version converter 사용 ● 기존에는 Django 1.9를 Python 2.7로 사용하고 있었음 ● 사내 Django의 쓰임새 ○ 서비스 백오피스 제공 ○ Data Infra 관리 개요
  • 6. 진행해야 했던 이유 ● 조만간의 Django 버전업을 위해서 ○ django 2.0 부터는 python 2.7 을 지원하지 않는다 ● python3 기능 수요가 늘어남 ○ asyncronous programming 과 사용하려던 몇몇 라이브러리 ● python 2.7로는 폼이 안남 ○ 실력 있는 구직자가 python 2.7을 쓰는걸 보면 어떻게 느낄까? 개요개요
  • 7. Error Driven Development ● 선택한 접근 방법론은 EDD ● Error-driven development is systems development, where everything is done in reaction to errors. ● 모든 것은 에러에 대한 대응으로 진행된다! 개요개요
  • 8. EDD를 선택한 이유 ● 위험해 보이지만 가장 효율적이다 ● 설계 & 개발하는 것이 아니라 갈아엎는 작업에 적합 ● 비용의 차이 ○ 체계적인 계획과 실천 vs 일단 엎고 수습하기 개요개요
  • 9. EDD에서 중요한 것들 ● TODO List & Check List 관리 ○ list up의 중요성은 아무리 강조해도 지나치지 않다! ● Monitoring Plan ○ 항상 action 대한 monitoring plan이 필요 ● Failover Plan ○ 안정화 되기 전까지는 항상 기존 상태로 회귀 가능해야 함 개요개요
  • 10. ● fixer라고 부르는 unit converter들의 집합 ● python에 기본 탑재 & command line 명령으로 실행 ● 사용하고자 하는 fixer들만 골라서 conversion 할 수 있음 ● 백업파일 생성 가능 ○ git ignored 파일에 대해 유용하게 사용할 수 있음 ● https://docs.python.org/2/library/2to3.html 2to3 converter 개요개요
  • 11. 2to3 converter ● 여러가지 옵션이 있다. ○ -f 옵션으로 사용할 fixer들을 골라서 단계적 진행 ○ -w 옵션으로 백업 파일 생성 (.bak suffix로 같은 dir에 생성) ○ -d 옵션으로 doctest 가능 ● default fixer들만 사용하는 것으로 정하고 -w 옵션만 사용 ○ 단계를 더 나눠서 진행하기 귀찮음 ○ 빨리 고치고 디버깅하는게 더 중요 개요개요
  • 12. ● 당연하지만 문법 에러가 있으면 에러 발생 ● python2에는 없는 python3 문법이 있어도 에러 발생 ○ async, await, {**{}}, ... ○ 이런 류의 코드는 잠시 지워두고 2to3를 적용한 뒤 다시 첨가해야함 ○ 보통 2to3를 하게 되는 상황은 py2, py3 공존하던 상황이 py2 코드밖에 없던 상황보다 많다 2to3 converter 주의사항 개요개요
  • 13. ● 2to3 결과를 따로 로깅하자 ○ 2to3 -w example_app >> 2to3_example_app.log 2>&1 ○ 그래야 에러로 진행되지 않은 부분이 무엇인지 알 수 있음 ● git ignored 파일들에 대해서도 진행하자 ○ 배포할 때도 기억해야 함 2to3 converter 주의사항 개요개요
  • 14. ● .py 파일이 아니면 filepath를 명시해줘야 진행됨 ○ 하지만 다른 언어의 경우 당연히 python 문법 에러 발생 ○ 우리도 shell script 안의 python 코드 손수 고쳐주었다 ● 어떤 3.x로 변환하는지 알 수 없음 ○ 별 문제 없음 ○ 3.0으로 변환하는 것으로 추측 2to3 converter 주의사항 개요개요
  • 15. ● 3rd party library에 대해서는 웬만하면 진행하지 말자 ○ 3rd party 쪽에서 알아서 python 버전 호환성을 맞춰 놓기 마련 ○ 2to3 커스터마이징을 하더라도 손수 진행하는게 낫다 ○ 라이브러리 코드는 버전관리가 되지 않고 있을 것이고, 따라서 2to3의 변화를 롤백하기 어렵다 ○ 예상치 못한 문제 발생시 대응하기 힘들고 귀찮음 2to3 converter 주의사항 개요개요
  • 16. 1단계 - 2to3 conversion runserver error 없애기
  • 17. 2to3 conversion 진행 ● 1st Phase 목표 - runserver 에러 고치기 ○ py3 interpreter로 django runserver 실행시 에러발생 ○ 그 때 발생하는 error 들만 없애는게 목표 ○ ImportError, SyntaxError 등이 있다. ○ 2to3로 conversion을 전부 진행하면 이는 대부분 없어진다. 1st Phase1st Phase
  • 18. 2to3 conversion 진행 ● 하다보면 branch를 매우 많이 만들게 됨 ● 1st phase라는 걸 알아보기 쉽도록 branch 이름 앞부분에 숫자 1을 넣어서 표시 1st Phase
  • 19. 2to3 conversion 진행 ● Django 프로젝트 내 app 별로 conversion 진행 ○ commit도 app 별로 하나씩 하자 ○ app에 속하지 않는 기타 파일들도 가장 상위 디렉토리별로 commit 1st Phase1st Phase
  • 20. SyntaxError 예시 - Long ● py2 int vs long 이원화 ● py3 int 일원화 int -sys.maxint-1 ~ sys.maxint long bignum L을 붙여서 구분 int bignum L 안 붙임 1st Phase1st Phase
  • 21. SyntaxError 예시 - Long ● 2to3에 의해 해결 1st Phase1st Phase
  • 22. ImportError 예시 - relative import ● 모든 import statements는 absolute import로 하자 ● relative import를 하고 싶다면 leading dots라는 특수 문법을 동원하여 explicit relative import를 하자 PEP 328 1st Phase1st Phase
  • 23. ImportError 예시 - relative import PEP 328 1st Phase1st Phase
  • 24. ImportError 예시 - relative import ● 2to3에 의해 해결 ● 하지만 3rd party library에서 이 문제가 발생하면 어떨까? 손수 해결해줘야 함! PEP 328 1st Phase1st Phase
  • 25. ImportError 예시 - umalqurra ● 3rd party library 내에서도 ImportError가 발생 가능 ● 대부분 library 버전업을 진행하면 해결된다 ● 하지만 간혹 많이들 사용하는 라이브러리 임에도 python 버전 호환성 대응이 안되어 있는 경우가 있다 1st Phase1st Phase
  • 26. ImportError 예시 - umalqurra hijri_date.py py2.7 deprecated but OK py3.6 Error py2.7 OK py3.6 OK 1st Phase1st Phase
  • 27. 2to3에 의해 새로이 생성되는 Error ● 앞서 얘기한대로 2to3 conversion은 py2와 py3가 공존하는 상황에서 진행되는 경우가 더 많다 ○ 이 때문에 2to3가 새로이 발생시키는 에러가 존재 ● 보통은 py-std library에 대한 import statements ○ 대개 분기문에서 에러가 발생 1st Phase1st Phase
  • 28. 2to3에 의해 새로이 생성되는 ImportError before 2to3 after 2to3 py2 imap, map 이원화 map() imap() py3 map 일원화 list(map()) map() 1st Phase1st Phase
  • 29. 2to3 conversion PR ● 하나의 app에 하나의 commit ○ 손수 고친 부분은 무조건 2to3가 고친 commit과 분리하여 commit ○ 손수 고친 부분이 많으면 branch도 분리해도 좋음 ● 사람이 다 읽은 것 중 가장 큰 PR ○ app별로 분리해서 PR 만드시길 추천 1st Phase1st Phase
  • 30. 여기까지가 1st Phase ● 테스트 전 단계에서는 모든 에러를 해결한 셈 ○ 일단 django 서버가 로컬에서 돌아는 감 ○ 팀장님한테 어필할 수 있는 첫 단계 ● 지금까지 소개한 에러 말고도 여러가지 이슈가 있을 수 있다 ○ 인생의 좋은 경험이다 생각하고 열심히 수습하는거 밖에 방법이 없다 1st Phase1st Phase
  • 31. 2단계 - 호환성 코드 rollback python 2, python 3 호환되는 코드는 롤백하기
  • 32. py2 py3 호환성 코드만 Rollback ● 2nd Phase 목표 - 호환성 코드 rollback ● 필요없는 경우는 진행할 필요가 없다 ○ 호환성 코드가 없는 경우 ○ 별 문제가 없음이 확실히 확인된 경우 2nd Phase
  • 33. Py-version diagram 1st Phase 1st Phase Py2 Py3 Py3 Compatible 1st Phase
  • 34. Py-version diagram 1st Phase ● py2, py3가 호환되는 코드는 그냥 놔두는게 좋지 않았을까? ● 이대로는 팀장님을 설득하기 힘듦 1st Phase Py2 Py3 Py3 Compatible 1st Phase
  • 35. Py-version diagram 1st Phase 2nd Phase 1st Phase Py2 Py3 Py3 Compatible Py3 Compatible 1st Phase
  • 36. py2 py3 호환성 코드만 Rollback ● py2 interpreter로 실행하면 static 에러로서 상당수 나온다 ● 나머지는 장대한 diff 내역을 보며 호환성코드 복구 ○ 대체로 분기문, 예외처리문에 의한 import statements ○ 찾을 키워드는 six future past builtins stringIO urllib ○ 사람이니까 조금씩 놓칠 수 있음 ○ 빠르게 테스트하고 고치는게 중요 2nd Phase2nd Phase
  • 37. 여기까지가 2nd Phase ● EDD를 본격적으로 시작하기 전에 반드시 해야할 작업이 아직 남아 있다 ● DB migration! ○ 코드가 아주 많이 변경되었으니 꼭 고려해주어야 함 2nd Phase2nd Phase
  • 38. 3단계 - DB migration django DB migration에서 발생가능한 이슈들 정리
  • 39. ● django의 makemigrations 명령을 실행 ○ py3로 실행해야 함 ○ 경우에 따라 무언가 마이그레이션이 생성될 수 있음 ○ 바뀐것도 없는데 왜? Django makemigrations after 2to3 3th Phase
  • 40. ● Django에는 각 앱 별로 migrations 파일이 존재 1. migrations 폴더 내용을 가지고 project state 만들고 2. model 파일로도 project state 만들어서 3. 둘을 비교 4. 변경사항 있으면 새로운 migration 파일을 생성 Django makemigrations 3th Phase3th Phase
  • 41. py2 vs py3 - unicode, str, bytes py2 py3 3th Phase3th Phase
  • 42. from __future__ import unicode_literals py2 py3 3th Phase3th Phase
  • 43. from __future__ import unicode_literals py2 py3 3th Phase3th Phase
  • 44. ● 2to3를 거쳐도 ‘PYCON’은 그대로 ‘PYCON’ ○ 왜냐하면 str은 그대로 str이어야 하므로 2to3 conversion 주의사항 3th Phase3th Phase before 2to3 after 2to3
  • 45. ● verbose_name, choices, validators, default 등의 값들이 문제 ● 장고는 models.py에 unicode_literals를 넣어준다 Django makemigrations 주의사항 3th Phase3th Phase
  • 46. ● 하지만 아래와 같다면? Django makemigrations 주의사항 3th Phase3th Phase commonapp.utils.py
  • 47. ● commonapp/utils.py는 우리가 만든 파일이고 unicode_literals feature import가 없을 수 있다 ● 이 경우 py2에서는 bytes py3에서는 unicode Django makemigrations 주의사항 3th Phase3th Phase
  • 48. 1. py2 makemigrations bytes로 migration 생성 이런 경우 아래처럼 된다 3th Phase3th Phase
  • 49. 2. 2to3 conversion 코드 그대로 유지 py2 str(bytes) ➝ py3 str(unicode) 이런 경우 아래처럼 된다 3th Phase3th Phase commonapp.utils.py
  • 50. 3. py3 makemigrations unicode로 migration 하나 더 생성 이런 경우 아래처럼 된다 3th Phase3th Phase
  • 51. ● 3rd Phase 목표 - migration 관련 발생가능한 이슈 제거 ● 새롭게 생성된 migration을 어떻게 처리하나? ○ 그냥 fake migration 하고 넘어가도 된다 ○ python migration 파일에서 bytes로 정의하든 unicode로 정의하든 DB에 영향 주는 부분은 없기 때문 Django makemigrations after 2to3 3th Phase3th Phase
  • 52. ● 이 이슈는 library에서도 발생 가능 ○ django-axes가 그 예시 ○ 마찬가지로 fake처리하면 된다 (in development env) ○ 하지만 git ignored 파일이므로 배포할때는 해당사항 없다 Django makemigrations after 2to3 3th Phase3th Phase
  • 53. ● py2로 makemigrations 실행하면? ○ 2to3를 거친 코드는 py3로만 돌릴 것이므로 아무 의미가 없음 ○ 이상한 migration이 무더기로 생성됨 ○ 생성되는 이유는 2to3가 migration 파일에서 아래를 지워버리기 때문 ○ 정말 만에 하나 2to3를 거친 코드를 py2로 돌려야 한다면 이 또한 진행 그리고 마찬가지로 fake 처리 Django makemigrations after 2to3 3th Phase3th Phase
  • 54. ● migration 관련 주의사항 ○ 3rd Phase까지의 완료물을 바로 master에 머지할 수는 없다! ○ 따라서 master에 머지하기 전에 co-worker들이 생성하는 migration이 중간에 끼어들 가능성이 아주 높다 ○ 이를 배포전에는 renumbering 해주는 것을 절대 잊지 말자 Django makemigrations after 2to3 3th Phase3th Phase
  • 55. ● 여기까지가 3rd Phase 끝 ○ 여기서 배포하면 테스트하지 않은 수 많은 에러가 발생 ○ 그러면 배포 전에 무엇을 할 것인가? ● 이제 4th Phase ○ 프로젝트 규모가 크다면 모든 것을 다 테스트할 수 없다 ○ 꼭 해야 할 것들만 추려서 테스트 진행 Start EDD? 3th Phase3th Phase
  • 56. 4단계 - Test & Debug 주요기능만 test하고 넘어가자
  • 57. ● 4th Phase 목표 - py2에서랑 똑같이 동작하도록 만들기 ○ 모든 코드 모듈간 인터페이스를 py2에서와 같게 만들면 모든게 해결 ○ 최소한의 수정만으로 같게 만드는 것이 중요 ○ 그래야 뒤끝이 없다 ● 꼭 해야 하는 최소한만 테스트 하고 넘어가자 Test & Debug 4th Phase
  • 58. ● 수 없이 많은 에러를 최대한 빠르게 캐치하고 트러블슈팅 ○ 기록해둔 것만 서로 다른 에러 20여건 ○ 상당수는 배포 이후 발견한 것들 ● 특히 만나기 쉬운 에러들 소개 ○ Library Issue (non-std library) ○ Python Issue (std library) Runtime Error 소개 4th Phase4th Phase
  • 59. ● MacOS sierra 이상에서 발생 ● 2.1.0에서 6.2.1로 업그레이드 Library Issue - ipython 4th Phase4th Phase
  • 60. Library Issue - Supervisor in py3 ● py2에서 Supervisor를 사용 ○ process management & daemonizing ● Supervisor가 py3를 지원하지 않는다! ○ 최신 버전은 3.3.4 ○ 4.0.0 버전업에서 py3 지원예정 4th Phase4th Phase
  • 61. Library Issue - Circus ● py3에서는 Supervisor 대신 alternative로 circus 사용 ● Supervisor보다 장점이 많다 ○ configuration이 명시적이고 documentation이 더 잘되어 있음 ○ stderr redirection customizing 가능 ○ more developer friendly ○ advanced web interface 제공 ○ circus-top 등 여러가지 강력한 monitoring feature 제공 ○ 생태계가 작다는건 단점 4th Phase4th Phase
  • 62. Library Issue - Circus 주의사항 5th Phase ● circusd도 같은 환경에서 실행 필요 ○ copy_env, virtualenv값 반드시 정의 4th Phase4th Phase
  • 63. ● hive-python interface library ● pyhive[hive]==0.2.1에서 ● PyHive==0.5.1로 바꿔서 해결 Library Issue - pyhive 4th Phase4th Phase
  • 64. Library Issue - botocore ● AWS python SDK ● botocore==1.4.66에서 ● botocore==1.9.22로 바꿔서 해결 4th Phase4th Phase
  • 65. ● 두 라이브러리 모두 사용 ○ Unirest가 py3를 지원하지 않음 ○ Requests는 py2, py3 호환 ● Requests만 사용하는것으로 변경 ● 두 라이브러리의 usage가 꽤 다름 ○ Unirest에는 callback이 있고 Requests에는 없음 ○ Response 구조도 달라서 다 대응해줘야 함 Library Issue - Unirest vs Requests 4th Phase4th Phase
  • 66. ● django-revproxy==0.9.13 사용하는데 아래 에러 발생 ● urllib3==1.22 사용중인 것이 원인 ● pip check ○ django-revproxy==0.9.13 urllib3 <1.17,>=1.12 Library Issue - django-revproxy 4th Phase4th Phase
  • 67. Library Issue - django-revproxy ● 하지만 requests때문에 urllib3 다운그레이드 섣불리 못함 ● pip check ○ django-revproxy==0.9.13 urllib3 <1.17,>=1.12 ○ requests==2.18.4 urllib3 <1.23,>=1.21.1 ● 구서버에서는 requests==2.4.2 사용 ○ 이 버전은 py3에서 사용 불가능 4th Phase4th Phase
  • 68. Library Issue - django-revproxy ● requests==2.14.0가 py3지원하는 가장 낮은 버전 ● requests==2.14.0은 urllib3 version dependency 정보를 홈페이지를 뒤져도 찾을 수 없음! ○ EDD답게 requests==2.14.0로 일단 downgrade하고 critical feature test 진행 → 이상 없음! 4th Phase4th Phase
  • 69. ● cryptography를 사용해 private key 생성시 에러 발생 ○ encryption할 피암호화 값은 당연히 bytes여야 함 Python Issue - encoding for encryption 4th Phase4th Phase
  • 70. ● cryptography를 사용해 private key 생성시 에러 발생 ○ encryption할 피암호화 값은 당연히 bytes여야 함 Python Issue - encoding for encryption 4th Phase 변경전 변경후 4th Phase
  • 71. ● hashlib.sha512 사용할 때도 마찬가지 Python Issue - encoding for encryption 4th Phase4th Phase
  • 72. ● hashlib.sha512 사용할 때도 마찬가지 Python Issue - encoding for encryption 4th Phase 변경전 변경후 4th Phase
  • 73. ● open 함수 decode codec ○ py2 byte strings ○ py3 utf-8 ○ 문제는 utf-8 codec은 0x1f 0x8b라는 gz 파일의 magic number를 decode하지 못한다! Python Issue - read gzip by utf-8 4th Phase4th Phase
  • 74. ● gzip.open으로 바로 initiation해서 해결 ● 물론 open 함수를 rb로 열어도 된다 Python Issue - read gzip by utf-8 4th Phase4th Phase
  • 75. Python Issue - read gzip by utf-8 4th Phase error error OK bytes OK bytes OK but str OK bytes 4th Phase
  • 76. ● gzip을 사용하는 다른 코드에서도 encoding issue Python Issue - read gzip 4th Phase 변경전 변경후 4th Phase
  • 77. ● gzip을 사용하는 다른 코드에서도 encoding issue ● 이를 아래처럼 고치려 했다면? Python Issue - read gzip 4th Phase4th Phase
  • 78. Python Issue - read gzip by utf-8 4th Phase ● 당연히 상기한 에러 발생! 왜냐면 gz 파일을 utf-8로 decode했으므로 ● 이를 아래처럼 고치려 했다면? Error 4th Phase
  • 79. ● gzip을 read할 때 말고 write할 때도 encoding 이슈 발생 Python Issue - write gzip 4th Phase json obj newfilegzip file read & parsing by str write with wb mode 4th Phase
  • 80. ● gzip을 read할 때 말고 write할 때도 encoding 이슈 발생 Python Issue - write gzip 4th Phase json obj newfilegzip file read & parsing by str write with wt mode 변경전 변경후 4th Phase
  • 81. ● Mysql Bit(1) Field에 대해 django cursor로 SQL select 쿼리를 call하면 ○ b‘True’, b‘False’ 가 아닌 ○ b‘x00’, b‘x01’ 를 return Python Issue - Mysql Bit(1) edge case 4th Phase4th Phase
  • 82. ● Mysql Bit(1) Field에 대해 django cursor로 SQL select 쿼리를 call하면 ○ b‘True’, b‘False’ 가 아닌 ○ b‘x00’, b‘x01’ 를 return ● 그래서 다음과 같은 함수를 사용해야 했다 Python Issue - Mysql Bit(1) edge case 4th Phase4th Phase
  • 83. ● Mysql Bit(1) Field에 대해 django cursor로 SQL select 쿼리를 call하면 ○ b‘True’, b‘False’ 가 아닌 ○ b‘x00’, b‘x01’ 를 return ● 그래서 다음과 같은 함수를 사용해야 했다 ● 하지만 이는 에러나기 딱 좋은 사용법 Python Issue - Mysql Bit(1) edge case 4th Phase4th Phase
  • 84. ● py2에서는 str, bytes가 똑같아 b‘x00’가 들어올 때 정상동작 ● py3에서는 str, bytes가 달라서 b‘x00’가 들어와도 True 리턴! ○ 이 때문에 수많은 False여야 할 데이터가 True로 저장 ○ Exception 발생이 아니니까 온갖 에러가 다 발생하고서야 알아챔 Python Issue - Mysql Bit(1) edge case 4th Phase4th Phase
  • 85. ● py2에서는 str, bytes가 똑같아 b‘x00’가 들어올 때 정상동작 ● py3에서는 str, bytes가 달라서 b‘x00’가 들어와도 True 리턴! ○ 이 때문에 수많은 False여야 할 데이터가 True로 저장 ○ Exception 발생이 아니니까 온갖 에러가 다 발생하고서야 알아챔 ● 근데 더 문제는 이 함수의 사용처 Python Issue - Mysql Bit(1) edge case 4th Phase4th Phase
  • 86. Python Issue - Mysql Bit(1) edge case 4th Phase before 2to3 ● 데이터 적재 전 전처리 하는 함수 ● b‘x00’을 False로 바꾸는 작업 등을 했던 것 ● 문제는 두번째 if 조건이 bytes가 아니라 str ● 물론 py2에선 str == bytes 이므로 이상 무 4th Phase
  • 87. Python Issue - Mysql Bit(1) edge case 4th Phase before 2to3 after 2to3 4th Phase
  • 88. Python Issue - Mysql Bit(1) edge case 4th Phase after 2to3 ● py3에선 str != bytes ● 따라서 더 이상 조건문의 의도대로 되지 않음 ● 조건문의 위치까지 공교롭게도 convert_to_boolean이 quote_or_null 보다 먼저 4th Phase
  • 89. Python Issue - Mysql Bit(1) edge case 4th Phase after 2to3 ● 조건문의 위치까지 공교롭게도 convert_to_boolean이 quote_or_null 보다 먼저 ● 온갖 스트링이 다 True가 됨 after 2to3 4th Phase
  • 90. ● 만약 b‘x00’, b‘x01’ 대신 b‘False’, b‘True’였다면? ○ eval(value) 사용으로 py2, py3에서 모두 문제 없이 동작 ● 조건문 고쳐서 해결 Python Issue - Mysql Bit(1) edge case 4th Phase4th Phase
  • 91. ● __unicode__ vs __str__ ○ py2에선 __unicode__만 정의해둬도 print를 할 때 __str__ 정의된 것처럼 실행 (bytes로 return) ○ py3에선 str == unicode 이므로 그렇지 않음 ○ py3는 그래서 __str__ 함수를 따로 만들어주어야 함 Python Issue - __unicode__ vs __str__ 4th Phase 4th Phase4th Phase
  • 92. ● django decorator 중 python_2_unicode_compatible라는 것 존재 ○ py3에서 __str__을 unicode return 하도록 정의하면 ○ py2에서 __str__ returns bytes, __unicode__ returns unicode ○ 이를 이용해 py2, 3 공존 가능 Python Issue - __unicode__ vs __str__ 4th Phase 4th Phase4th Phase
  • 93. ● django orm .count ○ py2에서는 .count > 0 도 가능 ○ py3에서는 .count() > 0 만 가능 Python Issue - Comparison 4th Phase 4th Phase4th Phase
  • 94. Python Issue - Comparison 4th Phase 4th Phase ● NoneType Comparison ○ py2 ○ py3 4th Phase
  • 95. ● django dispatcher의 request ○ requests.body가 bytes 타입! ○ str vs bytes 문제 발생하기 좋음 Python Issue - 여러가지 위험요소들 4th Phase4th Phase
  • 96. ● 나눗셈 변화 ○ py2 ○ py3 Python Issue - 여러가지 위험요소들 4th Phase4th Phase
  • 97. ● __cmp__ deprecated ○ py2에는 class 내의 __cmp__ 함수로 compare함수 정의 가능 ○ py3에는 __cmp__ 없음 ○ __lt__, __le__, __gt__, __ge__, __eq__, __ne__ 각각 정의해줘야 함 Python Issue - 여러가지 위험요소들 4th Phase4th Phase
  • 98. ● Exception 구조 변화 - message 없어짐 ○ py2 ○ py3 Python Issue - 여러가지 위험요소들 4th Phase4th Phase
  • 99. ● flush() 함수 사용할 필요 없어짐 ● py2에서는 5초뒤 한꺼번에 0, 1, 2, 3, 4 ● py3에서는 1초에 한번씩 0, 1, 2, 3, 4 ● py2에서 의도한대로 출력하려면 주석처리된 flush함수 사용해야 함 Python Issue - 여러가지 위험요소들 4th Phase4th Phase
  • 100. ● 여기까지가 4th Phase 끝 ○ 여기에 소개된 에러들 중 상당수는 배포 이후에 만남 ○ EDD의 현장 기록들 Test & Debug 3th Phase3th Phase
  • 101. 5단계 - Deploy 배포한 이후에도 에러를 많이 만날 수 있음
  • 102. ● 주요 테스트를 끝내고 이제 서버를 새로 띄우자 ● py2 서버는 바로 내리지 말고 안정화 될 때까지 상비 ● server migration todo list 다섯 가지 배포 crontab supervisor & circus django 외 다른 nginx servers batch job cache & message queue 5th Phase
  • 103. 배포 흐름에 따른 Branch 관리 1. new server 구축 2. 상기한 5가지 migration 작업 진행 및 트러블 슈팅하며 안정화 3. branch feature/5-phase-deploy-for-py2 from master merge feature/5-phase-deploy-for-py3 into master 4. 배포 branch 변경 5th Phase new server feature/5-phase-deploy-for-py3 old server master 5th Phase new server master old server feature/5-phase-deploy-for-py2 5th Phase
  • 104. crontab migration ● crontab task들은 진행전 체크할 것이 많다 ○ 구 서버 system timezone은 어디인가 ○ 여러번 재실행해도 되는 task인가 ○ 아무때나 재실행해도 되는 task인가 5th Phase5th Phase
  • 105. crontab migration ● crontab task들은 진행전 체크할 것이 많다 ○ 구 서버 system timezone은 어디인가 → KST ○ 여러번 재실행해도 되는 task인가 → 그런 것도 있고 아닌 것도 있다 ○ 아무때나 재실행해도 되는 task인가 → 그런 것도 있고 아닌 것도 있다 5th Phase5th Phase
  • 106. crontab migration ● 실서버 테스트 할 수 있는건 즉각 테스트 및 migration ● 테스트 불가능하면 테스트 환경에서 테스트 ○ 하루 정해진 횟수, 정해진 시간에만 실행되도록 조건부 migration 진행 5th Phase5th Phase
  • 107. crontab migration ● timezone UTC에서 KST로 변경 및 crontab 재시작 5th Phase5th Phase
  • 108. crontab migration ● timezone UTC에서 KST로 변경 및 crontab 재시작 ● 이를 해주지 않으면? ○ timing depend한 cron job에서 문제 발생 5th Phase5th Phase
  • 109. crontab migration ● 만약 system time을 변경하지 않은걸 나중에서야 발견했다면? ○ 늦게라도 timezone 바꾸고 하루에 한 번씩만 돌아가야 하는 task들 정리 ○ KST(target timezone) 기준으로 하루 한 번씩만 돌아가도록 조건부 migration 5th Phase5th Phase
  • 110. django 외 다른 nginx servers ● 에러날 경우 구 서버에 proxy 해주는게 방법 5th Phase5th Phase
  • 111. ● crontab이 아니더라도 여러가지 batch job이 돌아갈 수 있다 ○ data engineering을 한다면 특히 많을 수밖에 ● 이를 하나하나 새로운 서버로 옮기는걸 잊지 말자 ○ airflow를 사용하는데 일부 batch job이 서버 이전 작업에서 누락되어 구서버에서 돌아가는 문제를 겪음 ○ py2, py3 환경이 아예 다르기 때문에 큰 문제 발생 가능 Batch Job 5th Phase5th Phase
  • 112. ● cache와 message queue도 py3 서버용 새로 구축 ○ cache, MQ의 python interface protocol이 달라질 수 있다 cache & message queue 5th Phase5th Phase
  • 113. ● django cache를 사용하다 보니 이 에러 발생 ● py2 서버와 py3 서버 모두 운용할 때 발생 ● 이게 뭘까? unsupported pickle protocol: 4 5th Phase5th Phase
  • 114. ● pickle은 python의 serialization 모듈 이름 ○ pickling == serialization, unpickling == deserialization ○ py2.7는 protocol 2 ○ py3.6은 protocol 4 unsupported pickle protocol: 4 5th Phase5th Phase
  • 115. ● py2 서버와 py3 서버가 cache를 공유하면서 발생한 것 ○ py3에서 protocol 4로 pickling해서 cache에 set data ○ py2에서 protocol 2로 해당 data를 unpickling할 때 발생 ○ 각 서버에서 서로 다른 cache를 사용하도록 따로 설정해줘야 함 unsupported pickle protocol: 4 5th Phase5th Phase
  • 116. ● gitignore 된 파일들의 python version ● py3 코드가 py2 interpreter로 돌아가는 경우 ○ 반대의 경우도 존재 주요 이슈들의 contexts 5th Phase5th Phase
  • 117. ● python 버전업 문제도 많지만 서버 migration 문제도 아주 많다 ● 심오한 기술적인 문제보다 human error가 훨씬 많이 발생 ○ 작업이 잘못된다거나, 누락된다거나, 멈춘다거나 등등 ● system entropy 관리 문제가 human error의 근본 원인 ○ 항상 간단한 List up을 하는 것이 문제 해결의 시작! 주요 이슈들의 contexts 5th Phase5th Phase
  • 118. 정리
  • 119. ● 기본적으로 여섯 가지 branch를 만들자 ● 앞의 1 ~ 4단계 개별로 하나씩 Git branch 관리방법 정리
  • 120. ● 기본적으로 여섯 가지 branch를 만들자 ● 앞의 1 ~ 4단계 개별로 하나씩 ● 이전 단계의 브랜치의 변경사항이 생기면 ○ 뒤 단계 브랜치들에는 바로바로 merge! Git branch 관리방법 정리정리
  • 121. ● 추가적으로 배포용 브랜치 두 개 ○ 하나는 py3 베타테스트 용도, 다른 하나는 py2 백업 용도 ○ py2 백업 브랜치는 django 서버가 두 종류라면 무조건 있어야 한다! Git branch 관리방법 정리정리
  • 122. ● py2, py3 공생시키기 vs py3로 갈아 엎기 ○ porting에 어려움이 있는게 아니라면 후자가 낫다 ○ 처음 시작하는 프로젝트는 무조건 python3로 개발하자 ○ py2가 필요한 부분이 분리가능하다면 레포를 분리 ○ 그래도 해야 한다면? Py2, Py3 공생시키기 정리정리
  • 123. Py2, Py3 공생시키기 ● future, six 사용하기 ● py2, py3의 차이점들 이해하기 ● 추천자료 ○ 김태환, Python 2 와 3 공존하기, pycon 2017, https://www.pycon.kr/2017/program/151 ○ Ed Schofield, Writing Python 2-3 compatible code, python-future, http://python-future.org/compatible_idioms.html 정리정리
  • 124. ● EDD가 효율적인 이유? ○ 계획 세우는 비용을 아낄 수 있어서 ○ 보통은 테스트 & 디버깅 한 번 만에 해결이 돼서 ○ 목표에 바로 도달할 수 있어서 소감 정리정리
  • 125. ● 하다보니 그냥 한 번에 에러가 나서 서버가 바로 죽어주는게 차라리 고마웠다. ○ 데이터가 바뀌거나 무결성 깨져서 나중에야 그걸 알게되고 뒷수습하는 일이 더 힘들었음 소감 정리정리
  • 126. ● 2to3 conversion을 안전하고 빠르게 하려면? ○ 첫 째도 list up, 둘 째도 list up ○ list up이 한계가 있다면 의존성 관리를 사람이 하지 말고 코드에게 시키는 것만으로도 어느 정도 개선됨 소감 정리정리
  • 127. ● 좋았던 점 ○ Pycon 2018 발표 ○ asyncio 사용 중 ○ ipython 추가기능, 여러가지 django extension들 사용 ○ django 버전업 가능 ○ 버전업하고 팀내 신규 입사자 6명 소감 정리정리
  • 128. ● Kristjan Wager, Error-driven Software Development, http://errordrivendevelopment.blogspot.com/2009/06/error-driven-software-development.html ● 김태환, Python 2 와 3 공존하기, pycon 2017, https://www.pycon.kr/2017/program/151 ● Ed Schofield, Writing Python 2-3 compatible code, python-future, http://python-future.org/compatible_idioms.html ● Timothy Bramlett, Strings Bytes and Unicode in Python 2 and 3, https://timothybramlett.com/Strings_Bytes_and_Unicode_in_Python_2_and_3.html ● python, Standard Encodings, Python Library Reference https://docs.python.org/2.4/lib/standard-encodings.html 참고 문헌 정리정리