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 주의사항
개요개요
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
22. ImportError 예시 - relative import
● 모든 import statements는 absolute import로 하자
● relative import를 하고 싶다면 leading dots라는
특수 문법을 동원하여 explicit 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
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
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
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
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
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
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
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
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
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
참고 문헌
정리정리