scratch 프로젝트와 Rush 모노레포: 개발 환경 최적화 전략
스크래치 (scratch) 란 무엇인가
- 스크래치는 교육용 비주얼 프로그래밍 언어로, 전 세계 초중등 교육에서 프로그래밍 입문 도구로 활용되고 있음
핵심 특징
1. 블록 기반 프로그래밍 : 텍스트 코딩 대신 끌어다 놓는 방식의 직관적인 인터페이스
2. 시각적 피드백 : 코드 실행 결과를 즉시 확인 가능
3. 다양한 미디어 지원 : 그래픽, 사운드, 애니메이션 등 통합 환경을 제공
4. 교육적 설계 : 사용자가 변수, 반복문, 조건문, 함수 등 프로그래밍의 기본 개념을 직관적으로 학습할 수 있도록 도와줌
스크래치 프로젝트의 현재 구조
스크래치는 오픈소스로서 물리적으로 여러 개의 독립적인 저장소로 분리되어 있지만, 기능적으로는 모노레포처럼 동작하는 독특한 구조를 가지고 있음
https://github.com/scratchfoundation
Scratch Foundation
Scratch. Scratch Foundation has 66 repositories available. Follow their code on GitHub.
github.com
주요 패키지 구성
1. scratch-gui : 사용자의 인터페이스를 담당 (React 기반)
2. scratch-vm : 스크래치 실행 엔진 (가상머신), 블록이 실행되는 로직을 처리함
3. scratch-blocks : 블록 프로그래밍 인터페이스 (google blockly 기반)
4. scratch-render : 스테이지 영역을 렌더링함
스크래치의 현재, 기능적 모노레포 방식
스크래치는 현재 다음과 같은 방식으로 개발되고 있음.
1. 각 패키지가 별도의 github 저장소로 관리되고 있음.
2. 개발 시에는 npm link를 사용하여, 로컬에서 패키지 간 의존성을 연결해야 함
3. 패키지 간 강한 의존성으로 인해 하나의 변경이 여러 패키지에 영향을 미침
# 현재 개발 방식 예시
git clone https://github.com/scratchfoundation/scratch-vm.git
cd scratch-vm
npm install
npm link
git clone https://github.com/scratchfoundation/scratch-gui.git
cd scratch-gui
npm install
npm link scratch-vm
현재 방식의 문제점
1. 복잡한 개발환경 설정
- 여러 저장소를 클론하고, npm link로 연결하는 이 과정이 번거로움
- 새로운 개발자의 온보딩 과정이 복잡하고 시간 소모가 큼. (언제 다 하고 있나 관점)
2. 의존성 관리의 불안정성
- npm link는 불안정함. 예상치 못한 문제를 일으킬 가능성이 있음.
- 패키지 간 버전 관리 부분에서 충돌 발생이 일어날 수 있음.
3. 일관성 유지 어려움
- 여러 저장소에 걸친 코드 스타일, lint 규칙 등 일관성 유지가 어려움
- 통합 테스트 구현도 복잡해짐.
4. 비효율적인 빌드 프로세스
- 각 패키지를 개별적으로 빌드해야 함.
- 최적화된 빌드 파이프라인을 구성할 수 있을 지? 구성이 어려움.
왜 모노레포가 필요한가?
모노레포는 여러 프로젝트나 패키지를 단일 저장소에서 관리하는 방식이다. 앞서 작성한 스크래치와 같이 밀접하게 연관된 여러 패키지로 구성된 프로젝트에서 모노레포를 적용하게 된다면 좋은 이점들이 있다.
1. 통합된 코드 베이스
- 모든 코드가 한 곳에 있어서 전체 시스템 파악이 용이함.
- 패키지간에 의존성 관계가 조금 더 명시적임.
2. 원활한 리팩토링
- 여러 패키지에 걸친 변경들을 단일 커밋으로 처리할 수 있음. 편함
- 대규모 구조 변경을 할 때도 용이해짐
3. 일관된 개발 환경
- 모든 패키지에 동일한 lint, test, build 규칙을 적용할 수 있음. (번거롭지 않다)
- 개발 환경 설정이 간소화 됨
4. 최적화된 빌드 프로세스
- 변경된 패키지만 선택적으로 빌드하고 테스트 할 수 있음.
- 패키지 간 의존성을 고려한 빌드 순서가 자동화 됨
5. 버전 관리 간소화
- 패키지 간에 버전이 일관됨
- 릴리스 프로세스 통합
Rush를 사용하는 이유
rush는 마이크로소프트에서 개발한 확장가능한 모노레포 관리 도구로, 대규모 js / ts 프로젝트에 최적화 되어 있음.
rush를 사용해야 하는 다양한 이유가 있음
1. 엔터프라이즈 급의 확장성
- 수백 개의 패키지들도 효율적으로 관리할 수 있음.
- 스크래치의 복잡한 의존성 구조 처리에 적합함.
2. PNPM 기반의 의존성 관리
- npm link 보다 안정적인 로컬 의존성이 해결됨
- 디스크 공간 절약 및 설치 속도 향상
3. 중분 빌드 지원
- 변경된 패키지와 그 의존성만 빌드하여서 개발 생산성이 향상됨
- 대규모의 CI 파이프라인에 최적화 됨
4. 정책 시스템
- 패키지 버전, 의존성 관리에 대한 정책 적용
- 일관된 코드 품질을 유지함
5. 병렬 처리
- 독립적인 패키지를 병렬로 빌드해서 성능을 향상시킴
- 멀티 코어 활용이 최적화됨
Rush를 활용한 스크래치 모노레포 구성 방안
1. 저장소 구조
scratch-monorepo/
├── common/
│ ├── config/ # 공통 린트, 테스트 설정
│ └── scripts/ # 공유 빌드 스크립트
├── rush.json # Rush 설정 파일
└── packages/
├── scratch-gui/
├── scratch-vm/
├── scratch-blocks/
├── scratch-render/
├── scratch-l10n/
└── scratch-desktop/
2. Rush 설정 예시
{
"rushVersion": "5.86.1",
"pnpmVersion": "7.18.2",
"projectFolderMinDepth": 2,
"projectFolderMaxDepth": 2,
"projects": [
{
"packageName": "scratch-blocks",
"projectFolder": "packages/scratch-blocks"
},
{
"packageName": "scratch-vm",
"projectFolder": "packages/scratch-vm"
},
{
"packageName": "scratch-gui",
"projectFolder": "packages/scratch-gui"
},
{
"packageName": "scratch-render",
"projectFolder": "packages/scratch-render"
},
{
"packageName": "scratch-l10n",
"projectFolder": "packages/scratch-l10n"
},
{
"packageName": "scratch-desktop",
"projectFolder": "packages/scratch-desktop"
}
]
}
3. 개발 워크플로우 개선
# 모노레포 클론
git clone https://github.com/example/scratch-monorepo.git
cd scratch-monorepo
# Rush 초기화
rush update
# 모든 프로젝트 빌드
rush build
# GUI와 그 의존성만 빌드
rush build --to scratch-gui
# 변경된 패키지만 빌드
rush build --changed-projects-only