Python 3.6 f-string으로 마이그레이션

배경

사내 데이터 파이프라인 프로젝트를 Python 3.6으로 업그레이드하면서 f-string을 도입하기로 했다. 기존 코드는 % 포맷팅과 .format()이 혼재되어 있었고, 특히 로깅 메시지에서 가독성이 떨어졌다.

기존 코드

logger.info('Processing user %s with %d items' % (user_id, item_count))
query = "SELECT * FROM users WHERE id = {} AND status = '{}'".format(user_id, status)
error_msg = 'Failed to process: %s' % str(exception)

세 가지 방식이 섞여 있어서 일관성이 없었다.

변경 후

logger.info(f'Processing user {user_id} with {item_count} items')
query = f"SELECT * FROM users WHERE id = {user_id} AND status = '{status}'"
error_msg = f'Failed to process: {exception}'

훨씬 읽기 쉬워졌다. 특히 변수가 많은 경우 차이가 두드러졌다.

마이그레이션 과정

정규식으로 일괄 변경하려다가 예외 케이스가 많아서 수동으로 진행했다. SQL 쿼리 부분은 인젝션 위험 때문에 parameterized query로 별도 처리했다.

# 잘못된 예시 (SQL injection 위험)
query = f"SELECT * FROM users WHERE name = '{name}'"  # NO

# 올바른 예시
query = "SELECT * FROM users WHERE name = %s"
cursor.execute(query, (name,))  # YES

결과

약 200개 파일, 1500여 줄의 문자열 포맷팅을 변경했다. 코드 리뷰 시 로직 파악이 빨라졌다는 피드백을 받았다. Python 3.6의 다른 기능들도 점진적으로 도입할 계획이다.