feconf25에 방문해서 세션을 들은 후 남기는 후기 글입니다
이 강연 진심 개웃깁니다
진짜
얼마나 웃기냐면... 본문에서 보시죠
레츠고
2025.08.23. (토) FECONF 25
세션7(17:10 ~ 17:40): 모노레포 절망편, 14개 레포로 부활하기까지 걸린 1년
연사자: 플렉스 - Web Client Platform Team - Product Engineer(FE) - 김종혁 개발자
연사자 블로그: maxkim-j.github.io
연사자 세션 후기(발표자료 링크 포함): 링크드인 포스트
Flex 간단 소개
Flex라는 서비스는 구성원들의 계약, 휴가/근무, 급여/연말정산 등의 관리를 돕는 HR 시스템이다.
우리 회사(레브잇)도 쓰고 있다.
난 사실 휴가 신청할 때만 쓰긴 함..ㅋㅋ
휴가를 신청할 수 있게 해주는 고마운 툴...
그래서 Flex 모노레포에 무슨 일이 있었나요?
yarn을 사용해 workspaces:*로 모노레포 내 패키지들을 연결하고
turborepo로 패키지 단위의 테스크 실행 및 의존성 추적을 실행하고 있었다고 한다
그런데 그 복잡성과 의존성이 점점 늘어나 위 사진처럼 되었다고...
이 의존성을 그래프화 했을 때는 아래처럼 끔찍한 그래프가 나왔다고 한다
난 이 흑흑 무서웡 짤을 보는 순간 느꼈다... 이 발표자 개그 감각이 보통이 아니라고...
연사자는 이 심연의 우주를 보고 공포를 느꼈다고 한다 (그럴만두🥟)
걷잡을 수 없이 불어난 의존성 때문에 정기배포 요일을 정하고 아래와 같은 루틴을 지켰다고 한다
진심 저 빽빽한 체크리스트를 보고 공포를 느낌
'최선을 다해 지켜본다' 이것도 개웃김 ㅠㅠ (아니 사실 안웃김 내 이야기 같기도)
그리고 전설의 짤이 등장한다
진심 남일같지가 않음ㅋㅋㅋㅋㅋㅋㅌㅠ
다음주 정기배포 당번(하기 싫음) <- 무슨 초등학교 주번도 아니고 배포 당번 있는 것부터 슬픔ㅠㅠㅠ
그래서 결국 이 정기배포를 그만둘 결심을 했다고 한다
폴리레포로 만들어서 각 레포 관리주체가 배포 시기를 각각 관리하도록...
정기배포 그만두기 프로젝트
24년 2월에 시작된 그들의 여정...!
모노레포를 해체하고, 패키지와 어플리케이션을 개별 레포지토리로 분리한다
연사자가 여러 번 강조했던 점
이 거대한 프로젝트의 타임라인을 꼼꼼하게 세우고, 그걸 수행했다는 점이다
한눈에 진척도를 가시화할 수 있고, 팀원들도 포기하지 않고 계속해나갈 수 있었다고 한다
2022년 6월 14일에 처음으로 정기 배포를 이 연사자가 시작, 3년간 162번의 정기배포가 있었다고 한다
그리고 1년 5개월간 9개의 마일스톤을 바탕으로 폴리레포로 분리했고,
마침내 2025년 7월 9일에 정기배포 그만두기를 성공하게 된다
(이부분 들으면서 괜히 내가 벅차오름)
이때 슬랙에 올린 메시지를 보여주시면서 "네, 평새 받을 따봉(이모지) 다 받았고..."<-이것도 너무 짠하고 웃기고...그랬음
이 프로젝트를 통해 연사자가 깨달은 점 3가지도 함께 공유 받았다
팀과 제품에 맞는 적정 코드베이스를 만들기 위해 꼭 알아야 하는 3가지
1. 경계 없이 코드를 공유하지 말 것
- 사실 모노레포냐 폴리레포냐의 문제가 아니다
예시 상황
1) 공용 패키지를 A 개발자가 만들었다.
예) 재고 목록을 보여주는 컴포넌트
2) B 개발자가 공용 패키지를 사용하려고 한다.
- 그런데 원하는 기능과 정확히 Fit하지 않았다.
- props를 하나 더 파서 원하는 기능처럼 동작하게 만들었다. (문제의 시작)
예) 조회 버튼을 누르면 원하는 재고 목록이 뜨도록 만듦
- 이게 왜 문제인가요?
- 원본 모듈의 취지가 모호해졌다.
- 최초에 A개발자가 모듈을 사용했던 코드들은 이 수정사항에 어떤 영향을 받을지 모른다.
(보통 공용 모듈에 props 하나 추가해서 쓸 때, 기존 코드들까지 돌아보진 않는다.)
3) C개발자가 공용 패키지를 사용하려고 한다.
- A개발자가 만든 공용 패키지에서 함수만 딱 빼와서 원하는 모양으로 고쳤다.
예) 재고 목록을 가져오는 함수
4) 그러던 와중에 A개발자가 퇴사했다.
- 이제 이 패키지는 건들면 터지는 패키지 취급을 받는다.
5) 용감한 D개발자가 입사해서 이 공용 패키지를 뜯어 고치려고 한다.
- 이 공용 패키지와 모든 앱들이 터지기 시작한다. (이미 서로의 의존성이 너무 꼬여서 뭘 고치면 뭐가 터질지 모름)
이런 상황이 발생했다고, 각 개발자들을 탓해서는 안된다
어린 아이에게 빵을 먹지 말라고 해도, 빵을 꺼낼 수 있는 막대가 있다면 먹을 것이다.
이제 이런식으로 쓰지 마세요~ 라고 해도 원칙이 구두로만 존재하고, 실제로는 손을 댈 수 있다면?
누구라도 급하면 그렇게 쓸 것이다. (이번만 예외로 치지 뭐)
모노레포의 정의
여러 프로젝트가 포함된 레포지토리에서는 코드가 "같은 곳에 위치(code colocation)"하지만, 이들 사이에 명확하게 정의된 관계(well defined relationship)가 없다면 우리는 그것을 모노레포라고 부르지 않을 것입니다.
- Nx Team(momorepo.tools)
결국 중요한 건 "명확하게 정의된 관계"(경계)이다.
어디까지 공유하고, 어디부터는 분리할 것인가?
Flex팀이 모노레포를 버린 이유
폴리레포로 가게 된다면
- 업무 공유가 힘들어질 것이고(pr이 각 레포에 나뉘어 올라옴)
- 코드가 파편화될 것이며(당연함 각 레포에서 작업이 나눠지기 때문)
- 원자적 커밋이 불가능하다(한 커밋으로 전사에 영향을 줄 수 없다)
하지만 Flex팀은 이를 감당할 수 있다고 생각했다.
또, 이를 보완했을 때 얻을 수 있는 폴리레포의 장점이 더 크다고 판단했다.
모노레포는 툴링으로 한 레포 안에서 경계를 만들어야 한다.
Why Google Stores Billions of Lines of Code in a Single Repository(2016)에 따르면,
구글은 모노레포를 유지하기 위해 Piper(사내 버전관리 시스템), CitC(클라우드 기반 워크스페이스), CodeSearch(대규모 코드 검색 도구), Roise(대규모 코드 변경 자동화 도구), Refaster(패턴 기반 리팩토링 도구), ClangMR(코드 자동 변환 도구) 등...을 쓴다고 한다.
폴리레포는 물리적으로 레포가 분리되어있기 때문에 자연스럽게 경계를 만들 수 있다
이를 통해 레포지토리 경계 안정성을 얻을 수 있고, 정기배포의 고통에서 벗어날 수 있다.
2. 코드베이스를 복잡한 상태로 방치하지 말 것
- 사람이 인지할 수 있는 의존성/버전 개수는 한계가 존재한다.
방치된 코드베이스가 복잡한 경우, 코드 변경이 두려워진다
- 패키지 개수가 너무 많다
- 의존성이 인지 범위를 넘어간다
- 변경 추적이 불가능하다
- 알아야 하는 코드가 많다
이 사진이 진심 적절하다고 생각함ㅋㅋㅋㅋ
사실 코드 베이스가 복잡해서 '건드리면 터져서 건들기 싫어잉ㅠ'이라는 기조가 형성되는 순간,
모두가 그 코드에 '웬만하면 들어가고 싶지 않고' '기여하기도 싫다'는 생각을 한다
그래서 코드 베이스를 잘 다져놔야 누구나 쉽게 기여하는 분위기를 만들 수 있다
하... 나도 해야하는데
이 복잡한 패키지들이 정말 다 필요했을까?
아니요..
- 어디에 어떤 모듈이 있는지 모른다
- 공유하려고 만들었는데 공유가 안된다
- 모듈 1~2개를 공유하기 위해 패키지를 자꾸 새로 만든다
복잡한 패키지를 정리하자
- 플렉스의 공통 패키지 정리 레포지토리: 고구마...
- 고구마인 이유: 모노레포 의존성이 고구마 줄기처럼 줄줄이 나옴
고구마 패키지를 분석했을 때 뭐가 엄청 많이 나왔다 역시 고구마닉값)
그리고, 매일 아침 고구마에서 기존 공용 패키지를 정리한 결과를 슬랙봇으로 알려줬다
패키지 개수만 줄여도 전체 패키지 빌드 성능이 38% 개선되었다
그래도! 여전히 의존성은 많이 엮여있다.
연사자는 퇴사할 때까지 의존성만 뜯어도 완전한 의존성 분리는 어려울 것 같다고 생각했다.
그래서 이 모든 의존성을 다 세세히 뜯는 방법 대신 '통버저닝'을 고안했다.
통버저닝
패키지 여러 개를 하나로 합쳐서 하나로 버저닝한다.
그럼 몇 개의 패키지와 몇 개의 버전만 알면 된다.
(사람이 인지할 수 있는 variation 범위 안에 들어오면 판단하고 관리할 수 있다)
의존성 설치, ci 과정에서
각 패키지의 버전 정합성이 맞지 않으면 에러를 발생시킨다
패키지 사이 의존 관계를 정의했다
최대한 단방향을 지향해서 서로 의존성 루프가 생기는 걸 막았다
결과적으로 코드베이스 전체에 단순함을 가져왔다
그 결과, 6개 패키지를 3개의 통버저닝 패키지로 묶어서 정리했다고 한다
결과
원래 알아야했던 것
- 모노레포의 복잡한 패키지 의존 관계
이제 알아야 하는 것
- 패키지의 단일버전
- 내 앱이 사용하는 패키지들
인지 부하를 줄여서 관리용이성을 높였다!
그리고, 패키지는 시간에 따라 또 늘어날 것이기에 계속 관리해야 하고, '몰아서 한다'는 생각을 버려야 한다
3. 공유 모듈을 정의하고 알맞게 다룰 것
공유 모듈에 퀼트 조각마냥 누덕누덕... 필요할 때마다 기능을 붙여서 커진 경우
= "뭔지 모를 것이 됨"
너무 여기저기 불필요하게 의존성이 생기니까 코드 관리 취약성이 증가함
(그래서 이게 어디까지 영향이 미치는데요?? << 모름 너무 많음)
공유 모듈이 될 수 있는 것은?
- 제품 전체에서 하나여야만 하는 코드
- 공용화가 안되면 개발 생산성이 급격히 떨어지는 코드
-> 이 외 코드는 과감하게 중복, 각 사용처로 내재화
(요즘 이거 보고 반성해서 코드 좀 다르게 짜고 있음)
각 공용 레이어 패키지 의미를 정의하고, 이에 맞게 관리한다
(이러면 한 공용 모듈에 여러 성격의 기능이 섞이는 것을 막을 수 있을 듯?)
공유 모듈 처리 의사결정 트리
이 의사결정 트리를 바탕으로 공유 모듈로 넣을지 말지 여부를 결정했다고 한다.
사실 코드 중복이 무조건 죄악이라고 생각했는데,
어거지로 공유 모듈로 빼는 것보다 차라리 코드 중복시켜서 의존성 끊는게 낫다고 생각하는 요즘이다...
(모달 헤더 컴포넌트 만들면서 느낌)
애플리케이션 코드 고립
만약 어떤 패키지가 두 레포 사이에 낑기게 된다면,
어떻게든 의존성을 끊어내거나(코드를 중복시켜서라도?)
공유 레이어로 뺐다고 한다
그래서 어떻게 공유 모듈 경계를 분리했나요?
아까 모노레포 절망편 짤 이후 두 번째로 인상깊은 짤
+145,733 커밋 << 진심 모든 의미가 압축되어 있음
좀 지친 면도 있는데 <<ㅠㅠ 공감되고 슬픔
기존 PR들을 다 뿌러트렸습니다 죄송합니다<<동료 개발자들에게 무슨 평을 받았을지 두려움
이제 사이버육체노동에 종말을 고할 수 있습니다<< 뭔가 이뤄낸 것 같음 멋있음
작업계획서 작성
정기배포 그만두기 작업계획서에 코드 고립 작업 대상을 포함시키고
위와 같이 관리했다고 한다
그리고 이 역시 의사 결정 트리로 판단했다고 한다
원자적 관리가 필요한 경우, 공유 모듈 레포로 일부 이관 시키거나 전체 이관을 시켰고
그렇지 않은 경우라면 차라리 코드를 중복시키는 판단을 했다고 함
위 코드 고립 작업 대상 구현체 데이터베이스에서 각 구현체를 클릭하면
이와 같은 내용으로 작성했다고 한다
꼼꼼히 태깅하고 우선순위, 완료여부 표시한게 작업 관리에 용이했을 듯 하다
결론
팀과 제품에 맞는 적정 코드 베이스를 만들기 위해 알아야 하는 3가지
1. 경계없이 코드를 공유하지 말 것
- 모노레포든 폴리레포든 코드 사이에 적절한 경계가 필요하다
2. 코드베이스를 복잡한 상태로 방치하지 말 것
- 코드베이스를 단순하게 유지하고 인지 부하를 관리해야 한다
3. 공유 모듈을 정의하고 알맞게 다룰 것
- 공유할 가치가 없는 모듈들이 코드베이스를 취약하게 만든다
앞으로의 계획
- 규제 완화 및 스쿼드가 더욱 자유롭게 개발할 수 있도록 지원
- 공용 모듈에 대한 명세와 문서 만들어 AI 개발 도구 지원
이 프로젝트를 통해 Flex의 Web Client Platform Team의 정체성도 정의했다고 한다
그래서 관심있으면 지원하라는 전형적인 flow로 마무리 됨ㅋㅋㅋ
FE 팀에는 '저희가 궂은 일 다 할테니 오셔서 꿀잼 개발만 하셔요!'라는 문구로 지원을 유도하고
FE Platform 팀에는 '이게???재밌어 보인다고요? 당신을 애타게 찾았습니다'라고 함ㅋㅋㅋㅋㅋㅋㅋㅋ
진심 마지막까지 개웃겼슨...
웃겨서 사진 찍었는데, 뒷자리에서 같은 회사 동료끼리 온 건지
"ㅇㅇ님... QR 찍지 마세요..."라고 소소하게 동료 유출을 방지하는 훈훈한 대화도 들었다
무튼 짱재밌는 강연이었다
마지막으로 연사자분이 직접 공유하신 세션 후기 링크드인 포스트를 끝으로 글을 마무리하겠다!
Flex 팀 - 김종혁 개발자: 모노레포 절먕편, 14개 레포로 부활하기까지 걸린 1년
FEConf 2025에서 제가 발표했었던 "모노레포 절망편, 14개의 레포로 부활하기까지 걸린 1년" 세션의
FEConf 2025에서 제가 발표했었던 "모노레포 절망편, 14개의 레포로 부활하기까지 걸린 1년" 세션의 발표 자료 공유드립니다! https://lnkd.in/g4zbim4v 팀과 제품의 규모에 맞는 코드베이스 전략에 대해 좋
kr.linkedin.com
이 세션 후기 글을 재밌게 읽으셨다면 레브잇 FE 개발자 심수연에게도 많은 관심을 부탁드립니다~^^
그럼 이만
2025/08/30
'개발 관련 컨퍼런스 참여' 카테고리의 다른 글
[FECONF25] 개발자를 위한 모션 그래픽 솔루션: Lottie의 기술 진화와 활용전략 (1) | 2025.08.31 |
---|---|
토스 개발자 컨퍼런스 SLASH24 (7) | 2024.09.02 |