메인 콘텐츠로 건너뛰기
Syncer는 Sonamu의 자동 생성 시스템입니다. 파일 변경을 감지하고, 필요한 코드를 자동으로 생성하며, 타겟 프로젝트(web, app 등)에 동기화합니다.

Syncer란?

파일 변경 감지

Entity, Model, Types 파일 변경 추적Checksum 기반 효율적 감지

자동 코드 생성

타입, 스키마, API 클라이언트 생성Template 기반 생성

HMR 지원

개발 중 실시간 반영파일 무효화 및 재로드

멀티 타겟 동기화

web, app 등 여러 프로젝트 동기화자동 파일 복사

Syncer의 동작 흐름

감시 대상 파일

Syncer가 변경을 추적하는 파일 패턴입니다:
파일 타입패턴용도
Entitysrc/application/**/*.entity.json데이터 구조 정의
Typessrc/application/**/*.types.ts타입 정의
Modelsrc/application/**/*.model.ts비즈니스 로직
Framesrc/application/**/*.frame.ts프레임 로직
Functionssrc/application/**/*.functions.ts유틸 함수
Generatedsrc/application/sonamu.generated.ts생성된 베이스 파일
Configsrc/sonamu.config.tsSonamu 설정
Workflowsrc/application/**/*.workflow.ts워크플로우 정의
i18nsrc/i18n/**/*.ts다국어 파일
파일 패턴: file-patterns.ts에서 관리되며, checksum으로 변경 감지

수동 동기화

개발 서버 없이 수동으로 동기화할 수 있습니다.
# 전체 동기화
pnpm sonamu sync

# 변경된 파일만 동기화
pnpm sonamu sync --check
실행 결과:
🔄 Syncing files...
✅ Generated: sonamu.generated.ts
✅ Generated: sonamu.generated.sso.ts
✅ Copied: web/src/services/user/user.types.ts
✅ Copied: web/src/services/sonamu.generated.ts
✅ Generated: services.generated.ts
✅ Generated: sonamu.generated.http
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  All files are synced!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

자동 동기화 (HMR)

개발 서버 실행 중에는 파일 변경이 자동으로 감지되고 동기화됩니다.
# 개발 서버 시작
pnpm dev

# 파일 변경하면 자동 동기화
# - user.entity.json 변경 → 타입 재생성
# - user.model.ts 변경 → API 클라이언트 재생성
HMR 로그 예시:
🔄 Invalidated:
- src/application/user/user.model.ts (with 5 APIs)
- src/application/user/user.types.ts

✅ Generated: sonamu.generated.sso.ts
✅ Copied: web/src/services/user/user.types.ts
✅ Generated: services.generated.ts

✨ HMR completed in 234ms

Syncer 이벤트

Syncer는 EventEmitter로 이벤트를 발생시킵니다.
import { Sonamu } from "sonamu";

// HMR 완료 이벤트 구독
Sonamu.syncer.eventEmitter.on("onHMRCompleted", () => {
  console.log("✅ HMR completed!");
  // 추가 작업 수행...
});
이벤트 종류:
이벤트발생 시점사용 예시
onHMRCompletedHMR 완료 시후속 작업 트리거

Syncer 액션

파일 변경 유형에 따라 다른 액션이 실행됩니다.

1. Entity 변경 (handleEntityChange)

Entity 파일이 변경되면 스키마를 재생성합니다. 트리거: *.entity.json 파일 변경 액션:
  1. EntityManager 재로드
  2. 새 Entity면 *.types.ts 생성
  3. 스키마 파일 생성:
    • sonamu.generated.ts
    • sonamu.generated.sso.ts
  4. 타겟에 파일 복사
// Syncer 내부 로직
async handleEntityChange(diffGroups, diffTypes) {
  await EntityManager.reload();
  
  // 새 Entity 타입 파일 생성
  if (entity.parentId === undefined && !(await exists(typeFilePath))) {
    await generateTemplate("init_types", { entityId });
  }
  
  // 스키마 생성
  await this.actionGenerateSchemas();
}

2. Types/Functions/Generated 변경

타입 파일이 변경되면 타겟에 복사합니다. 트리거: *.types.ts, *.functions.ts, *.generated.ts 변경 액션:
  1. 변경된 파일 목록 수집
  2. 각 타겟(web, app)에 복사
  3. sonamu import를 ./sonamu.shared로 변경
// 복사 시 import 변경
// Before (api)
import { BaseModelClass } from "sonamu";

// After (web/app)
import { BaseModelClass } from "./sonamu.shared";
sonamu.shared.ts: web/app에는 sonamu 패키지가 없으므로, 공통 유틸리티를 shared 파일로 제공합니다.

3. Model/Frame 변경

Model 파일이 변경되면 API 클라이언트를 재생성합니다. 트리거: *.model.ts, *.frame.ts 변경 액션:
  1. Model, Types, APIs 재로드
  2. API 클라이언트 생성 (services.generated.ts)
  3. HTTP 테스트 파일 생성 (sonamu.generated.http)
  4. SSR 파일 재생성 (queries.generated.ts, entry-server.generated.tsx)
async handleModelOrFrameChange(diffGroups) {
  // 모듈 재로드
  await this.autoloadModels();
  await this.autoloadTypes();
  await this.autoloadApis();
  
  // 서비스 생성
  await this.actionGenerateServices(params);
  await this.actionGenerateHttps();
  
  // SSR 파일 재생성
  await generateTemplate("queries", {}, { overwrite: true });
  await generateTemplate("entry_server", {}, { overwrite: true });
}

