3. 프로젝트 아키텍처 및 디렉토리 역할
최상위 디렉토리 구조
계층별 책임 분리
src/common/ — 공유 키트 (내부 전용, 별도 배포 없음)
별도 패키지가 아니라 같은 소스 트리의 모듈입니다. tsup이 noExternal로 전부 인라인하므로 빌드 결과물 안에만 존재합니다.
agent/는 의도적으로index.ts에서 재노출하지 않습니다. 빌드가noExternal로 모든 의존성을 인라인하기 때문에, 재노출하면 langchain·deepagents가 배포되는 MCP 서버 번들에 끌려 들어갑니다. 쓰는 쪽에서@/common/agent경로로 직접 가져오며,dist/에는 포함되지 않습니다.이렇게 해서 계층이 한 방향으로 유지됩니다. 에이전트를 조립하는 곳은
src/common/agent하나뿐이고, 나머지 소스는 MCP 도구만 제공합니다. 도구를 LLM으로 검증하고 싶으면 테스트에서@/common/agent에 MCP 서버와 프롬프트를 넘겨 실행합니다 (src/agent.test.ts참고).
src/tools/ — MCP 도구 정의
src/exchange/ — 환율 스크레이핑 도메인
Playwright로 네이버·구글·다음을 직접 열어 환율을 읽어옵니다. playwright는 실행 시점에 브라우저 드라이버를 자기 패키지 경로에서 찾으므로 번들하지 않고 dependencies로 남겨 둡니다 (tsup.config.ts에서 external 처리).
src/tmdb/ — TMDB 영화 조회 도메인
TMDB v3 REST API를 fetch로 호출합니다. 브라우저도 추가 의존성도 쓰지 않으므로 나머지 소스와 똑같이 번들에 인라인됩니다.
인증은 환경 변수에서 읽습니다. TMDB_API_KEY(v3 API 키)는 쿼리 문자열로, TMDB_ACCESS_TOKEN(읽기 액세스 토큰)은 Bearer 헤더로 보냅니다. 둘 다 있으면 토큰을 써서 비밀값이 URL에 남지 않게 합니다.
src/system/ — 기계 상태 도메인
서버가 돌고 있는 기계를 systeminformation으로 읽습니다. 네트워크도 자격 증명도 브라우저도 쓰지 않지만, 이 패키지는 플랫폼 명령(ioreg, vm_stat, df 등)을 실행하므로 읽기마다 제한 시간을 걸어 둡니다.
이 도메인의 결정 세 가지는 원본 수치가 질문과 다른 답을 주기 때문에 있습니다.
- CPU 부하는 표본을 두 번 뜹니다.
currentLoad()는 앞선 호출과의 차이를 돌려주므로 프로세스의 첫 호출은 부팅 이후 평균입니다.readCpu()는 한 번 눌러 기준점을 잡고sampleMs(최소 200ms — 그보다 짧으면systeminformation이 캐시된 값을 돌려줍니다)를 기다린 뒤 다시 읽습니다. - 메모리는
used가 아니라active를 셉니다. macOS·Linux의used는 캐시와 버퍼를 포함해 한가한 기계도 90%대로 만듭니다. 회수 가능한 몫은cachedBytes로 따로 담습니다. - 디스크는 전부가 아니라 하나를 고릅니다. macOS는 APFS 컨테이너 하나를 여러 볼륨으로 쪼개고
/에 읽기 전용 시스템 스냅샷을 올려 사용률이 3% 남짓으로 나옵니다.pickPrimaryDisk()는 darwin에서/System/Volumes/Data, Windows에서 작업 디렉터리가 놓인 드라이브, 그 밖에서는/를 고릅니다.allDisks를 주면 마운트된 것을 모두 돌려줍니다.
readSnapshot()은 요청한 항목을 동시에 읽으므로 네 항목을 다 물어도 CPU 하나를 물을 때와 비용이 비슷합니다. 실패한 항목은 null이 되고 이유가 errors에 담기는데, 이것이 "배터리를 읽지 못했다"와 "배터리가 없는 기계다"를 가릅니다.
docs/ + rspress.config.ts — Rspress 문서 사이트
readme-docs-plugin이 손으로 쓴 루트 README.md를 /api(및 /ko/api) 라우트에 렌더링합니다.
전체 데이터 흐름
tsconfig path alias: @/* → ./src/* (루트 tsconfig.json, rstest.config.ts가 동일 별칭을 미러링)
아키텍처 다이어그램
모듈 및 의존 구조
src/common은 별도 패키지로 배포되지 않고 빌드 시 번들에 인라인됩니다.
소스 내부 구조
하나의 tools 정의가 세 가지로 소비됩니다: MCP 서버(stdio), CLI 실행기, 라이브러리 진입점. 문서는 네 번째 소비처이고 손으로 씁니다.
빌드 흐름
릴리스 파이프라인 (.github/workflows/release.yml)
관심사 분리 원칙
- 도구 정의는
src/tools/에서 담당 — MCP에 노출할 인터페이스는 여기에만 위치 - 도메인 로직은
src/exchange/,src/tmdb/,src/system/에서 담당 — 스크레이핑·파싱·타임아웃 처리 - MCP 서버/CLI 공통 로직은
src/common/kit/에서 담당 — 서버 생성, CLI 파싱, 에러 처리 등 src/server.ts는 도구 객체를createMcpServer()에 전달하는 역할만 수행 (매우 얇은 레이어)src/cli.ts는 도구 객체를runCli()에 전달하는 역할만 수행 (매우 얇은 레이어)
신규 기능 추가 위치
- 새 도구 추가:
src/tools/하위에 파일 추가 (또는 기존 파일에 추가) 후src/tools/index.ts에 집계 - 새 포털/통화 추가:
src/exchange/providers/에 스크레이퍼 추가,src/exchange/types.ts에 상수 추가 - 새 TMDB 엔드포인트 추가:
src/tmdb/movies.ts에 호출 추가,src/tmdb/types.ts에 응답 타입 추가 - 새 기계 상태 항목 추가:
src/system/types.ts의SECTIONS에 항목 이름,src/system/normalize.ts에 정리 함수,src/system/collect.ts에 읽기 함수 추가 - 공통 기능 추가:
src/common/kit/에 모듈 추가 - 빌드 설정 변경: 루트
tsup.config.ts수정