Python 2.7에서 3.6으로 마이그레이션 작업 회고
배경
3년간 운영 중인 Django 1.8 프로젝트가 Python 2.7로 돌아가고 있었다. 2020년 2.7 지원 종료를 앞두고 Python 3.6으로 마이그레이션 작업을 시작했다.
주요 이슈
1. unicode vs str
Python 2에서 가장 골치 아팠던 부분이 문자열 처리였다.
# Python 2.7
def get_user_name(user):
return u"{}".format(user.name.encode('utf-8'))
# Python 3.6
def get_user_name(user):
return "{}".format(user.name) # 기본이 unicode
2. print 함수 변환
# Before
print "Debug:", value
# After
print("Debug:", value)
2to3 도구로 자동 변환했지만, 로깅이 섞인 부분은 수동 검토가 필요했다.
3. 라이브러리 호환성
celery, redis-py, psycopg2 등 주요 라이브러리는 3.6을 지원했지만, 사내에서 만든 헬퍼 모듈들이 문제였다. iteritems(), has_key() 같은 메서드들을 일일이 수정했다.
# Python 2
for key, value in dict.iteritems():
pass
# Python 3
for key, value in dict.items():
pass
전환 전략
six 라이브러리를 활용해 2/3 호환 코드를 먼저 작성하고, 테스트를 통과시킨 뒤 Python 3 전용 문법으로 정리하는 방식을 택했다.
import six
if six.PY2:
# Python 2 specific
else:
# Python 3 specific
결과
약 2주간의 작업 끝에 스테이징 환경 배포를 완료했다. 성능은 체감상 비슷했고, f-string 같은 새 기능을 쓸 수 있게 된 게 가장 큰 수확이다.