문화
개요
과기특성화대학 공동운영 산학협력(CUop)에 지원하여 래블업 주식회사(이하 래블업)에서 8주간 인턴으로 근무했다.
온보딩, Backend.AI 개발, PyCon 참가를 통해 경험한 것들을 작성했다.
지원 동기
우연히 보게된 PyCon 발표 세션을 통해 래블업에 대해 처음 알게 되었다. 기술적으로 깊이 있고 열정이 있는 구성원이 많은 회사라는 것을 알 수 있었다. 나는 Python과 비동기 프로그래밍에 관심이 많았기 때문에 래블업을 지원했다.
온보딩
첫 2주동안 온보딩 과정을 진행했다.
Realtime Web Chat 구현, Backend.AI 개발 환경 구축, 코드 베이스 세미나 순서로 진행했다.
Realtime Web Chat
Python asyncio에 친숙해지기 위한 과제이다. 실시간 채팅 앱을 비동기 웹 프레임워크인 aiohttp와 인메모리 데이터베이스인 redis를 이용해서 개발했다. 그리고 python과 redis를 한 번에 빌드하기 위한 docker compose를 설정하는 것도 과제에 포함되었다. 자세한 내용은 Github Readme를 참고하면 된다.
redis를 통해 메시지를 broadcast 하기 위해 Redis pub/sub을 이용했다. pub/sub은 메시지를 저장하지 않고 그대로 전달하는 플랫폼 역할을 한다. 메시지를 따로 저장하는 요구사항이 없었으므로 Redis pub/sub을 이용했다. 또한, Redis pub/sub 과정을 asyncio.create_task()를 통해 task로 등록하여 event loop에 의해 동작하도록 했다. Realtime Web Chat 실행 화면
asyncio의 기본 동작에 대해 이해할 수 있었다. 어려운 부분은 질문하며 해결할 수 있었다. 래블업에서는 Microsoft Teams를 통해 자유롭게 질의응답을 할 수 있어 인턴 및 주니어 개발자가 성장할 수 있는 환경을 갖추었다고 생각한다.
Backend.AI 개발 환경 구축
Backend.AI를 VM Farm 및 로컬 VM에 설치하여 직접 실행해보았다. 공식 문서를 읽으며 진행했는데 그 과정이 순탄치 않았다. 다양한 에러를 마주 했는데 인턴 동기들과 공유도 하고 Teams에 질문도 하며 해결했다.
💡 VM Farm은 가상 머신(Virtual Machine)을 관리하고 실행하는 환경을 뜻한다. 래블업은 독자적인 VM Farm을 가지고 있다.
그동안은 로컬에서만 개발을 했었는데 VM Farm과 VSCode를 SSH로 연결하여 개발하는 경험을 처음 해보았다. Backend.AI를 개발하기 위해서는 여러 프로세스들 (Manager, Agent, Storage proxy, Web server 등)과 Docker Container들을 실행해야 한다. 랩탑을 사용할 경우, 배터리에 부담이 가는 수준이다. 하지만 VM Farm을 사용하면 SSH 연결만 하면 되기 때문에 가볍게 Backend.AI를 개발할 수 있다. 실제로 회사 밖에서 랩탑을 충전할 수 없던 상황에서 VM Farm을 사용하여 오랫동안 개발할 수 있었다.
코드 베이스 세미나
Backend.AI에서 어려운 부분을 중심으로 코드를 본 후, 이해한 내용을 바탕으로 발표하는 세미나를 준비하게 되었다. Manager, Agent, GraphQL 중에서 나는 Manager 파트 발표를 맡았다.
Backend.AI는 오픈소스이기 때문에 공식 문서가 잘 쓰여 있다. 공식 문서를 보면서 전체적인 구조를 파악하고 궁금한 부분은 직접 사원분들에게 여쭤보면서 Backend.AI 아키텍처 공부를 진행했다. Backend.AI Manager의 Session / Kernel 생성, 스케줄링 제어가 발표 주제였기 때문에 Manager 코드를 보면서 manager process의 로그를 분석하는 방식으로 공부를 진행했다. 세미나 발표를 준비하며 그렸던 시퀀스 다이어그램
로그를 분석하며 Session 상태가 Preparing에서 다시 Pulling으로 돌아가는 버그를 발견했다. 로그를 하나씩 분석한 보람(?)을 느꼈다. 비동기 코드 베이스라 로그를 순서대로 분석하는게 어려웠다. 하지만 Call graph와 시퀀스 다이어그램을 그리는 것이 큰 도움이 되었다.
Backend.AI 개발
온보딩이 끝나고 Backend.AI 개발을 시작했다. GitHub Issue를 보고 자발적으로 지원하거나 이슈를 직접 발견해 해결하는 방식으로 진행했다.
Backend.AI repository 에서 9개의 Pull Request, Backend.AI-WebUI repository 에서 2개의 Pull Request를 생성했고 모두 Merge 되었다!
나는 우선순위가 높은 이슈 중에서 자신 있는 것들을 골라 해결했다. 두달이라는 짧은 시간동안 최대한 많은 기여를 하고 싶었기 때문이다.
첫 PR
https://github.com/lablup/backend.ai/pull/1395
세미나를 준비하면서 찾아낸 버그를 수정하는 PR을 생성했다. API Parameter를 수정하면 되는 쉬운 PR 이었다. 하지만 branch name convention, commit convention, news fragment에 대해서 알 수 있었다. 그리고 GitHub Actions에 의한 CI (Countinuous Integration, 지속적 통합) 과정을 경험하고 Git 관련 여러 삽질도 미리 할 수 있었던 좋은 경험이었다.
💡 news fragment는 PR에 의해 생성된 브랜치가 무엇을 하려는 브랜치인지 한 문장으로 설명하는 Markdown이다. 미래에 다시 이 PR을 봤을 때, 무엇을 하려 했던 PR이었는지 알 수 있도록 간단명료하게 작성해야 한다.
vfolder 관련 PRs
Teams에 인턴에게 줄 만한 이슈가 있다는 소식을 듣고 바로 지원했다. vfolder라는 새로운 개념을 공부해야 했지만, 이렇게 제품에 대해 이해해 나간다는 것이 중요할 것 같았다.
PR (1)
https://github.com/lablup/backend.ai/pull/1397
project type vfolder는 admin만이 생성할 수 있다. keypair resource policy의 max_vfolder_count에 상관없이 vfolder를 생성할 수 있어야 하는데 user type vfolder가 max_vfolder_count를 넘어설 경우, project type vfolder를 생성할 수 없는 이슈였다. 처음에는 용어부터 헷갈렸지만 코드를 분석하고 질문도 하며 용어를 해석할 수 있었다.
PR (2)
https://github.com/lablup/backend.ai/pull/1400
PR (1)을 해결하며 발견한 새로운 버그들을 해결했다.
PR (3)
https://github.com/lablup/backend.ai/pull/1417
PR (1) 이슈와 연관된 이슈를 발견했다. DB migration과 GraphQL이라는 새로운 개념이 등장했지만 해보고 싶었던 것들이라 지원했다. Alembic이라는 DB migration 툴을 이용했다. 그리고 GraphQL 스키마 개념을 공부하고 하위 호환성을 지원하기 위해 query와 mutation 코드를 수정했다. 수정한 코드를 테스트하기 위해서 cURL을 사용하려 했지만 GraphQL은 REST API 보다 훨씬 긴 request 형태를 가지고 있어서 번거로웠다. GraphQL을 잘 알고 있는 인턴과 사원분에게 질문하며 test code를 작성했다. CLI 형태로 간편하게 수정한 query와 mutation을 테스트하는 python code를 작성하여 테스트를 편하게 할 수 있었다.
WSProxy 관련 PRs
Teams에 이슈가 올라와 지원하였다. WebUI에서 resource group의 wsproxy 주소가 유효하지 않은 경우, 세션 삭제가 불가능한 버그가 있었다. WebUI 개발도 경험해보고 싶어 지원했다.
PR (1)
https://github.com/lablup/backend.ai/pull/1423
이슈를 해결하기 위해 WebUI 코드를 읽어봤는데 wsproxy의 개념이 잘 잡히지 않았다. wsproxy에는 v1과 v2가 있다는 것을 알았는데 둘의 차이를 알기 쉽지 않아서 사원분들에게 질문했다. v1과 v2의 가장 큰 차이는 트래픽의 경로였다. v1은 manager를 거쳐서 컨테이너와 통신하는 반면, v2는 manager를 거치지 않고 바로 컨테이너와 통신할 수 있어 더 빠르다. wsproxy가 어떤 역할과 v1, v2의 차이를 알고 나니 코드가 어떻게 동작하는지 더 수월하게 알 수 있었다. 그리고 생각보다 많은 사원분이 차이를 잘 모르는 것을 알게 되었다. 쉬워 보이는 질문이 조직 안에서 나오지 않은 질문일 수도 있음을 깨달았다.
PR (2)
https://github.com/lablup/backend.ai-webui/pull/1819
이슈를 해결하기 위해서 webui 코드도 수정했다. JavaScript 코드를 수정하기 위해서 Callback 함수, Promise 객체, async/await에 관해 공부했다. 다른 로직에 영향이 가지 않도록 에러 핸들링을 했고, 중복된 코드는 함수로 따로 정의 하여 코드의 중복을 없앴다.
PR (3)
https://github.com/lablup/backend.ai-webui/pull/1833
그런데 WebUI는 Backend.AI 22.09와 하위 호환성을 유지해야 하므로 HTTP Status 404도 처리해야 한다는 CEO님의 리뷰가 있어 404와 500을 모두 처리하도록 했다.
PR (4)
https://github.com/lablup/backend.ai/pull/1466
그런데 코드가 병합된 후에 버그가 발생했다. v1 wsproxy 설정 시, wsproxy-version에 대한 리턴값이 사라지는 버그였는데 내가 core 코드를 수정하다가 모든 분기에 대해 처리하지 못해서 생긴 버그였다. 급하게 코드를 수정했지만 간단한 실수라서 아쉬웠다. 이런 실수를 방지하기 위해 테스트 코드를 작성해야겠다는 생각이 들었다.
Manager 관련 PR
https://github.com/lablup/backend.ai/pull/1444
세미나를 준비하며 공부했던 manager에 대한 이슈가 생겼다. 인턴 기간이 얼마 남지 않은 상황에서 내가 가장 잘 알고 있는 코드에 대한 이슈를 해결하는 것이 기여할 수 있는 방법이라 생각했다.
이 PR은 코드 리뷰에 의해 많은 수정이 있었다. 처음에는 scheduler health check와 scheduler trigger를 동일한 API로 설계했었다. 코드 리뷰를 받은 후에, 두 기능을 다른 API로 나누어 책임을 분리했다. 그리고 원래는 schedule 함수에 관해서만 상태 정보를 저장했었는데 prepare 함수와 scale_services 함수에 대해서도 상태 정보를 저장했다. 왜냐하면 scheduler의 글로벌 타이머에 따라서 주기적으로 실행되는 세 개의 함수에 대해 상태 정보를 저장한 후에 trigger API를 만들어야 scheduler의 상태를 완전히 파악할 수 있기 때문이다. 또한, Manager 프로세스가 여러 개일수도 있기 때문에 Manager ID에 따라 scheduler의 상태를 저장할 수 있도록 설계를 바꿨다.
scheduler의 저장소에 대해서도 코드 리뷰가 진행되었다. 처음에는 기존 manager 상태 API에서 manager 상태를 etcd에 저장하는 코드를 보고 동일하게 scheduler의 상태를 etcd에 저장했다. etcd는 일관성을 유지해야 하는 설정 정보를 저장하는 데 유리하지만, write 속도가 느리다. redis는 휘발성이 있는 데이터베이스이지만 read/write가 많아도 성능이 좋다. scheduler 상태를 주기적으로 read/write 하고 일관성을 유지해야 하는 정보는 아니기 때문에 redis에 저장하는 것으로 변경했다.
Agent 관련 PR
https://github.com/lablup/backend.ai/pull/1472
Backend.AI의 Manager 부분을 어느 정도 이해했기 때문에 또 다른 중요한 컴포넌트인 Agent를 이해하고 싶었다. 마침 Agent에 대한 이슈가 생겨서 살펴보았다.
Backend.AI가 실행되는 동안 Agent의 내부 상태와 실제로 동작하는 컨테이너의 상태가 일치하지 않는 버그가 발생했다. 이에 따라 세션을 생성할 때, 실제로는 충분한 자원이 있음에도 불구하고 자원 할당 과정에서 InsufficientResource Error가 발생했다. 에러가 발생했을 때, 자원 할당 과정에서 무엇이 잘못되었는지를 알기 위해서 로깅을 개선할 필요가 있었다.
자원 할당 과정을 파악하는 것에 시간이 오래 걸렸다. 동시성 문제가 어려워서 CTO님과 많은 질의응답을 통해 대략적인 흐름을 파악하고 무엇을 로깅해야 하는지 알 수 있었다.
인턴이 끝나고 몆 주후, CTO님이 10개가 넘는 커밋을 통해 리팩터링과 테스트 코드까지 추가하시고 병합하셨다. 인상 깊었던 것은 에러를 재현하기 위해 테스트 코드를 작성하신 것이었다. 나는 에러를 재현하기 위한 복잡한 과정을 (PR 참고) 직접 수행했다. 그래서 개발 시간이 오래 걸리기도 했다. 이런 부분에서 생산성의 차이가 나타난다는 것을 알 수 있었다. 물론 테스트 코드를 작성할 생각은 했었지만, 구현이 너무 복잡할거라 생각했고 테스트 코드를 작성하느라 인턴이 끝날 것 같다고 생각했었다. 앞으로는 테스트 코드 작성에 너무 겁먹지 않고 일단 해보면서 배워야 겠다고 생각했다. 그리고 리팩터링은 코드 가독성을 중점으로 진행하신 것 같았다. 내가 수정한 부분의 함수가 너무 길어져서 가독성이 좋지 않았는데 리팩터링 후에는 함수가 짧아지고 로깅도 깔끔해져서 가독성이 좋았다. 구현하는데에서 멈추지 않고 좋은 코드를 만들기 위해 노력해야겠다는 생각을 했다.
PyCon 참가
8월 12, 13일에 래블업이 PyCon에 부스를 열었다. PyCon에 후원하는 회사는 부스 활동을 할 기회가 주어진다. 나는 인턴이었지만 부스활동에 참여 하고 발표 세션도 듣고 싶었다. 마침 회사에 PyCon 표가 남았다고 해서 참여할 수 있었다.
래블업 부스에서는 Llama2에게 10줄짜리 피라미드를 프롬프트를 통해 출력하도록 만드는 이벤트를 진행했다. 난이도가 그렇게 쉬운 편은 아니었고, Llama2가 잘 알아들을 수 있도록 풀어서 설명하는 것이 중요했다. 정답을 제출한 분 중 두 명을 추첨하여 닌텐도 스위치, 로지텍 마우스를 증정했다. 나는 부스에서 PyCon 참여자들이 이벤트에 참여할 수 있도록 안내하는 역할을 했다. 그리고 PyCon에 사원분들이 많이 오셨기 때문에 내가 듣고 싶은 발표 세션이 있으면 자유롭게 들을 수 있었다. 래블업은 오픈소스 기반 회사라 오픈소스에 기여하고 컨퍼런스에 참여하는 것을 독려한다. 실제로 PyCon에 참여한 발표자가 총 4명일 정도로 컨퍼런스에 참가하는 것을 중요하게 생각한다.
래블업 주식회사 부스
RustPython 세션 발표 중에 python lint 툴인 flake8과 isort를 대체할 수 있는 ruff라는 툴이 소개되었다. ruff는 Rust로 구성되어 있어 flake8에 비해 100배가 더 빠르다. Backend.AI에서는 flake8, isort를 통해 lint를 했었는데 CTO분이 ruff를 검토해 보시고는 코엑스 계단에서 바로 Backend.AI 프로젝트에 ruff를 도입하시는 것을 지켜보았다. 짧은 시간 내에 프로젝트에 새로운 툴을 적용하고 공식 문서까지 수정하는 것을 보면서 코딩에 관련된 프로세스에 정말 능숙하다고 생각했다. 나도 언젠가는 능숙한 개발자가 되고 싶다고 생각했다. PyCon이 끝나고 업데이트된 공식 문서를 보며 ruff를 Backend.AI 개발환경에 적용하고 lint가 100배 빨리 되는 것을 직접 체험했다. PyCon에 참여하지 않았다면 좋은 툴을 빨리 사용하지 못했을 것이다. 앞으로도 개발자 컨퍼런스에 계속 참여하고 싶다. 래블업 주식회사 구성원분들과 단체 사진
인턴십을 마치며
인턴십을 하며 최대한 많은 경험을 하려고 애썼다. 그리고 많은 기여를 하고 싶었다. 결론적으로, 많은 기여를 하기 위해 노력했기 때문에 많은 것을 경험할 수 있었다. Teams에서 언급되는 이슈에 빠르게 자원했다. 그래서 vfolder, wsproxy, web-ui, manager, agent라는 Backend.AI의 핵심 컴포넌트들을 이해할 수 있었다. 그리고 DB Migration, GraphQL, etcd 등의 새로운 개념들도 학습할 수 있었다. 주말 아침부터 저녁까지 컨퍼런스에 참여하는 것이 체력적으로 조금은 힘들었지만, 10개가 넘는 발표 세션을 자유롭게 들으며 영감을 얻고 부스 활동을 통해 다양한 사람들을 만나는 것도 재미있었다.
인턴십 동안 모르는 것을 적극적으로 질문했던 것 같다. 그 덕분에 이슈를 빠르게 해결할 수 있었다고 생각한다. 질문을 많이할 수 있었던 이유는 수평적인 래블업의 문화가 있었기 때문이라고 생각한다. 그리고 질문에 친절히 답변해주시는 분들이 많아서 활발하게 질문을 할 수 있었다. 이 자리를 빌어 도움을 주신 구성원분들에게 감사를 표하고 싶다.
내가 원했던 비동기 프로그래밍 경험을 포함해 GitHub 협업 방식, 영어 세미나 발표, 컨퍼런스 참가 등 다양한 것을 경험할 수 있었다. 이를 통해 개발자로서 큰 성장을 한 것 같다. 성장에 목마른 사람들에게 래블업 인턴십을 추천한다.