콘텐츠로 이동

아키텍처 리팩토링 가이드

이 장은 v1.0 이후 수행된 아키텍처 리팩토링으로 생성된 신규 파일을 설명합니다.

대형 파일을 책임별로 분리하여 유지보수성과 증분 빌드 속도를 개선했습니다.

리팩토링 전: 리팩토링 후:
rest_server.c (3,942 LOC) → rest_server.c (3,100 LOC)
+ rest_middleware.c (287 LOC)
+ rest_middleware.h (75 LOC)
purecvisorctl.c (6,996 LOC) → purecvisorctl.c (6,700 LOC)
+ cli_rpc.c (190 LOC)
+ cli_rpc.h (65 LOC)
+ cli_output.c (280 LOC)
+ cli_output.h (34 LOC)

21.2 REST 미들웨어 (src/api/rest_middleware.c)

섹션 제목: “21.2 REST 미들웨어 (src/api/rest_middleware.c)”

HTTP 요청 처리 파이프라인에서 **횡단 관심사(cross-cutting concerns)**를 분리한 모듈입니다.

HTTP 요청 도착
[rest_server.c] 요청 수신 + 라우팅
[rest_middleware.c] ETag / Rate Limit / 타임아웃 / 검증
[dispatcher.c] RPC 핸들러 호출
함수역할사용 예시
pcv_compute_etag(body, len)응답 본문의 MD5 ETag 생성GET 응답 캐싱 (304 Not Modified)
pcv_validate_required(params, keys)필수 파라미터 검증RPC 파라미터 체크
pcv_get_endpoint_rate_limit(path)엔드포인트별 Rate Limit 티어/auth/* 60, /metrics 3600
pcv_get_rpc_timeout(method)RPC 메서드별 타임아웃vm.create 30초, vm.list 8초
pcv_rest_error(msg, code, status, body)REST 에러 응답 생성인증 실패, 파라미터 오류
constexpr int 기본 = 600; // req/min (일반 API)
constexpr int 인증 = 60; // req/min (브루트포스 방지)
constexpr int 모니터링 = 3600; // req/min (에이전트 폴링)
constexpr int VM생성 = 120; // req/min (리소스 보호)

CLI(pcvctl)에서 데몬과 통신하는 UDS JSON-RPC 클라이언트입니다.

pcvctl vm list
cli_rpc.c: purectl_send_request("vm.list", params)
UDS 소켓: /var/run/purecvisor/daemon.sock
dispatcher.c → handler_vm_lifecycle.c → vm_manager.c
typedef struct {
gchar *sock_path; // UDS 소켓 경로
gboolean color; // 터미널 색상 출력 여부 (isatty 검사)
gboolean json_mode; // --json 플래그
gboolean csv_mode; // --csv 플래그
} PcvCtx;
// 글로벌: 모든 CLI 커맨드에서 공유
extern PcvCtx g_ctx;
// cc()/ce(): 터미널이 아니면 (파이프 출력) 색상 코드를 비활성화
printf("%sVM 시작됨%s\n", cc(GREEN), ce()); // 터미널: 초록색 / 파이프: 무색

21.4 CLI 출력 포맷터 (src/cli/cli_output.c)

섹션 제목: “21.4 CLI 출력 포맷터 (src/cli/cli_output.c)”

CLI의 구조화된 출력 시스템입니다.

// 사용 예시: VM 목록 테이블 출력
PcvTable *t = ptbl_new(4, "NAME", "STATE", "CPU", "MEM");
ptbl_row(t, "web-prod", "running", "2.5%", "1.2G");
ptbl_row(t, "db-prod", "stopped", "-", "4.0G");
if (g_ctx.csv_mode)
ptbl_print_csv(t); // NAME,STATE,CPU,MEM\nweb-prod,running,...
else
ptbl_print_plain(t); // 정렬된 컬럼 출력
ptbl_free(t);
모드플래그형식
테이블(기본)정렬된 컬럼 + 색상
JSON--jsonraw JSON 응답
CSV--csvRFC 4180 CSV
Plain파이프 시색상 없는 테이블

21.5 디스패처 핸들러 시그니처 (src/api/dispatcher.c)

섹션 제목: “21.5 디스패처 핸들러 시그니처 (src/api/dispatcher.c)”

RPC 핸들러는 모두 같은 시그니처를 가지며, g_rpc_routes 해시테이블이 메서드 이름("vm.clone" 등)을 그 함수 포인터로 매핑합니다.

정의 위치는 한 곳이 아닙니다src/api/dispatcher.c 안에 static 으로 있는 것과, src/modules/dispatcher/handler_*.c(일부는 src/modules/network/network_manager.c)로 분리돼 외부 링크를 갖는 것이 섞여 있으며 후자가 더 많습니다.
한 곳에 모여 있는 것은 정의가 아니라 등록입니다 — dispatcher_init_routes()g_rpc_routes 삽입 목록이 “어떤 메서드가 존재하는가”의 진리원이고, 계약 게이트들도 그 표를 읽습니다.

// 핸들러 함수 시그니처 (모든 RPC 핸들러의 공통 패턴)
typedef void (*PcvDispatchHandler)(
JsonObject *params, // RPC 파라미터
const gchar *rpc_id, // 요청 ID (응답 매칭용)
UdsServer *server, // UDS 서버 인스턴스
GSocketConnection *connection // 클라이언트 연결
);

21.6 커밋 메시지 Hook (scripts/commit-msg)

섹션 제목: “21.6 커밋 메시지 Hook (scripts/commit-msg)”

Conventional Commits 포맷을 강제하는 Git hook입니다.

허용 접두사: feat | fix | refactor | perf | docs | chore | test | ci | style
형식:
<type>: <description>
<type>(scope): <description>
예시:
feat: VM 스냅샷 목록 필터 추가
fix(rest_server): rate limiter 1024 IP 우회 수정
refactor: C11 → C23 전환
docs: CHANGELOG.md v1.0 업데이트

21.7 감사 후속의 결과·자원 수명 계약

섹션 제목: “21.7 감사 후속의 결과·자원 수명 계약”

최근 개발선 감사는 기존 단일 프로세스·GMainLoop·GTask 구조 안에서 결과와 자원의 소유권을 재검토합니다.
새로운 프로세스 구조나 프레임워크 도입을 완료한 것으로 해석하지 않습니다.

검토 영역확인해야 할 계약현재 상태
Job 결과accepted 응답·Job ID·영속 row·실제 작업 결과가 일치하고 SQL 실패와 ID 충돌을 식별해야 함시정·독립 검증 잔여
Trace 자식 프로세스stop 요청, 실제 wait 회수, 실행 guard 해제가 순서대로 확인돼야 함실제 도구·환경 검증 잔여
비동기 I/O실패 반환한 제출의 후속 실행 방지, pending 접근 동기화, 미전달 결과 FD와 ring 소유권 정리지정 경로의 발견을 후속 처리 중
UI 요청과 창대상 VM 식별과 요청 순번, 원래 창의 완료·timer 수명이 일치해야 함개발선 지정 시정·독립 리뷰·UI 배포 확인 완료
모니터링 표시누적 counter, 실제 경과 시간과 차트 단위·시간축이 일치해야 함시정·독립 검증 잔여

본문 읽기·격리 시험·실환경 확인·독립 리뷰는 서로 다른 증거입니다.
지정 경로의 통과를 해당 모듈 전체나 공개 릴리스의 완료로 확대하지 않습니다.