GitHub 개인 계정과 조직: 어떤 리포를 조직으로 옮길까?
기능 모듈을 패키지로 내려다가 리포 하나를 개인 계정에서 조직으로 옮겼습니다. 옮기기 직전까지 저는 이 일이 귀찮을 거라고 생각했습니다. 러너를 다시 붙이고, 시크릿을 다시 넣고, 문서마다 주소를 고쳐야 할 것 같았습니다. 실제로는 API 호출 한 번과 원격 주소 한 줄로 끝났습니다. 그 과정에서 어떤 리포를 조직에 두고 어떤 리포를 개인 계정에 둘지 기준이 하나 생겨서 정리해 둡니다.
스코프가 곧 소유자라는 GitHub Packages의 규칙
듀오랩스에는 디자인 시스템 DEUX가 있고, 이미 duolabs-deux라는 조직에서 @duolabs-deux/ui 같은 이름으로 npm 패키지를 내고 있습니다. 이번에 만드는 UNIT은 사업자등록 확인 같은 기능을 모듈로 묶어 다른 프로젝트에서 npm install 한 줄로 쓰게 하려는 프로젝트입니다. DEUX를 쓰는 프로젝트는 이미 .npmrc에 @duolabs-deux 레지스트리와 읽기 토큰이 잡혀 있으니, UNIT도 같은 스코프로 나가면 소비하는 쪽에서 설정할 것이 없습니다.
문제는 GitHub Packages의 npm 레지스트리가 스코프를 소유자 이름으로 쓴다는 점입니다. @duolabs-deux/…로 내려면 패키지 주인이 duolabs-deux 조직이어야 합니다. 그런데 UNIT 리포는 개인 계정에 있었습니다.
옮기지 않는 방법 두 가지와 그 비용
리포를 옮기지 않고도 방법은 있었습니다. 셋을 놓고 비교했습니다.
| 리포 위치 | 패키지 이름 | 대가 | |
|---|---|---|---|
| 조직으로 옮김 | 조직 | @duolabs-deux/unit-* |
한 번 옮기는 수고 |
| 그대로 두고 토큰 추가 | 개인 계정 | @duolabs-deux/unit-* |
조직 쓰기 권한 토큰을 시크릿으로 넣고, 만료될 때마다 갱신 |
| 그대로 두고 개인 스코프 | 개인 계정 | @<개인계정>/unit-* |
소비 프로젝트마다 .npmrc에 레지스트리 한 줄 추가 |
두 번째는 지금 당장은 가장 편해 보였습니다. 그런데 만료되는 토큰은 잊고 있다가 배포가 멈춘 날에야 생각납니다. 세 번째는 비용이 소비하는 쪽으로 넘어갑니다. 프로젝트가 늘수록 설정 줄도 같이 늘어납니다. 한 번 수고하고 끝나는 첫 번째가 길게 보면 가장 덜 귀찮다고 판단했습니다.
이름표를 같이 쓰면 생기는 충돌, contracts
같은 스코프를 쓰기로 하자 바로 걸리는 것이 있었습니다. DEUX에 이미 @duolabs-deux/contracts가 있습니다. 디자인 시스템의 매니페스트 타입을 담은 패키지입니다. UNIT에도 공통 타입 패키지가 필요한데 같은 이름으로는 낼 수 없습니다.
그래서 UNIT 패키지에는 전부 unit- 접두를 붙이기로 했습니다. unit-contracts, unit-runtime, unit-biz-registry처럼요. 충돌하는 것은 contracts 하나였지만 전부 붙인 데는 이유가 있습니다. 조직의 패키지 목록은 이름순으로 섞여 나오는데, biz-registry만 보고는 그게 화면 패키지인지 기능 패키지인지 알 수 없습니다. DEUX도 테마 패키지에 -ui 접미를 붙여(vega-ui, lyra-ui) 종류를 이름으로 드러내고 있어서 같은 관례를 따른 셈입니다.
API 호출 한 번으로 끝난 이전
옮기는 것 자체는 이렇게 끝났습니다.
gh api -X POST repos/<개인계정>/<리포>/transfer -f new_owner=<조직> -f new_name=<새 이름>
git remote set-url origin https://github.com/<조직>/<새 이름>.git제가 가장 걱정한 것은 셀프호스티드 러너였습니다. 이 리포는 배포를 오리진 서버의 러너가 맡고 있고, 러너는 리포 단위로 등록되어 있었습니다. 옮기면 떨어질 거라고 보고 다시 등록할 준비를 해 두었습니다.
확인해 보니 러너는 online인 채로 새 리포에 붙어 있었습니다. 러너 폴더의 설정 파일에는 여전히 옛 주소가 적혀 있는데도 그랬습니다. 배포 워크플로를 한 번 돌려 봤고 1분 46초 만에 성공했습니다. 시크릿 세 개도 그대로 따라왔습니다. 문서에 박혀 있던 옛 주소는 한 곳뿐이었습니다.
하나 확인하지 못한 것이 있습니다. 조직의 Actions 정책은 제 토큰에 admin:org 권한이 없어서 API로 읽지 못했습니다. 실제 배포가 돌았으니 셀프호스티드 러너가 허용되어 있는 것은 맞지만, 정책을 눈으로 확인한 것은 아닙니다.
조직에 둘 것과 개인 계정에 둘 것
이번 일로 기준을 하나 정했습니다. 다른 프로젝트가 가져다 쓰는 것은 조직에 두고, 제가 운영하는 서비스 앱은 개인 계정에 그대로 둡니다.
가져다 쓰는 것을 조직에 두면 얻는 것이 분명합니다. 패키지 스코프를 함께 쓰고, 권한을 조직 단위로 줄 수 있습니다. 나중에 외부 인력에게 디자인 시스템과 기능 모듈만 보여 줘야 할 때, 개인 계정에 섞여 있으면 리포마다 권한을 따로 줘야 합니다. 제품군을 통째로 넘길 일이 생겨도 조직 소유자만 바꾸면 됩니다.
반대로 랜딩 사이트나 고객 데모 같은 운영 앱은 옮겨도 얻는 것이 없습니다. 아무도 그 리포를 패키지로 받지 않고, 주소만 바뀝니다. 그래서 이번에는 UNIT 하나만 옮겼고 나머지 서비스 리포는 그대로 두었습니다.
남겨 둔 숙제, 조직 러너
조직으로 모으면 생기는 이점 중 아직 쓰지 않은 것이 있습니다. 지금 오리진 서버에는 리포마다 러너가 하나씩 떠 있습니다. 조직 러너를 하나 두면 조직 안의 리포가 그 러너를 같이 씁니다. DEUX 쪽 배포는 GitHub가 제공하는 러너에서 돌고 있어서 지금은 합칠 대상이 UNIT 하나뿐이고, 그래서 미뤄 두었습니다. 조직에 리포가 더 늘면 그때 옮길 생각입니다.
함께 읽기
- Sentry 란 무엇인가: 에러 수집 도구가 하는 일과 대안 비교헬스체크는 200 을 돌려주는데 화면은 500 입니다. 컨테이너는 떠 있고, 워치독은 조용하고, 서버 로그에는 같은 스택 트레이스가 수백 줄 흩어져 있습니다. 어느 배포부터 시작됐는지, 몇 명이 겪었는지, 지금도 나고 있는지는 로그를 아무리 봐도 안 나옵니다.
- cmux와 Orca 비교: 터미널을 늘릴 것인가, 시도를 늘릴 것인가두 앱의 소개 문구는 거의 같습니다. 코딩 에이전트를 여러 개 동시에 돌린다는 것입니다. 그런데 cmux는 Swift와 AppKit으로 짠 macOS 전용 앱이고, Orca는 Electron으로 짜서 Windows와 Linux, 심지어 휴대폰까지 갑니다. 라이선스도 GPL-3.0과 MIT로 갈립니다.
- colima 자동 기동: brew services가 10초마다 재실행되는 이유개발기에 도커를 새로 깔 일이 생겼습니다. 컨테이너 하나만 돌리면 되는 일이라 가볍게 끝날 줄 알았는데, 설치 자체는 5분이었고 그 뒤에 두 가지를 더 고쳐야 했습니다. 하나는 깃 저장소가 더러워진 것이고, 하나는 코어 하나의 2.8%가 계속 타고 있던 것입니다.
- 드라이런과 멱등성: 사고를 막는 시점의 차이배포 스크립트에 안전장치를 넣는다고 할 때 두 가지가 자주 같이 나옵니다.
- 새 맥북 개발 환경 세팅: git clone이 가져오지 않는 것들맥북을 새로 받고 하던 프로젝트를 이어서 하려 했습니다. 리포를 클론하고 npm install 을 돌린 다음 개발 서버를 띄웠는데, 브라우저에 이게 떴습니다.