4. Config 변경

설정 파일이 변경되면 환경 변수를 동기화합니다. 트리거: sonamu.config.ts 변경 액션:
  1. .sonamu.env 파일 생성/업데이트
  2. 각 타겟에 복사
web/.sonamu.env
API_HOST=localhost
API_PORT=3000

5. Workflow 변경

워크플로우 파일이 변경되면 재로드합니다. 트리거: *.workflow.ts 변경 액션: 워크플로우 재로드 및 동기화

6. i18n 변경

다국어 파일이 변경되면 SD 파일을 재생성합니다. 트리거: src/i18n/**/*.ts 변경 액션:
  1. Locale 파일을 타겟에 복사
  2. sd.generated.ts 생성 (api, web, app)

Checksum 기반 변경 감지

Syncer는 파일의 checksum을 저장하여 효율적으로 변경을 감지합니다.
// .sonamu-checksums.json
{
  "src/application/user/user.entity.json": "a7f4b3e2c1d5...",
  "src/application/user/user.types.ts": "c3d1e4f5a6b7...",
  "src/application/user/user.model.ts": "e5f6a7b8c9d0..."
}
작동 방식:
  1. 파일 내용의 SHA-256 해시 계산
  2. 저장된 checksum과 비교
  3. 다르면 변경으로 판단
  4. 동기화 후 checksum 갱신
장점:
  • 빠른 변경 감지 (파일 내용 비교 불필요)
  • 정확한 변경 추적 (timestamp 영향 없음)
  • 여러 파일 동시 변경 처리

Syncer API

Syncer는 프로그래밍 방식으로 사용할 수 있습니다.

수동 동기화

import { Sonamu } from "sonamu";

// 전체 동기화
await Sonamu.syncer.sync();

// 특정 파일 동기화
await Sonamu.syncer.syncFromWatcher(
  "change",
  "/path/to/user.entity.json"
);

템플릿 생성

// Entity 생성
await Sonamu.syncer.createEntity({
  entityId: "User",
  table: "users",
  props: [
    { name: "id", type: "integer" },
    { name: "email", type: "string" },
  ],
  subsets: {
    A: ["id", "email"],
  },
  enums: {},
  indexes: [],
});

// 템플릿 생성
await Sonamu.syncer.generateTemplate(
  "model",
  { entityId: "User" },
  { overwrite: false }
);

// 커스텀 템플릿 렌더링
const files = await Sonamu.syncer.renderTemplate(
  "view_list",
  { entityId: "User" }
);

모듈 로드

// 타입 로드
await Sonamu.syncer.autoloadTypes();
console.log(Sonamu.syncer.types);

// Model 로드
await Sonamu.syncer.autoloadModels();
console.log(Sonamu.syncer.models);

// API 로드
await Sonamu.syncer.autoloadApis();
console.log(Sonamu.syncer.apis);

// Workflow 로드
await Sonamu.syncer.autoloadWorkflows();
console.log(Sonamu.syncer.workflows);

Syncer 설정

sonamu.config.ts에서 Syncer 동작을 설정할 수 있습니다.
api/src/sonamu.config.ts
export default {
  sync: {
    // 동기화 타겟 프로젝트
    targets: ["web", "app"],
  },
  
  // API 서버 설정 (환경 변수 생성에 사용)
  server: {
    baseUrl: "http://localhost:3000",
    listen: {
      host: "localhost",
      port: 3000,
    },
  },
};

개발 워크플로우

Syncer를 활용한 일반적인 개발 흐름입니다:
1

개발 서버 시작

pnpm dev
Syncer가 파일 변경을 감시합니다.
2

Entity 정의

Sonamu UI에서 Entity를 정의하거나 .entity.json 파일을 수정합니다.자동 실행:
  • *.types.ts 생성
  • sonamu.generated.ts 갱신
  • sonamu.generated.sso.ts 갱신
  • 타겟에 파일 복사
3

Model 작성

비즈니스 로직을 Model에 작성하고 @api 데코레이터를 추가합니다.자동 실행:
  • services.generated.ts 갱신
  • sonamu.generated.http 갱신
  • SSR 파일 갱신
4

프론트엔드 개발

생성된 API 클라이언트와 Types를 사용하여 UI를 개발합니다.
import { useUsers } from "@/services/services.generated";
import type { User } from "@/services/user/user.types";

function UserList() {
  const { data } = useUsers();
  // ...
}
5

실시간 반영

Model이나 Entity를 수정하면 HMR로 즉시 반영됩니다.브라우저 새로고침 없이 변경사항 확인 가능!

문제 해결

Syncer가 동작하지 않을 때

확인 사항:
  1. 개발 서버가 실행 중인지 확인
  2. 파일이 감시 대상 패턴에 포함되는지 확인
  3. Checksum 파일 삭제 후 재시도
rm .sonamu-checksums.json
pnpm sonamu sync
확인 사항:
  1. sonamu.config.tssync.targets 확인
  2. 타겟 디렉토리 존재 확인
  3. 타겟 디렉토리에 src/services/ 디렉토리 생성
mkdir -p web/src/services
mkdir -p app/src/services
최적화 방법:
  1. Node.js 최신 버전 사용 (v22+)
  2. SSD 사용 (HDD는 느림)
  3. 불필요한 파일 제외
  4. TypeScript 프로젝트 분리 (monorepo)
원인: sonamu import가 ./sonamu.shared로 변환되지 않음해결:
# 강제 재동기화
pnpm sonamu sync --force

다음 단계