- Chris Krycho는 LinkedIn에서 약 5년간 데스크톱 웹 앱의 프런트엔드 인프라와 개발자 경험을 맡으며, 대규모 코드베이스를 안전하게 바꾸는 일과 빠른 제품 실행 요구 사이의 충돌을 겪음
- 입사 당시 약 200만 줄 JavaScript였던 LinkedIn 데스크톱 앱은 이후 약 320만 줄 모노레포로 커졌고, 마이그레이션은 자동화와 제품팀 부담 최소화 없이는 현실적으로 어려웠음
- Ember 현대화와 TypeScript 도입은 오류 감소와 개발 품질 개선을 겨냥했으며, TypeScript 전환으로 애플리케이션 로그 오류량을 최소 25% 줄일 수 있다는 분석이 내부 설득에 쓰임
- Ember에서 React로 옮기는 계획은 Chris 팀의 3~5년 점진적 자동화 전략과, 더 빠른 제품 실험을 위해 기존 방식을 크게 다시 설계하려는 접근이 맞부딪힘
- 대규모 장애 대응 과정에서 알림, 관측성, 복원력, 코드 리뷰의 한계가 드러났고, Chris는 속도를 최우선으로 두는 조직 방향이 자신의 가치와 맞지 않아 떠남
5년간 맡았던 일과 코드베이스 규모
- Chris Krycho는 2019년 1월 말 LinkedIn에 합류해 약 5년 동안 근무함
- 담당 영역은 서버 인프라가 아니라 LinkedIn 데스크톱 웹 앱의 프런트엔드 인프라와 개발자 경험 개선이었음
- LinkedIn.com의 비모바일 브라우저 경험을 담당하는 데스크톱 앱에서 대규모 JavaScript 현대화 프로젝트를 이끎
- 이전 회사 앱은 약 15만 줄 규모였지만, LinkedIn 프런트엔드는 입사 당시 약 200만 줄 코드였음
- 같은 앱에 분기마다 150~200명 엔지니어가 커밋했고, 수십 개 팀이 하나의 제품을 계속 배포하는 구조였음
- 입사 당시 원격 엔지니어는 전체 수천 명 중 100명 미만이었고, Chris는 Colorado에서 원격으로 일하는 드문 사례였음
200만 줄 코드에서 마이그레이션하는 법
- 초기 대형 작업 중 하나는 Ember 기반 코드에 JavaScript의 현대적 class 문법을 도입하는 일이었음
- 기존 Ember 클래스와 네이티브 JavaScript 클래스가 상속 체인에서 섞이는 문제가 있었고, 내부에서는 이를 “Zebra Striping”이라고 부름
- 이 규모의 마이그레이션은 가능한 한 자동화되어야 했음
- 200만 줄을 수동으로 고치려면 몇 달 이상 걸릴 수 있음
- 제품팀에 기능 개발을 멈추고 새 문법 도입만 하라고 요구하기 어려움
- LinkedIn에는 여러 팀을 가로지르는 수평 이니셔티브(horizontal initiatives) 프로세스가 있었고, 제품팀 참여를 10% 이하로 유지하려는 운영 원칙이 있었음
- Chris 팀은 제품팀이 직접 코드 모드를 실행하는 방식보다, 인프라 팀이 자동화로 PR을 만들고 제품팀은 리뷰와 스모크 테스트를 맡는 방식이 더 쉽게 받아들여진다고 판단함
- Ember 관련 작업은 전체적으로 18개월이 걸렸고, 대부분은 6개월 안에 진행됐지만 일부 팀의 지연으로 긴 꼬리가 남음
TypeScript 도입을 설득한 오류 감소 논리
- Ember 현대화 이후 Chris 팀은 프런트엔드에서 발생하는 대량의 JavaScript 오류를 다음 대상으로 삼음
- LinkedIn은 오류 로그 규모가 커서 외부 서비스 대신 내부 로깅 인프라를 사용함
- LinkedIn은 전년도에 회원 수 10억 명을 넘겼고, Chris가 떠날 때 모노레포는 약 320만 줄 규모였음
- 절반은 테스트 코드
- 절반은 프로덕션 코드
- Chris 팀은 TypeScript가 잡을 수 있는 오류 범주를 따로 분석함
- 일부 오류는 TypeScript로도 잡을 수 없지만, 전체 마이그레이션을 마치면 하루 수백만 건 수준의 JavaScript 오류 중 애플리케이션 로그량을 최소 25% 줄일 수 있다고 봄
- Chris가 작성한 TypeScript 전환 문서는 엔지니어와 매니저 사이에서 반복적으로 공유됨
- 해결하려는 문제
- 기대할 수 있는 이점
- 채용 경쟁력에서의 비교
- 다른 우선순위와 비교할 판단 근거가 담김
- 이후 Chris는 까다로운 TypeScript 타입 문제를 도와주는 내부 전문가 역할을 맡게 됨
Ember에서 React로: 점진적 전환과 전면 재구상
- LinkedIn은 세계에서 가장 큰 EmberJS 사용자였지만, Chris의 업무는 결국 Ember에서 React로 옮기는 계획을 세우는 방향으로 바뀜
- 고위 리더들은 LinkedIn의 마이그레이션 비용이 너무 높고, 제품 속도를 늦춘다고 봄
- Chris 팀의 계획은 3~5년짜리 점진적 자동화 전략이었음
- 제품팀이 거의 멈추지 않도록 자동화를 강화함
- 빌드 파이프라인, 데이터 계층, 라우팅 계층, 반응성 시스템, 뷰 계층을 순서대로 분리해 전환함
- 마지막에 Ember 렌더링·반응성 시스템을 React 쪽으로 바꾸는 흐름이었음
- 다른 팀은 속도 문제를 더 직접적으로 겨냥함
- 아이디어에서 A/B 테스트까지 걸리는 시간을 몇 달에서 몇 주 수준으로 줄이는 것이 목표였음
- 데스크톱 웹, 모바일 웹, iOS, Android의 서로 다른 스택과 긴 사이클 타임을 문제로 봄
- Chris는 그 팀의 접근을 “finger guns mode”에 가까운 태도로 받아들임
- 수십 명을 지원하던 경험을 수백 명 엔지니어 지원으로 확장할 때 생길 문제를 충분히 다루지 않는다고 느낌
- 질문에 대해 “문제가 되지 않을 것”이라는 식의 반응이 많았다고 봄
- Chris 팀의 3~5년 계획은 리더십에게 좋은 반응을 얻지 못함
- 계획 자체가 길고 흥미롭지 않았음
- 팀도 “가장 덜 나쁜 선택”처럼 제안했기 때문에 설득력이 약했음
장애 대응에서 드러난 복원력 문제
- Chris가 크리스마스 휴가에서 돌아온 뒤 LinkedIn 일부 사용자에게 최대 약 20분 동안 LinkedIn.com 페이지가 보이지 않는 문제가 발생함
- 문제는 클라이언트 코드를 Node.js로 실행해 백엔드 데이터를 모아 빠르게 전달하는 프리렌더링 서비스와 관련돼 있었음
- 서비스에는 메모리 누수가 있었고, 컨테이너가 메모리 한도를 넘으면 재시작되는 구조였음
- 장애를 키운 요인이 여러 개 겹침
- 메모리 kill에 대한 알림이 충분하지 않았음
- 동시에 재시작할 수 있는 컨테이너 수 설정이 YAML 파일의 키로 존재했음
- 해당 값은 타입상 가능한 값이었지만, 이 시스템에는 잘못된 값이었음
- 설정값이 사실상 실행 중인 서비스 전체 수에 가까웠음
- 배포 중단이 긴 주말처럼 오래 이어질 때 서비스들이 비슷한 시점에 메모리를 소진했고, 한꺼번에 재시작되며 사용자 요청을 처리하지 못함
- 일부 서버가 내려가면 남은 서버의 부하가 커지고, 그 서버들의 메모리 사용량도 더 빨리 증가해 데이터센터 단위로 서버가 내려가는 상황이 생김
- 동시에 fleet의 CPU와 메모리 사용량을 줄이는 리소스 적정화(rightsizing) 작업이 진행돼 여유 공간이 줄어든 상태였음
- Chris와 다른 엔지니어들은 더 나은 알림, 관측성, 복원력이 필요하다고 봄
- Node 서버 하나가 runaway 상태가 되어도 호스트 프로세스까지 죽이지 않아야 함
- Node 프로세스만 종료하고 알림을 낸 뒤 재시작하는 편이 안전함
- 서비스가 내려가면 클라이언트 측 fetch로 넘어가는 대체 경로도 검토함
코드 리뷰만으로는 막을 수 없다는 충돌
- 장애 대응 회의는 주 여러 차례 진행됐고, 진행 상황을 공유하고 임원에게 보고하는 성격이 있었음
- 다른 팀의 매니저가 장애 대응을 맡으며 추가 인력을 투입했고, Chris는 자신과 기존 팀의 답을 신뢰하지 않는 흐름으로 받아들임
- 그 과정에서 한 시니어 엔지니어가 “왜 코드 리뷰가 이걸 해결하지 못하나?”라고 질문함
- Chris는 코드 리뷰만으로는 같은 일이 다시 발생하지 않도록 보장할 수 없다고 봄
- 사람은 실수함
- 주니어 엔지니어가 매우 시니어한 SRE의 PR에서 설정값이 합리적인지 의심하기 어려움
- 시스템은 시니어 엔지니어의 가장 좋은 날뿐 아니라, 주니어 엔지니어의 나쁜 날에도 안전하게 작동해야 함
- Chris에게 소프트웨어 엔지니어링은 제품 결과를 내는 엔지니어를 지원하는 시스템 설계까지 포함함
- 기술적 장애와 조직적 의사소통은 분리되지 않았고, Charity Majors의 말처럼 고위 수준에서는 순수하게 사회적이거나 순수하게 기술적인 문제만 존재하지 않음
리더십, 원격 문화, 가치 충돌
- Chris는 자신의 팀과 접근법이 다른 팀의 제안에 밀렸다고 봄
- 다른 팀의 계획은 데스크톱과 모바일 앱을 모두 다시 생각하는 방향으로 커졌고, LinkedIn의 제품 구축 방식을 전반적으로 재검토하는 성격이 됨
- Chris는 그 제안을 더 좋게 만들고 싶었지만, 우려나 질문이 충분히 받아들여지지 않는다고 느낌
- 한 매니저에게 “너는 너무 이상주의적이고, 손익을 충분히 신경 쓰지 않으며, 가치를 바꿔야 한다”는 말을 들었다고 함
- Chris는 원격 근무가 관계 형성에 영향을 줬다고 봄
- LinkedIn은 대면 문화가 강했고, 많은 사람이 카페테리아나 복도에서 자연스럽게 관계를 쌓음
- 고위 엔지니어·임원과의 반복적인 물리적 접촉이 갈등 상황에서 차이를 만들 수 있다고 느낌
- Chris는 자신에게도 관계 형성의 약점이 있었다고 돌아봄
결국 떠난 이유
- Chris는 기존 코드베이스의 많은 문제가 속도를 과대평가하고 보조 경로의 문제를 고치거나 제거하지 않은 결과라고 봄
- 속도가 최우선 가치가 되면 초반 속도는 얻을 수 있어도 시간이 지나며 유지하기 어렵다고 판단함
- 그는 이전 직장에서 번아웃을 겪었고, 심한 편두통, 복통, 운동 불능, 갑작스러운 울음, 공황 발작을 경험했다고 함
- LinkedIn에서 계속 일하면 매일 분노하지 않으려고 애써야 하는 상태가 이어질 것이라고 봄
- 거대한 조직의 방향을 작은 노젓는 배로 바꾸려는 상황에 비유하며, 자신이 믿지 않는 방식과 일에 몇 년을 쓰지 않기로 결정함
- Chris는 LinkedIn에서 300만 줄 규모 앱, 대기업의 TypeScript 마이그레이션, 대규모 엔지니어링 문제를 배웠지만, 자신의 가치와 맞는 일을 찾기 위해 떠남