왜 나는 Portage를 Go로 다시 작성했는가: GRPM v0.1.0 소개

발행: (2026년 1월 9일 오전 03:39 GMT+9)
10 min read
원문: Dev.to

Source: Dev.to

Gentoo Linux를 사용해 본 적이 있다면 Portage를 알고 있을 겁니다. 강력하고 유연하며… 파이썬 기반이죠. 수년간—말 그대로 수년 동안—나는 이 지속적인 생각을 했습니다: Portage가 Go로 작성된다면 어떨까? 빠른 컴파일, 단일 바이너리, 런타임 의존성 없음, 네이티브 동시성. 그 생각은 계속 떠올랐습니다.

지난 봄에 나는 결국 생각을 멈추고 코딩을 시작했습니다. “얼마나 어려운지 한번 해보자”는 생각으로 시작했지만 8 months에 걸친 집중 개발, ~60 000줄의 Go 코드, 그리고 패키지 관리자의 완전한 재‑구현으로 이어졌습니다.

오늘 나는 **GRPM v0.1.0 (Go Resource Package Manager)**를 공개합니다—현대적인 아키텍처와 충돌 없는 의존성 해결을 보장하는 Portage의 드롭‑인 대체제입니다.

Source:

왜 SAT‑기반 해결자를 사용할까?

전통적인 의존성 해결 알고리즘은 휴리스틱에 의존합니다. 충돌이 발생하면 포기하거나 최적이 아닌 선택을 하는 경우가 많습니다. Portage의 해결자는 정교하지만, 순환 의존성과 슬롯 충돌이 있는 복잡한 그래프에서는 여전히 실패할 수 있습니다.

나는 수학적으로 보장된 해결책을 원했습니다. 즉, 해가 존재한다면 반드시 찾을 수 있는 방법 말이죠.

핵심 아이디어

GRPM은 핵심에 Boolean Satisfiability (SAT) 솔버를 사용합니다.

  • 각 패키지 버전은 Boolean 변수가 됩니다.
  • 각 의존성은 논리 절(clause)로 변환됩니다.
// internal/solver/gophersat_adapter.go
type GophersatAdapter struct {
    clauses  [][]int
    vars     map[string]int            // name@version -> var ID
    packages map[string][]*pkg.Package // name -> []versions
}

func (g *GophersatAdapter) AddPackage(p *pkg.Package) {
    key := p.Name + "@" + p.Version
    g.packages[p.Name] = append(g.packages[p.Name], p)
    g.getVarID(key)
}

이렇게 하면 의존성 해결을 잘 연구된 수학 문제로 바꿀 수 있습니다. 유효한 설치가 존재한다면 SAT 솔버가 이를 찾아냅니다.

PropertyBenefit
Completeness해가 존재하면 찾아냄
Conflict handling여러 슬롯 버전, 차단자, USE 플래그 제약 → SAT 절
Speed최신 SAT 솔버는 수백만 변수도 처리
Dependenciesgophersat 사용, 순수 Go SAT 솔버 (CGO 없음)

아키텍처 (Domain‑Driven Design)

┌─────────────────────────────────────┐
│  CLI / Daemon Layer                 │
├─────────────────────────────────────┤
│  Application Layer   ← Use cases    │
├─────────────────────────────────────┤
│  Domain Layer         ← Business   │
│   (pkg, solver)                    │
├─────────────────────────────────────┤
│  Infrastructure Layer ← Repos, sync, install │
└─────────────────────────────────────┘

도메인 레이어는 Portage 파일 형식이나 파일 시스템 세부 사항에 대해 알지 못하므로, 코드베이스를 테스트하기 쉽고 확장 가능하게 만든다.

패키지 형식

GRPM은 최신 GPKG (.gpkg.tar)와 레거시 TBZ2 (.tbz2) 형식을 모두 지원합니다.

# Install from binary package
sudo grpm install --binpkg www-servers/nginx

# Build binary package from installed
sudo grpm build app-misc/hello-2.10

The binary‑package subsystem handles:

  • 다양한 압축 형식 (zstd, xz, gzip, bzip2)
  • 패키지 서명 (GPG, SSH, RSA)
  • 원격 binhost 지원

소스에서 빌드하기

# Build from source with 8 parallel jobs
sudo grpm emerge --jobs 8 dev-lang/go

# Show build plan first
grpm emerge --pretend app-misc/hello

Output

*** Dependency resolution (--pretend mode):
[ebuild  N    ] sys-libs/zlib-1.2.13 [0]
[ebuild  N    ] app-misc/hello-2.10 [0]

Total: 2 package(s)

GRPM은 모든 PMS 단계(pkg_setup, src_unpack, src_prepare, src_configure, src_compile, src_install)를 구현합니다.

리포지토리 동기화

외부 rsync 바이너리가 필요하지 않습니다—GRPM은 순수 Go 구현인 gokrazy/rsync를 사용합니다.

# Auto‑select best method
sudo grpm sync

# Use Git with GPG verification
sudo grpm sync --method git

# Native Go rsync (faster, no GPG)
sudo grpm sync --method rsync

데몬 모드 (gRPC & REST)

# Start daemon
sudo grpm daemon

# CLI auto‑connects to daemon if running
grpm status
  • gRPC는 Unix 소켓(/var/run/grpm.sock)에서 동작
  • REST API는 HTTP(127.0.0.1:8080)에서 동작
  • 충돌 감지를 포함한 작업 큐
  • 병렬 작업 지원

Btrfs/ZFS에서 스냅샷

GRPM은 패키지 작업 전에 자동으로 스냅샷을 생성합니다.

# Snapshot created automatically
sudo grpm install --snapshot-dir /.snapshots sys-libs/zlib

