22. 대규모 변경
23 Apr 2023 | Software Engineering
22. 대규모 변경
- 구글에서는 코드베이스 전반을 전면적으로 건드리는 변경을 원자적으로 수행한다는 아이디어를 포기함
- 코드베이스와 엔지니어의 수가 늘어날수록 원자적으로 수행하 ㄹ수 있는 변경의 크기는 줄어듬
- 영향받는 모든 프리서브밋 검사와 테스트를 수행하기가 어렵고, 서브밋 전에 변경에 포함된 파일 전부가 최신 버전인지도 확신할 수 없게 됩니다.
- 기반 인프라를 계속 개선시켜야 하는데, 전면적인 변경은 점점 어려워짐
- 이를 해결할 수 있는 대규모 변경 방법을 현실에서 수행할 방법을 찾아내야 함
22.1 대규모 변경(Large Scale Change)이란?
- LSC는 연관되어 있으나 현실적인 한계 때문에 원자적으로 서브밋할 수 없는 변경들의 집합
- 이유는
- 너무 많은 파일을 건드려서 기반 도구가 단번에 커밋하지 못함
- 너무 커다란 변경이라 병합 과정에서 항상 출동이 나서
- LSC는 리포지터리 토폴러지에 영향을 많이 받음
- 분산 리포지터리를 이용하거나 여러 리포지터리를 연합해 이용하고 있다면 원자적으로 변경하기가 기술적으로도 애초에 불가능 할 것임
- 구글의 경우 LSC는 거의 항상 자동화 도구를 이용해 생성함
- LSC로 인해 생성되는 변경들은 대체로 다음과 같이 분류할 수 있음
- 코드 베이스 전반을 훑는 분석 도구로 찾은 공통 안티패턴 청소
- 폐기 대상 API 호출 대체
- (컴파일러 업그레이드 등) 저수준 인프라 개선사항 활성화
- 사용자들을 옛 시스템에서 새로운 시스템으로 마이그레이션
- 구글에서 수행하는 LSC의 대다수는 기능은 거의 변경하지 않음
- 주로 명확성, 최적화 미래 호환성 개선등이 목표
- 구글 스케일에서는 몇백만개의 참조를 수정할 때도 있다
22.2 누가 대규모 변경을 처리하나?
- 구글에서는 LSC의 상당 비중을 인프라팀들이 수행함
- 인프라팀은 이런일에 대한 전문가이다. 전문가가 일을 처리하는 것이 좋다
- 조직차원에서 처리해야 한다
- 대규모로 변경해야 할 시스템을 소유한 팀이 주도해야 변경을 완료하는 데 유리함
22.3 원자적 변경을 가로막는 요인
- 구글의 LSC 프로레스를 이야기하려면 먼저 왜 수많은 변경들이 원자적으로 커밋될 수 없는지를 이해해야 함
- 이상적인 세계에서는 모든 논리적 변경은 하나의 원자적 단위로 묶어서 다른 변경들과 독립적으로 한 번에 테스트하고 리뷰하고 커밋할 수 있어야 함
22.3.1 기술적 한계
- VCS에서는 기능을 수행하는 비용이 변경의 크기에 비례해 커짐
- 수십 개 규모의 작은 커밋을 무리없이 처리할 수 있지만, 파일 수천 개를 원자적으로 커밋하기에느 ㄴ힘들어 할 수 있음
- 중앙집중형 VCS에서는 커밋 중에는 다른 사용자가 쓰기 작업을 못함
- 거대한 커밋은 다른 사용자들의 일을 멈춰세운다.
- 인프라에 따라 아예 불가능한 일일 수 있다
23.3.2 병합 충돌
- 변경의 규모가 커질수록 자연스럽게 병합 시 충돌이 생길 가능성이 커짐
- 회사가 작다면 아무도 출근안했을때 얼른 처리해볼 수도 있지만, 구글은 불가능…
- 변경하는 파일이 적다면 병합 출동 확률이 작으므로 문제없이 커밋될 가능성이 높아짐
22.3.3 유령의 묘지
- 유령의 묘지(haunted graveyard)란 너무 오래되고 둔하고 복잡해서 아무도 손대려 하지 않는 시스템을 뜻함
- 사업상 아주 중요한 시스템 중에 유명의 묘지가 많음
- 코드베이스에서 이런 부분은 LSC 프로세스를 방해하는 걸림돌
- 더 나은 라이브러리와 컴파일러를 도입하지 못하게 하고, 낡은 시스템을 폐기시키지 못하게 함
- 테스트를 충실히 하면 이 유령의 묘지를 없앨 수 있음
22.3.4 이질성
- LSC가 가능하려면 작업을 사람이 아닌 컴퓨터가 대부분 처리해주어야 함
- 프리서브밋 검사에서 이러한 검사를 실패로 처리하는 경우가 있음
- LSC때는 눈감아 줘야 함
22.3.5 테스트
- 모든 변경은 테스트 되어야 한다
- 변경의 덩치가 커지면 제대로 테스트하기가 훨씬 어려움
- 작고 독립적인 변경은 검증하기 쉬움
22.3.6 코드리뷰
- 모든 변경은 서브밋하기 전에 리뷰를 거쳐야 함
- LSC도 예외는 아님
- LSC를 별도의 샤드로 나누면 훨씬 쉬워짐
22.4 대규모 변경 인프라
- 구글은 LSC를 가능하게 하기 위해 인프라에 막대한 투자를 함
- 변경 생성
- 변경 관리
- 변경 리뷰
- 테스트 도구
- 문화적 규범의 진화
22.4.1 정책과 문화
- 구글은 LSC를 만들려는 팀과 ㅣ개인을 위한 가벼운 승인 프로세스를 고안
- 다양한 언어의 미묘한 특성에 익숙한 숙련된 엔지니어 그룹이 감독
- 새로 만들려는 LSC 관련 도메인 전문가 초대
- 변경 작성자가 구글의 기술과 인적 지원을 최대한 활용하여 가장 이상적인 변경을 생성하도록 돕는 것
22.4.2 코드베이스 인사이트
- LSC를 진행하려면 코드베이스 전반을 분석할 수 있어야 함
- 의미론적 인덱싱 도구, 컴파일러 기반 인덱스 등을 이용하여 코드베이스에 대한 분석을 해야 함
- ClangMR
- JavaFlume
- Refaster
- …
24.4.3 변경 관리
- 마스터 변경을 여러 개의 샤드로 나눈 후 테스트, 메일링, 리뷰, 커밋 단계를 독립적으로 관리해주는 도구
- 구글은 Rosie를 사용 함
24.4.4 테스트
- 테스트도 중요함
- 표준적인 프로젝트별 프리서브밋 테스트를 이용하지 않음
24.4.5 언어 지원
- 구글은 LSC를 주로 언어별로 진행하며, 언어에 따라 LSC 난이도가 크게 다름
- 타입 별칭과 전달 함수를 지원하는 프로그래밍 언어라면 새로운 시스템으로 마이그레이션하는 중에도 기존 코드가 문제없이 동작하게 만들기가 훨씬 쉬움 (C++, JAVA…)
- 아닌 애들은 어려움 (Python, JS…)
- 자동 포맷터도 중요함
22.5 대규모 변경 프로세스
- 관한 부여
- 변경 생성
- 샤드 관리
- 마무리 청소
22.5.1 권한 부여
- LSC 작성자에게 다음의 내용을 포함한 간단한 제안 문서를 작성해달라고 요청
- 변경을 제안하는 이유
- 코드베이스 전반에 주는 예상 영향 (ex: 제안한 LSC로 인해 생성되는 작은 샤드 수)
- 리뷰어들이 던질만한 질문과 그에 대한 답변
- 이후 프로세스 감독자 10여 명으로 구성된 위원회에 제안을 송부
- 피드백
- 글로벌 승인자에게 할당
- 위원회는 승인에 관대하다
22.5.2 변경 생성
- 승인을 얻은 LSC작성자는 실제로 코드를 수정하기 시작함
- 거대한 전역 변경 하나를 생성한 후 다수의 독립적인 샤드로 쪼갬
- 변경 생성 프로세스는 가능한 한 자동화해야 함
22.5.3 샤드로 나누기와 서브밋
- 글로벌 변경을 생성했다면, Rosie를 실행함
- 거대한 변경을 하나 입력받아서 서브밋할 수 있는 샤드들로 쪼개 줌
- 프로젝트 경계와 소유권 규칙을 참고
- 개별 샤드를 독립된 테스트-메일-서브밋 파이프라인에 태움
테스트하기
- 독립된 샤드 각각은 구글의 CI 프레임워크인 TAP에 의해 테스트됨
- 변경이 크므로 이 테스트는 부하가 크다
- 실제 대다수의 샤드는 천 개 이하의 테스트만 수행 (구글의 테스트는 수백만 개에 이름)
- 더 많은 테스트를 수행해야 하는 샤드들은 일단 하나의 그룹으로 묶음
- 그룹 내 샤드들에 영향받는 테스트 모두를 1차로 수행
- 2차로는 샤드별로 테스트하는데, 해당 샤드에 영향받는 테스트 중 1차 때 실패한 테스트들만 수행
- 2차부터는 비용이 거의 공짜
- 구글의 자동화 도구에서는 서브밋 시 최근에 튄 불규칙한 테스트르리 무시하도록 함
리뷰어에게 메일 보내기
- OWNERS 파일 기반으로 리뷰 요청
리뷰하기
- LSC는 엄격하게 리뷰하지는 않음
- 인프라팀을 믿고 피상적인 수준으로만 살펴보고 통과함
서브밋하기
- 개별 변경을 커밋
22.5.4 마무리 청소
- 옛 시스템 완벽히 제거
- 중요한 참조들을 마이스레이션한 후 옛 참조들은 자연스럽게 사라지도록 내버려두기
- …
- 대규모 변경이 애써 제거한 심볼이나 시스템이 다시 사용되는 일을 막아주는 방책이 꼭 필요함
- Tricorder
22.7 핵심 정리
- LSC 프로세스는 되돌릴 수 없다고 여기던 기술적 결정들을 다시 생각해볼 수 있게 해줌
- 전통적인 리팩터링 모델은 코드 규모가 커지면 한계를 드러냄
- LSC에 성공하려면 LSC를 습관처럼 진행해야 함 (코드베이스가 오래될 수록 고치기가 점점 어려워 짐)
22. 대규모 변경
- 구글에서는 코드베이스 전반을 전면적으로 건드리는 변경을 원자적으로 수행한다는 아이디어를 포기함
- 코드베이스와 엔지니어의 수가 늘어날수록 원자적으로 수행하 ㄹ수 있는 변경의 크기는 줄어듬
- 영향받는 모든 프리서브밋 검사와 테스트를 수행하기가 어렵고, 서브밋 전에 변경에 포함된 파일 전부가 최신 버전인지도 확신할 수 없게 됩니다.
- 기반 인프라를 계속 개선시켜야 하는데, 전면적인 변경은 점점 어려워짐
- 이를 해결할 수 있는 대규모 변경 방법을 현실에서 수행할 방법을 찾아내야 함
22.1 대규모 변경(Large Scale Change)이란?
- LSC는 연관되어 있으나 현실적인 한계 때문에 원자적으로 서브밋할 수 없는 변경들의 집합
- 이유는
- 너무 많은 파일을 건드려서 기반 도구가 단번에 커밋하지 못함
- 너무 커다란 변경이라 병합 과정에서 항상 출동이 나서
- LSC는 리포지터리 토폴러지에 영향을 많이 받음
- 분산 리포지터리를 이용하거나 여러 리포지터리를 연합해 이용하고 있다면 원자적으로 변경하기가 기술적으로도 애초에 불가능 할 것임
- 구글의 경우 LSC는 거의 항상 자동화 도구를 이용해 생성함
- LSC로 인해 생성되는 변경들은 대체로 다음과 같이 분류할 수 있음
- 코드 베이스 전반을 훑는 분석 도구로 찾은 공통 안티패턴 청소
- 폐기 대상 API 호출 대체
- (컴파일러 업그레이드 등) 저수준 인프라 개선사항 활성화
- 사용자들을 옛 시스템에서 새로운 시스템으로 마이그레이션
- 구글에서 수행하는 LSC의 대다수는 기능은 거의 변경하지 않음
- 주로 명확성, 최적화 미래 호환성 개선등이 목표
- 구글 스케일에서는 몇백만개의 참조를 수정할 때도 있다
22.2 누가 대규모 변경을 처리하나?
- 구글에서는 LSC의 상당 비중을 인프라팀들이 수행함
- 인프라팀은 이런일에 대한 전문가이다. 전문가가 일을 처리하는 것이 좋다
- 조직차원에서 처리해야 한다
- 대규모로 변경해야 할 시스템을 소유한 팀이 주도해야 변경을 완료하는 데 유리함
22.3 원자적 변경을 가로막는 요인
- 구글의 LSC 프로레스를 이야기하려면 먼저 왜 수많은 변경들이 원자적으로 커밋될 수 없는지를 이해해야 함
- 이상적인 세계에서는 모든 논리적 변경은 하나의 원자적 단위로 묶어서 다른 변경들과 독립적으로 한 번에 테스트하고 리뷰하고 커밋할 수 있어야 함
22.3.1 기술적 한계
- VCS에서는 기능을 수행하는 비용이 변경의 크기에 비례해 커짐
- 수십 개 규모의 작은 커밋을 무리없이 처리할 수 있지만, 파일 수천 개를 원자적으로 커밋하기에느 ㄴ힘들어 할 수 있음
- 중앙집중형 VCS에서는 커밋 중에는 다른 사용자가 쓰기 작업을 못함
- 거대한 커밋은 다른 사용자들의 일을 멈춰세운다.
- 인프라에 따라 아예 불가능한 일일 수 있다
23.3.2 병합 충돌
- 변경의 규모가 커질수록 자연스럽게 병합 시 충돌이 생길 가능성이 커짐
- 회사가 작다면 아무도 출근안했을때 얼른 처리해볼 수도 있지만, 구글은 불가능…
- 변경하는 파일이 적다면 병합 출동 확률이 작으므로 문제없이 커밋될 가능성이 높아짐
22.3.3 유령의 묘지
- 유령의 묘지(haunted graveyard)란 너무 오래되고 둔하고 복잡해서 아무도 손대려 하지 않는 시스템을 뜻함
- 사업상 아주 중요한 시스템 중에 유명의 묘지가 많음
- 코드베이스에서 이런 부분은 LSC 프로세스를 방해하는 걸림돌
- 더 나은 라이브러리와 컴파일러를 도입하지 못하게 하고, 낡은 시스템을 폐기시키지 못하게 함
- 테스트를 충실히 하면 이 유령의 묘지를 없앨 수 있음
22.3.4 이질성
- LSC가 가능하려면 작업을 사람이 아닌 컴퓨터가 대부분 처리해주어야 함
- 프리서브밋 검사에서 이러한 검사를 실패로 처리하는 경우가 있음
- LSC때는 눈감아 줘야 함
22.3.5 테스트
- 모든 변경은 테스트 되어야 한다
- 변경의 덩치가 커지면 제대로 테스트하기가 훨씬 어려움
- 작고 독립적인 변경은 검증하기 쉬움
22.3.6 코드리뷰
- 모든 변경은 서브밋하기 전에 리뷰를 거쳐야 함
- LSC도 예외는 아님
- LSC를 별도의 샤드로 나누면 훨씬 쉬워짐
22.4 대규모 변경 인프라
- 구글은 LSC를 가능하게 하기 위해 인프라에 막대한 투자를 함
- 변경 생성
- 변경 관리
- 변경 리뷰
- 테스트 도구
- 문화적 규범의 진화
22.4.1 정책과 문화
- 구글은 LSC를 만들려는 팀과 ㅣ개인을 위한 가벼운 승인 프로세스를 고안
- 다양한 언어의 미묘한 특성에 익숙한 숙련된 엔지니어 그룹이 감독
- 새로 만들려는 LSC 관련 도메인 전문가 초대
- 변경 작성자가 구글의 기술과 인적 지원을 최대한 활용하여 가장 이상적인 변경을 생성하도록 돕는 것
22.4.2 코드베이스 인사이트
- LSC를 진행하려면 코드베이스 전반을 분석할 수 있어야 함
- 의미론적 인덱싱 도구, 컴파일러 기반 인덱스 등을 이용하여 코드베이스에 대한 분석을 해야 함
- ClangMR
- JavaFlume
- Refaster
- …
24.4.3 변경 관리
- 마스터 변경을 여러 개의 샤드로 나눈 후 테스트, 메일링, 리뷰, 커밋 단계를 독립적으로 관리해주는 도구
- 구글은 Rosie를 사용 함
24.4.4 테스트
- 테스트도 중요함
- 표준적인 프로젝트별 프리서브밋 테스트를 이용하지 않음
24.4.5 언어 지원
- 구글은 LSC를 주로 언어별로 진행하며, 언어에 따라 LSC 난이도가 크게 다름
- 타입 별칭과 전달 함수를 지원하는 프로그래밍 언어라면 새로운 시스템으로 마이그레이션하는 중에도 기존 코드가 문제없이 동작하게 만들기가 훨씬 쉬움 (C++, JAVA…)
- 아닌 애들은 어려움 (Python, JS…)
- 자동 포맷터도 중요함
22.5 대규모 변경 프로세스
- 관한 부여
- 변경 생성
- 샤드 관리
- 마무리 청소
22.5.1 권한 부여
- LSC 작성자에게 다음의 내용을 포함한 간단한 제안 문서를 작성해달라고 요청
- 변경을 제안하는 이유
- 코드베이스 전반에 주는 예상 영향 (ex: 제안한 LSC로 인해 생성되는 작은 샤드 수)
- 리뷰어들이 던질만한 질문과 그에 대한 답변
- 이후 프로세스 감독자 10여 명으로 구성된 위원회에 제안을 송부
- 피드백
- 글로벌 승인자에게 할당
- 위원회는 승인에 관대하다
22.5.2 변경 생성
- 승인을 얻은 LSC작성자는 실제로 코드를 수정하기 시작함
- 거대한 전역 변경 하나를 생성한 후 다수의 독립적인 샤드로 쪼갬
- 변경 생성 프로세스는 가능한 한 자동화해야 함
22.5.3 샤드로 나누기와 서브밋
- 글로벌 변경을 생성했다면, Rosie를 실행함
- 거대한 변경을 하나 입력받아서 서브밋할 수 있는 샤드들로 쪼개 줌
- 프로젝트 경계와 소유권 규칙을 참고
- 개별 샤드를 독립된 테스트-메일-서브밋 파이프라인에 태움
테스트하기
- 독립된 샤드 각각은 구글의 CI 프레임워크인 TAP에 의해 테스트됨
- 변경이 크므로 이 테스트는 부하가 크다
- 실제 대다수의 샤드는 천 개 이하의 테스트만 수행 (구글의 테스트는 수백만 개에 이름)
- 더 많은 테스트를 수행해야 하는 샤드들은 일단 하나의 그룹으로 묶음
- 그룹 내 샤드들에 영향받는 테스트 모두를 1차로 수행
- 2차로는 샤드별로 테스트하는데, 해당 샤드에 영향받는 테스트 중 1차 때 실패한 테스트들만 수행
- 2차부터는 비용이 거의 공짜
- 구글의 자동화 도구에서는 서브밋 시 최근에 튄 불규칙한 테스트르리 무시하도록 함
리뷰어에게 메일 보내기
- OWNERS 파일 기반으로 리뷰 요청
리뷰하기
- LSC는 엄격하게 리뷰하지는 않음
- 인프라팀을 믿고 피상적인 수준으로만 살펴보고 통과함
서브밋하기
- 개별 변경을 커밋
22.5.4 마무리 청소
- 옛 시스템 완벽히 제거
- 중요한 참조들을 마이스레이션한 후 옛 참조들은 자연스럽게 사라지도록 내버려두기
- …
- 대규모 변경이 애써 제거한 심볼이나 시스템이 다시 사용되는 일을 막아주는 방책이 꼭 필요함
- Tricorder
22.7 핵심 정리
- LSC 프로세스는 되돌릴 수 없다고 여기던 기술적 결정들을 다시 생각해볼 수 있게 해줌
- 전통적인 리팩터링 모델은 코드 규모가 커지면 한계를 드러냄
- LSC에 성공하려면 LSC를 습관처럼 진행해야 함 (코드베이스가 오래될 수록 고치기가 점점 어려워 짐)
Comments