
발대식 후기를 쓴 지 한 달이 조금 넘었다. 그때는 "혼자서는 벅찰 것 같다"는 생각과 "좋은 리뷰를 받아 Organization Member가 되는 것"이라는 목표만 있었는데, 지금은 실제로 이슈를 등록하고 PR을 올리고 리뷰를 주고받으며 한 달을 보냈다. Challenges 기간 중반을 지나며 지금까지 한 내용을 정리하려고 한다.

나는 OpenStack & Kubernetes 운영 문서화 및 국제화 팀 소속으로, 크게 세 갈래로 기여를 이어왔다.
infra-cloud-kr/openstack-kubernetes — 팀에서 직접 만들어가는 OpenStack-Helm 운영 문서kubernetes/website — 쿠버네티스 공식 문서 한글화k8s-kr/kubelingoassist — 한글화 작업을 돕는 VS Code 확장 프로그램여기에 더해 OpenDev 코드리뷰 워크플로우도 실습 진행했다.

처음 팀 파트를 나눌 때 네트워크 쪽에 인원이 몰렸다. 나도 처음엔 Gateway API 파트로 시작했는데, GitHub 이슈 현황을 전수 조사해보니 이미 여러 명이 관련 주제를 선점한 상태였다. 그래서 아직 아무도 손대지 않은 Octavia 로드밸런싱(networking/load-balancing.rst)으로 파트를 바꿔 이슈(#24)를 새로 등록했다.
이후 이미 병합되거나 열려있는 다른 분들의 PR(#36, #38)을 읽으며 이 프로젝트에서 통용되는 문서 스타일(list-table로 리소스 정리, code-block으로 아키텍처 다이어그램 그리기)을 파악했고, 그 스타일을 따라 로드밸런서·리스너·풀·멤버·헬스 모니터 개념과 amphora/OVN 드라이버 비교를 작성해 PR #40을 올렸다.
내가 문서로 정리한 게 바로 이 그림 속 구조다 — 로드밸런서 요청이 들어오면 amphora(실제 트래픽을 처리하는 VM 또는 컨테이너)가 뜨고, 컨트롤러가 이걸 관리하는 흐름을 이해하고 나니 글을 쓰기가 훨씬 수월해졌다. PR을 올리기 전 sphinx-build -W(경고 0건)와 doc8 린트(에러 0건)를 직접 돌려보고 확인한 것도 이번에 새로 익힌 습관이다.
kubernetes/website에 PR을 올리기 전에, 쿠버네티스 조직에 처음 PR을 올려본 곳은 kubernetes-sigs/contributor-playground였다(MERGED). CLA 서명이 제대로 되는지, Prow 봇이 어떻게 반응하는지 연습하는 온보딩용 저장소인데, 여기서 리뷰어가 GitHub의 "Approve" 버튼이 아니라 /lgtm, /approve 같은 "텍스트 커맨드"로 리뷰 상태를 바꿀 수도 있구나.. 많은 프로젝트에서 사용하지만 사용해보지 못했던 부분이라 신기했던거 같다.

kubernetes/website에서는 kubeadm 고가용성 토폴로지 가이드의 오래된 번역을 최신화하는 PR(#56648)을 올렸다. 리뷰를 받기 전엔 "자연스러운 한국어면 된다"고 생각했는데, 리뷰어분께 받은 피드백 7건을 하나씩 내 원문과 비교해보니 내가 놓친 게 눈에 보였다.
| 내가 쓴 문장 | 리뷰 후 |
|---|---|
| "지역 etcd 멤버" | "로컬 etcd 멤버" |
| (원문 일부 생략) "비슷한 방식이 지역의 X와 Y에도" | "같은 방식이 로컬 X와 Y 인스턴스에도" |
| "커플링에 실패할 위험" | "결합이 실패할 위험" |
local을 무조건 '지역'으로 직역하면 오히려 원문 의미가 흐려질 수 있다는 것, 매끄럽게 읽히려고 슬쩍 생략한 단어가 사실은 한글화팀이 지키려는 "원문 구조 보존" 원칙을 깨는 일이라는 걸 이때 처음 체감했다. 리뷰가 끝난 뒤엔 "커밋을 하나로 스쿼시해달라"는 요청도 받았는데, 리뷰 중엔 커밋을 계속 쌓다가 승인 직전에만 정리한다는 팀 관례도 이렇게 실제로 겪으며 배운거같다.
반대로 내가 간단하게 리뷰어가 되어본 경험도 있었다. 다른 분의 번역 PR(#56678)을 원문과 문단 단위로 대조하다가, 문서 상단의 translator 링크에 있는 GitHub 계정명 오타(hongp vs hong-p)를 발견했다. 번역 자체는 정확했지만, 링크가 실제 번역자를 가리키는지까지 확인하지 않았다면 놓쳤을 문제였다. 리뷰를 받는 입장과 직접 리뷰하는 입장을 모두 경험하면서, 좋은 번역은 ‘자연스럽게 읽히는 번역’에서 끝나는 것이 아니라 원문의 의미와 구조, 문서의 세부 요소까지 보존하는 번역이라는 걸 알게 됐다.

kubelingoassist에 기여하면서는 조금 다른 종류의 배움이 있었다. 번역 문서에서 자주 흔들리는 표기(예: 프록시/프락시)를 실시간으로 잡아주는 기능을 직접 설계·구현했는데, 처음엔 실제 문서 541개를 스캔해서 더 많이 쓰인 표현을 그냥 추천하려고 했다.
그런데 "가비지 컬렉션"이 corpus에서 더 많이 쓰인다고 보고 이걸 추천하려던 순간, 공식 용어집을 확인해보니 정답은 "가비지 수집"이었다. 컬렉션+콜렉션을 다 합쳐도 수집의 사용 빈도에 한참 못 미쳤다. 데이터(빈도)만 보고 판단하면 완전히 틀릴 수 있다는 걸, 내가 만들던 도구에서 직접 겪으며 배웠다. 이 경험 덕분에 "공식 용어집이 있으면 그걸 최우선으로, 없을 때만 데이터를 참고한다"는 설계 원칙을 세울 수 있었고, 이 기능을 VS Code Extension Host 환경에서 70개 이상의 테스트로 검증한 뒤 이슈(#30)와 PR(#31)을 올렸다.

우리 팀이 최종적으로 바라보는 목표는 openstack-helm처럼 실제 OpenStack 프로젝트에 기여하는 것인데, 이 프로젝트들은 GitHub가 아니라 OpenDev라는, OpenInfra Foundation이 직접 운영하는 별도의 코드 호스팅·리뷰 인프라 위에서 돌아간다. 그래서 본격적으로 문서 작업을 하기 전에, OpenDev가 제공하는 연습용 저장소인 opendev/sandbox에서 이 낯선 워크플로부터 먼저 익혀보기로 했다.
계정 하나로 시작하는 GitHub와 달리, OpenDev는 Ubuntu One 계정(login.ubuntu.com)으로 로그인한다 — 이 계정은 Gerrit뿐 아니라 Launchpad(버그 트래커), 번역 플랫폼, 심지어 OpenInfra 재단 행사 투표까지 재단 전체 활동에 두루 쓰이는 단일 계정이었다. 이후 SSH key를 새로 만들어 ~/.ssh/config에 review.opendev.org 호스트를 등록하고 Gerrit에 공개키를 올렸고, git-review라는 전용 CLI 도구를 설치한 뒤 git review -s를 실행하면 gerrit이라는 리모트가 자동으로 생성된다. 커밋 메시지에도 규칙이 있었다 — 요약은 50자, 본문은 72자를 넘기지 않는 관례, 그리고 DCO(Developer Certificate of Origin, "내가 이 코드를 직접 썼고 라이선스에 동의한다"는 서명)를 뜻하는 Signed-off-by 태그를 반드시 붙여야 한다는 정보를 얻었다.
이렇게 세팅을 마치고 git-review로 패치를 올리니 터미널에 이런 로그가 찍혔다.

가장 헷갈렸던 건 "커밋을 새로 쌓는 방식이 아니라는 것"이었다. GitHub PR은 커밋을 계속 추가해서 리뷰 이력을 쌓아가지만, Gerrit은 git commit --amend로 같은 Change-Id를 가진 패치셋을 계속 덮어써서 갱신한다. 커밋 메시지 안에 있는 Related-Bug(연결된 버그 번호), Change-Id(이 리뷰를 식별하는 고유 값, 리비전이 바뀌어도 유지됨), Signed-off-by(DCO 서명) 세 태그를 이해하자

리뷰 방식도 완전히 달랐다. -1/0/+1은 누구나 줄 수 있는 리뷰 점수이고, +2는 승인 권한이 있는 리뷰어만 줄 수 있다는 점수제다. 게다가 병합되려면 세 종류의 라벨이 전부 채워져야 한다 — 사람이 코드를 검토하는 Code-Review, Zuul이라는 CI가 빌드·테스트 결과를 보고 자동으로 매기는 Verified, 그리고 병합 준비가 됐는지를 나타내는 Workflow. 이 셋 중 하나라도 비어 있으면 자동 병합(gate) 대상에서 제외된다는 걸 실습을 통해서 배울 수 있었다.
같은 실습 세션에서 팀원한분이 올린 연습 패치를 내가 리뷰해줄 기회도 있었다. Please capitalize the first letter.라는 코멘트를 남기고 Code-Review +2, Workflow +1을 직접 눌러 승인까지 해봤는데, GitHub에서는 "Approve" 버튼 한 번이면 끝날 일이 Gerrit에서는 점수 하나하나를 채워나가는 과정이 재밌었다. 한국어 번역에 많이 기여하고 더 나아가 영어번역에도 기여 할 수 있을 수 있게 많이 배우고 opendev사이트를 자주 방문해야겠다.

같은 "코드 리뷰"라도 프로젝트마다 문화와 도구가 이렇게 다를 수 있고, 우리 팀이 목표로 하는 openstack-helm 기여도 결국 이 Gerrit 문법(Change-Id, 패치셋, 점수제 승인, Zuul 게이트)을 몸에 익힌 다음에야 제대로 시작할 수 있겠다는 걸 이번 sandbox 연습을 하며 실습 환경을 익힌거같다.

정규 미팅이 끝난 뒤에도 디스코드에서 당일 밋업에서 다룬 내용 중 이해가 잘 되지 않았거나 궁금했던 부분을 자유롭게 질문할 수 있었다. 멘토님들께서 질문에 바로 답변해주셔서, 세션 내용을 다시 짚어보고 궁금했던 부분을 바로 해소할 수 있었던거 같다. (멘토님들 항상 감사드립니다..)
한 달 전만 해도 “번역은 자연스럽게만 하면 된다”고 생각했다면, 지금은 원문을 최대한 지키는 것과 자연스럽게 표현하는 것 사이에서 근거를 가지고 판단하는 법을 조금씩 배우고 있다. 리뷰를 받으면서, 반대로 다른 사람의 리뷰를 해보면서, 그리고 내가 만든 도구가 스스로 틀린 답을 낼 뻔한 순간을 겪으면서 결국 같은 교훈을 여러 방향에서 확인한 것 같다. 근거 없이 그럴듯해 보이는 것을 그냥 믿지 말 것. KubeCon Japan 이야기를 들으며 느낀 것도 비슷했다. 인프라도 문서도 결국 지금 맞다고 믿는 것을 계속 의심하고 검증하면서 조금씩 더 나은 방향으로 갱신해가는 일이라는 생각이 들었다.
앞으로 load-balancing.rst(PR #40)와 kubelingoassist(PR #31)가 실제 리뷰를 받게 된다면 이번에 배운 내용을 바탕으로 꼼꼼하게 반영해서 최종적으로 병합까지 이어갈 수 있는 PR을 만들고 싶다. 지금까지 OpenDev에서는 Sandbox를 통해 연습하는 데 그쳤다면, 이제는 실제 OpenStack 프로젝트, 특히 openstack-helm에 Gerrit으로 직접 패치를 올려보려고 한다. 다른 분들의 PR도 더 적극적으로 리뷰하면서 문서의 정확성을 검증하는 눈을 계속 키워가고 싶고, KubeCon Japan에 후기를 들으며 언뜻 접했던 AI 인프라의 흐름도 조금씩 따라가며 부족한 부분을 학습 해보려고 한다. 지금 당장 내가 직접 다뤄야 할 영역은 아니더라도, 내가 다듬고 작성하는 문서가 어떤 기술적 흐름 위에 놓여 있는지는 알고 써야 한다고 생각하기 때문이다.
처음에는 막막하게 시작했지만 한 달 사이에 GitHub와 Gerrit을 오가며 이슈를 만들고, PR을 올리고, 리뷰를 주고받는 과정이 어느새 제법 익숙해졌다. 아직 배워야 할 것도 많고 부족한 부분도 많지만, 적어도 한 달 전의 나와 비교하면 조금은 달라진 것 같다. Challenges 기간에서 많이 배웠고, 이어질 Masters 기간에서도 지금처럼 하나씩 부딪히고 확인해가면서 꾸준히 나아가보려고 한다.