설치가 실패하면 스냅샷으로 롤백할 수 있습니다.

정규식 성능 향상

GRPM은 Go의 표준 regexp 패키지 대신 coregex를 사용합니다. 성능 차이가 극적입니다:

벤치마크표준 라이브러리 regexpcoregex속도 향상
Compile5 100 ns23 ns221×
Match185 ns1.5 ns123×

모든 정규식 패턴은 패키지 초기화 시 미리 컴파일됩니다:

// internal/repo/ebuild_parser.go
var (
    ebuildVarRe = coregex.MustCompile(`(?m)^([A-Z_][A-Z0-9_]*)="([^"]*)"`)

    ebuildAtomVersionRe = coregex.MustCompile(`^(.+?)-(\d.*)$`)
)

명령어 참조 (Portage‑친화적)

CommandDescription
grpm resolveSAT 솔버를 사용하여 의존성 해결
grpm install패키지 설치 (바이너리 또는 소스)
grpm emerge소스에서 패키지 빌드
grpm remove설치된 패키지 제거
grpm search패키지 검색
grpm info패키지 정보 표시
grpm sync저장소 동기화
grpm update@world/@system 패키지 업데이트
grpm depclean고아 패키지 제거
grpm status데몬 상태 표시

드라이‑런 및 확인

# Show what would happen (dry‑run)
grpm install --pretend app-misc/hello

# Ask for confirmation
sudo grpm install --ask app-misc/hello

--ask 사용 시 출력

*** Installation plan:
[ebuild  N    ] sys-libs/zlib-1.2.13 to / USE="..."
[ebuild  N    ] app-misc/hello-2.10 to / USE="..."

Total: 2 package(s)

Would you like to merge these packages? [Yes/No]

설치

# Download
wget https://github.com/grpmsoft/grpm/releases/download/v0.1.0/grpm_0.1.0_linux_x86_64.tar.gz

# Extract and install
tar -xzf grpm_0.1.0_linux_x86_64.tar.gz
sudo install -m 0755 grpm /usr/bin/grpm

GRPM으로 더 빠르고 의존성 충돌이 없는 Gentoo 경험을 즐기세요!

빠른 명령

작업명령
저장소 동기화sudo grpm sync
패키지 검색grpm search firefox
패키지 정보 표시grpm info dev-lang/go
소스에서 빌드 (예상)sudo grpm emerge --pretend app-misc/hello
소스에서 빌드 (실제)sudo grpm emerge app-misc/hello
바이너리에서 설치sudo grpm install --binpkg app-misc/hello

프로젝트 개요

  • 언어: Go 1.25+
  • 라이선스: Apache‑2.0
  • 지원 플랫폼: Linux (x86_64, arm64, armv7, armv6, i386)
  • 코드베이스 규모: ~60 000줄의 Go
  • 테스트 커버리지: ~70 %

Core Dependencies

DependencyPurpose
gophersat의존성 해결을 위한 SAT 솔버
cobraCLI 프레임워크
grpc데몬 통신
gokrazy/rsync네이티브 rsync 구현
modernc.org/sqlite캐싱을 위한 순수 Go SQLite
coregex고성능 정규식 엔진

모든 의존성은 순수 Go이며 — CGO가 필요 없습니다.

현재 제한 사항 (v0.1.0)

  • Ebuild 실행이 autotools 워크플로우(./configure && make)에만 제한됨
  • 제한된 eclass 지원(toolchain-funcs, eutils, multilib)
  • EAPI 8 기능 없음
  • CMake/Meson 빌드 시스템 미지원

이러한 문제들은 향후 릴리스에서 해결될 예정입니다.

로드맵 – v1.0.0 (2026년 2분기)

  • Portage 명령 호환성 완전 구현
  • 전체 eclass 지원
  • EAPI 8 기능
  • CMake, Meson 및 Cargo 빌드 시스템 지원
  • 대규모 의존성 그래프에 대한 성능 최적화
  • 실제 Gentoo 시스템에서의 프로덕션 검증

왜 GRPM을 만들까요?

  1. 학습 – 패키지 관리자는 매력적인 시스템입니다. 처음부터 하나를 구축하면 의존성 그래프, 제약 해결, 파일 시스템 작업 및 시스템 통합에 대해 배울 수 있습니다.
  2. 성능 – Go의 빠른 컴파일, 효율적인 메모리 사용, 뛰어난 동시성은 시스템 도구에 이상적입니다.
  3. 커뮤니티 – Gentoo는 현대적인 도구를 필요로 합니다. GRPM이 몇 명이라도 사용자에게 도움이 된다면 그 노력은 가치가 있습니다.

직접 사용해 보기

  • 저장소:
  • 릴리스:
  • 문서: CLI Reference (link to be added)

기여

기여를 환영합니다! 버그 보고, 기능 요청, 혹은 코드 기여 등 어떤 형태든 도움이 됩니다.

직접 패키지 매니저를 만들어 보셨나요? 아니면 다른 분야에서 SAT 솔버를 사용한 경험이 있으신가요? 댓글로 이야기를 들려주세요.

Back to Blog

관련 글

더 보기 »

경량 크로스플랫폼 Hosts 관리 도구

소개 Go Hosts는 Go + Fyne으로 개발된 가벼운 크로스 플랫폼 Hosts 관리 도구로, Windows와 macOS(Intel)를 지원합니다. 용량이 큰 Electron 애플리케이션(예: SwitchHosts)과 비교했을 때, Go Hosts는 더 작고 컴파일 및 패키징이 유연하여 작은 도구에 집착하는 사용자에게 적합합니다. - GitHub 오픈소스 주소...