문서와 심볼

aidlc-docs 를 그대로 읽는다 · 읽기 전용
/home/sunny/enode-fixup-workshop2-visualizer연결 중
inception/reverse-engineering/technology-stack.md160 줄

enode — 기술 스택

go.mod · go.sum · CI 워크플로 · 소스 주석에서 직접 확인한 것.
의도적으로 없는 것이 이 저장소에서는 있는 것만큼 중요하다.

언어와 런타임

항목 값 근거
언어 Go 전 소스
언어 버전 하한 go 1.26 go.mod
툴체인 toolchain go1.26.6 go.mod
모듈 github.com/taeels/enode go.mod

go.mod 주석이 둘을 같은 버전으로 묶은 이유를 적어 두었다.

둘을 같은 버전으로 묶어 슬랙을 없앴다 — 넷이 서로 다른 컴파일러로 짜면
"내 기계에서는 되는데" 가 나온다. 명시적 실패가 조용한 드리프트보다 낫다

CI 도 같은 원칙을 따른다. actions/setup-go 가 go-version-file: go.mod 로
버전을 읽으므로 버전이 두 곳에 적히지 않는다.

직접 의존 라이브러리 (3)

라이브러리 버전 쓰임 쓰는 곳
github.com/jackc/pgx/v5 v5.10.0 PostgreSQL 드라이버 + pgxpool 커넥션 풀 internal/store 전용
golang.org/x/sys v0.47.0 파일 잠금(flock / LockFileEx)과 디스크 여유 측정의 OS 분기 internal/enode (lock_*.go · disk_*.go)
gopkg.in/yaml.v3 v3.0.1 Mediator 설정과 노드 local.yaml 파싱 internal/config · internal/enode/config.go

셋 전부 실사용된다. 미사용 의존 0건.

표준 라이브러리로 대신한 것 — 의도적 부재

이 저장소의 성격을 가장 잘 드러내는 절이다. 없는 것들이 대부분 코드 주석에
설계 결정으로 기록돼 있다.

웹 프레임워크 없음

표준 net/http 과 Go 1.22+ ServeMux 의 메서드+경로 패턴만 쓴다. 라우트 15개가
internal/api/api.go:53 Handler() 한 함수에 등록되고, 그 결정이 api.go 헤더
주석에 적혀 있다.

결과: 라우트 전수 확인이 grep 하나로 끝난다. 미들웨어 체인 대신
s.auth(handler) 명시적 래핑이라 인증 누락 라우트를 눈으로 셀 수 있다(현재 0).

테스트 프레임워크 없음

표준 testing 만 쓴다. assertion 라이브러리도 mock 라이브러리도 없다.

결과: internal/api/api_test.go 는 mock 대신 실제 PostgreSQL 을 띄우고
httptest 로 서버를 세우는 통합 스위트가 됐다(78개 테스트, 3,342줄). CI 는
Postgres 17 서비스 컨테이너를 붙이고, internal/api 에 SKIP 이 한 줄이라도
나오면 실패시키는 전용 단계를 따로 둔다.

ci.yml 주석이 근거를 적는다.

진짜 Postgres 로 돈다 — I5(전부 아니면 전무)는 트랜잭션으로 얻는 것이라
가짜 저장소로는 검증되지 않는다.

ORM · 마이그레이션 도구 없음

internal/store/schema.sql(144줄)을 //go:embed 로 바이너리에 넣고
Store.Migrate 가 통째로 Exec 한다. 모든 DDL 이 IF NOT EXISTS /
ADD COLUMN IF NOT EXISTS 로 멱등하게 쓰여 있다.

store.go:71 이 의도를 적는다 — "MVP 는 마이그레이션 도구를 안 쓴다 — 스키마가
굳으면 그때 넣는다". 이것의 운영 함의는 code-quality-assessment.md 참조.

로거 없음

표준 log/slog 만. 외부 로깅 라이브러리 없음.

코드 생성 · 벤더링 · Makefile 없음

go:generate 없음, vendor/ 없음, Makefile 없음. 빌드는 go build ./... 다.

OpenAPI · Swagger 없음

정본 문서가 "OpenAPI 로 굳히지 않는다" 를 명시했다. godoc 외의 생성 문서 없음.

린터 설정 없음

golangci-lint 설정 파일이 없다. CI 가 강제하는 것은 gofmt -l . 와
go vet ./... 둘, 그리고 저장소 고유의 장식 문자 검사 하나다.

간접 의존 (7)

라이브러리 버전
github.com/jackc/pgpassfile v1.0.0
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761
github.com/jackc/puddle/v2 v2.2.2
github.com/kr/text v0.2.0
github.com/rogpeppe/go-internal v1.16.0
golang.org/x/sync v0.17.0
golang.org/x/text v0.29.0

앞의 셋은 pgx 가 끌고 오고, kr/text · rogpeppe/go-internal 은 테스트
경로에서 온다.

외부 런타임 의존

무엇 버전 필수인가
PostgreSQL 17 Mediator 에 필수. 테스트는 scripts/testdb.sh 도커 또는 CI 서비스 컨테이너
claude CLI — 노드에서 선택적. 없으면 광고에서 하네스 속성이 빠질 뿐 노드는 뜬다
git — 워크스페이스 diff 에 쓰인다. 없으면 해당 테스트가 t.Skip
sh — 명령 단계 실행에 쓰인다. 없으면 해당 테스트가 t.Skip

하네스가 선택적이라는 점이 중요하다 — internal/enode/claude.go 의 Probe 가
없으면 그냥 광고 목록에서 빠진다. 노드가 죽지 않는다.

빌드와 패키징

크로스 컴파일

CI 의 cross 잡이 매 커밋 검증한다.

   GOOS=windows GOARCH=amd64        go build ./...
   GOOS=linux   GOARCH=arm GOARM=7  go build ./...   (Raspberry Pi 2)
   GOOS=darwin  GOARCH=arm64        go build ./...

ci.yml 주석이 왜 이것을 CI 에 두었는지 적는다.

ADR-015 가 Go 를 고른 핵심 이유를 검증한다. "리눅스 CI 에서 GOOS=windows 로
exe 가 나온다" 가 깨지면 윈도우 enode 배포 계획이 통째로 무너진다.

설치 패키지

대상 도구 파일
Linux deb · rpm nfpm packaging/linux/nfpm.yaml.in · nfpm-mediator.yaml.in
Windows msi wixl (리눅스에서 굽는다) packaging/windows/enode.wxs · enode-mediator.wxs
macOS 셸 스크립트 packaging/macos/build.sh
공통 packaging/build-installers.sh

설정 파일 목록

   go.mod  go.sum
   .github/workflows/ci.yml  package.yml  release.yml
   packaging/linux/nfpm.yaml.in  nfpm-mediator.yaml.in
   packaging/windows/enode.wxs  enode-mediator.wxs
   packaging/macos/build.sh  packaging/build-installers.sh
   internal/store/schema.sql        (//go:embed 로 바이너리에 들어간다)
   scripts/testdb.sh                (테스트용 Postgres 도커)

버전 고정 방식

  • Go 버전: go.mod 한 곳. CI 가 go-version-file 로 읽는다
  • 의존 버전: go.sum 이 해시로 고정
  • 제품 버전: internal/build 가 링커 플래그로 받거나 Go VCS 스탬프에서
    읽는다. 다섯 실행파일이 같은 패키지를 공유하므로 버전 문자열이 한 곳에만 있다
  • PostgreSQL 버전: ci.yml 의 image: postgres:17 과
    scripts/testdb.sh 두 곳