async generator에서 `yield from` 위임이 막히는 게 왜 실무에서 아픈지: PEP 828 이후의 코드 모양 요즘 파이썬 서비스에서 “스트리밍”은 특수 기능이 아니라 기본 도구가 됐다. 토큰 스트림, 이벤트 스트림, 로그 스트림, 진행률 스트림. 그러다 보면 레포에 비슷한 래퍼가 늘어난다. 원본 스트림에 메타데이터를 붙이는 래퍼 중간에 관측(로그/메트릭)을 끼워 넣는 래퍼 오류를 분류해서 한 번만 바꿔 던지는 래퍼 이 래퍼들은 대개 “위임”이 대부분이다. 본체는 원본 스트림이고, 나는 옆에서 잠깐 만져서 다시 흘려보내고 싶다. 동기 제너레이터라면 여기서 생각이 끝난다. yield from 으로 넘기면 된다. 그런데 async generator에서는, 그 자연스러운 동작이 막혀 있다. 그래서 개발자는 갑자기 ‘동작’을 구현하기 시작한다. async for 로 한 번 더 감싸고, 예외 전달을 고민하고, 종료 처리를 붙인다. 기능은 얇은데 코드가 두꺼워진다. 최근 Discourse에서 이 문제가 다시 뜨겁게 논의됐고, PEP 828로 정리되면서 “이제는 이야기만이 아니라 언어 차원에서 다뤄보자”는 분위기가 만들어졌다(참고자료). CPython 레퍼런스 구현까지 공개되면서, 실무 입장에서도 “어떻게 바뀔지”를 손에 잡히게 상상할 수 있게 됐다. 위임이 막히는 순간은 늘 ‘얇은 래퍼’에서 온다 문제가 터지는 장면은 거창하지 않다. 얇은 래퍼 하나 만들다가 시작한다. 예를 들어 어떤 스트림을 감싸서, 처음 한 번만 시작 이벤트를 넣고 싶다. 혹은 스트림이 끝날 때 한 줄 로그를 남기고 싶다. 동기 코드라면 래퍼는 깔끔하다. 앞에 한 줄, 뒤에 한 줄, 가운데는 yield from . async generator에서는 그 가운데가 금지다. 그래서 아래 같은 모양이 “하고 싶은데 못 하는” 코드로 남는다. async def wrapped(src): # (앞에서 이벤트 한 번 넣고) ...
배포가 자꾸 사람을 괴롭힌다면: publish를 ‘플러그인 가능한 동작’으로 바꾼 날 해커톤 마지막 날 오후였다. 누군가 노트북을 돌려 보여주면서 말했다. “앱은 돌아가요. 근데 배포만 하면 끝에서 항상 막혀요. 우리도 웹으로 올리는 publish 하나만… 딱 하나만 넣어주면 안 돼요?” 그 방에는 두 종류의 사람이 있었다. 한쪽은 바로 고개를 끄덕였다. “좋아, 커맨드 하나 추가하자.” 다른 쪽은 얼굴이 굳었다. “그거, 커맨드 하나로 끝나는 일이 아니야.” 나는 그 사이에서, 슬쩍 겁이 났다. 코드를 고치는 일은 익숙한데 배포는 늘 낯설었다. 특히 파이썬 프로젝트에서 배포는 더 그랬다. 어떤 팀은 SFTP로 올리고, 어떤 팀은 대시보드에서 클릭하고, 어떤 팀은 누군가의 로컬 스크립트를 빌려 쓴다. 그 스크립트는 빠르지만, 늘 한 사람의 기억에 의존한다. 그날 기능요청은 “웹 배포”였지만, 실제로 우리를 괴롭힌 건 다른 질문이었다. ‘publish’라는 동작을 어디까지 책임지게 할 건가? 문서에 배포 방법을 적어두면 된다고 생각했는데, 문서는 늘 늙었다. 호스팅 화면이 바뀌고, 인증 방식이 바뀌고, 팀원이 바뀌고, 무엇보다 “배포를 잘 아는 사람”이 바뀐다. 배포가 문서에 붙어 있는 순간, 배포는 기술이 아니라 기억력 시험이 된다. 이 글은 며칠 전 읽은 한 사례에서 시작한다. BeeWare Briefcase가 PythonAnywhere를 publish 타깃으로 붙인 과정과, 그 과정에서 briefcase publish web 이 어떻게 논의되는지를 보면(참고자료), 이 문제가 “특정 호스팅의 사용법”이 아니라 구조의 문제라는 게 드러난다. 그리고 구조를 바꾸지 않으면, 팀은 배포를 할수록 더 느려진다. (링크는 맨 아래에만 모았다.) “그럼 PythonAnywhere는 누가 알아야 하죠?”라는 질문 처음엔 다들 단순하게 생각한다. “PythonAnywhere API로 업로드하면 되지.” 그...