Skip to main content
BoundaryλŠ” HMR μ‹œμŠ€ν…œμ΄ λͺ¨λ“ˆμ„ μ•ˆμ „ν•˜κ²Œ ꡐ체할 수 μžˆλŠ” 경계λ₯Ό μ •μ˜ν•©λ‹ˆλ‹€. Sonamu둜 κ°œλ°œν•  λ•Œ Boundaryλ₯Ό μ œλŒ€λ‘œ μ΄ν•΄ν•˜λ©΄ HMR을 μ΅œλŒ€ν•œ ν™œμš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Boundaryλž€?

BoundaryλŠ” β€œμž¬λ‘œλ“œ κ°€λŠ₯ν•œ 경계”λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. HMR μ‹œμŠ€ν…œμ€ λ‹€μŒκ³Ό 같은 κ·œμΉ™μœΌλ‘œ λ™μž‘ν•©λ‹ˆλ‹€:
  • Boundary 파일: λ³€κ²½ μ‹œ λ‹€μ‹œ λ‘œλ“œλ  수 μžˆλŠ” 파일 (Model, API, Entity λ“±)
  • Non-boundary 파일: λ³€κ²½ μ‹œ 전체 μ„œλ²„ μž¬μ‹œμž‘μ΄ ν•„μš”ν•œ 파일 (μ„€μ •, ν™˜κ²½λ³€μˆ˜ λ“±)
βœ… Boundary 파일: μˆ˜μ • μ‹œ HMR둜 μ¦‰μ‹œ 반영 ❌ Non-boundary 파일: μˆ˜μ • μ‹œ μ„œλ²„ μž¬μ‹œμž‘ ν•„μš”

μ™œ Boundaryκ°€ ν•„μš”ν•œκ°€?

정적 importλŠ” Node.js μ‹œμž‘ μ‹œ ν•œ 번만 μ‹€ν–‰λ˜λ―€λ‘œ λŸ°νƒ€μž„μ— ꡐ체할 수 μ—†μŠ΅λ‹ˆλ‹€:
Boundary둜 μ§€μ •λœ νŒŒμΌμ€ λ°˜λ“œμ‹œ λ™μ μœΌλ‘œ importλ˜μ–΄μ•Ό ν•˜λ©°, κ·Έλž˜μ•Όλ§Œ λ³€κ²½ μ‹œ μ΅œμ‹  μ½”λ“œλ₯Ό κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

Sonamu의 Boundary μ„€μ •

SonamuλŠ” 기본적으둜 ν”„λ‘œμ νŠΈμ˜ λͺ¨λ“  TypeScript νŒŒμΌμ„ Boundary둜 μ„€μ •ν•©λ‹ˆλ‹€:
이 μ„€μ •μœΌλ‘œ 인해 src/ μ•„λž˜μ˜ λͺ¨λ“  νŒŒμΌμ€ HMR이 κ°€λŠ₯ν•˜λ©°, λ³€κ²½ μ‹œ μžλ™μœΌλ‘œ μž¬λ‘œλ“œλ©λ‹ˆλ‹€.

Boundary 파일 μ˜ˆμ‹œ

Boundary νŒŒμΌλ“€ (HMR κ°€λŠ₯):
  • user.model.ts - Model 파일
  • user.api.ts - API 파일
  • user.entity.ts - Entity μ •μ˜
  • helpers.ts - μœ ν‹Έλ¦¬ν‹° ν•¨μˆ˜
  • constants.ts - μƒμˆ˜ μ •μ˜
Non-boundary νŒŒμΌλ“€ (μž¬μ‹œμž‘ ν•„μš”):
  • sonamu.config.ts - Sonamu μ„€μ •
  • .env - ν™˜κ²½λ³€μˆ˜
  • package.json - μ˜μ‘΄μ„±

Boundary κ·œμΉ™

1. 동적 Import ν•„μˆ˜

Boundary νŒŒμΌμ€ λ°˜λ“œμ‹œ λ™μ μœΌλ‘œ importλ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€. ❌ 잘λͺ»λœ 예: 정적 import
βœ… μ˜¬λ°”λ₯Έ 예: 동적 import

SonamuλŠ” μžλ™μœΌλ‘œ μ²˜λ¦¬ν•©λ‹ˆλ‹€

λ‹€ν–‰νžˆ Sonamu의 SyncerλŠ” Entity 기반 νŒŒμΌλ“€μ„ μžλ™μœΌλ‘œ 동적 importν•©λ‹ˆλ‹€:
즉, 일반적인 Sonamu κ°œλ°œμ—μ„œλŠ” μ‹ κ²½ μ“Έ ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€!

2. Boundary κ°„ 정적 Import ν—ˆμš©

Boundary νŒŒμΌλΌλ¦¬λŠ” 정적 importκ°€ κ°€λŠ₯ν•©λ‹ˆλ‹€ (Sonamu의 κ°œμ„ μ‚¬ν•­):
이것이 κ°€λŠ₯ν•œ 이유:
  • 두 파일 λͺ¨λ‘ Boundaryμ΄λ―€λ‘œ
  • λ‘˜ λ‹€ Syncer에 μ˜ν•΄ λ™μ μœΌλ‘œ λ‘œλ“œλ¨
  • μ„œλ‘œ 참쑰해도 HMR이 정상 μž‘λ™ν•¨

3. Non-boundary의 Boundary Import μ œν•œ

Non-boundary 파일이 Boundaryλ₯Ό 정적 importν•˜λ©΄ HMR이 μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€:

μ‹€μ „ μ‹œλ‚˜λ¦¬μ˜€

User-Post κ΄€κ³„μ—μ„œ HMR ν™œμš©ν•˜κΈ°

상황: User Entity의 role ν•„λ“œλ₯Ό μΆ”κ°€ν•˜κ³ , Post APIμ—μ„œ μž‘μ„±μž κΆŒν•œ 체크λ₯Ό μΆ”κ°€ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 1단계: Entity μˆ˜μ •
μ €μž₯ν•˜λ©΄ HMR이 μžλ™μœΌλ‘œ:
  • user.entity.ts μ—…λ°μ΄νŠΈ
  • user.types.ts μž¬μƒμ„±
  • UserModel μž¬λ‘œλ“œ
μ½˜μ†” 좜λ ₯:
2단계: Model 둜직 μΆ”κ°€
μ €μž₯ν•˜λ©΄ HMR이:
  • UserModel μž¬λ‘œλ“œ
  • UserModel을 μ‚¬μš©ν•˜λŠ” λͺ¨λ“  API μž¬λ‘œλ“œ
3단계: API에 κΆŒν•œ 체크 μΆ”κ°€
μ €μž₯ν•˜λ©΄ HMR이:
  • PostApi.create μž¬λ“±λ‘
  • μ„œλ²„ μž¬μ‹œμž‘ 없이 λ°”λ‘œ ν…ŒμŠ€νŠΈ κ°€λŠ₯!

전톡적 방식이라면:
  1. Entity μˆ˜μ •
  2. Types 파일 μˆ˜λ™ 생성
  3. Model 파일 μˆ˜μ •
  4. μ„œλ²„ μž¬μ‹œμž‘ (30초)
  5. API 파일 μˆ˜μ •
  6. μ„œλ²„ μž¬μ‹œμž‘ (30초)
  7. ν…ŒμŠ€νŠΈ
Sonamu + HMR:
  1. Entity μˆ˜μ • (μžλ™ 생성)
  2. Model 파일 μˆ˜μ • (μžλ™ μž¬λ‘œλ“œ)
  3. API 파일 μˆ˜μ • (μžλ™ μž¬λ‘œλ“œ)
  4. ν…ŒμŠ€νŠΈ βœ…
3번의 μž¬μ‹œμž‘(90초)이 0번으둜!

λ³΅μž‘ν•œ λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 개발

상황: μ£Όλ¬Έ 생성 μ‹œ 재고 확인, 결제 처리, μ•Œλ¦Ό λ°œμ†‘μ„ κ΅¬ν˜„ν•©λ‹ˆλ‹€. 파일 ꡬ쑰:
1단계: 재고 체크 둜직
μ €μž₯ β†’ 2초 ν›„ β†’ μ¦‰μ‹œ 반영 βœ… 2단계: μ£Όλ¬Έ 생성 둜직
μ €μž₯ β†’ ProductModel μ˜μ‘΄μ„±λ„ μžλ™ μž¬λ‘œλ“œ βœ… 3단계: API μ—”λ“œν¬μΈνŠΈ
μ €μž₯ β†’ API μž¬λ“±λ‘ β†’ μ¦‰μ‹œ Postmanμ—μ„œ ν…ŒμŠ€νŠΈ! HMR 둜그:

import.meta.hot API

Boundary νŒŒμΌμ—μ„œλŠ” import.meta.hot APIλ₯Ό μ‚¬μš©ν•˜μ—¬ HMR λ™μž‘μ„ μ„Έλ°€ν•˜κ²Œ μ œμ–΄ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

dispose() - λ¦¬μ†ŒμŠ€ 정리

λͺ¨λ“ˆμ΄ μž¬λ‘œλ“œλ˜κΈ° 전에 정리 μž‘μ—…μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€:
λ¦¬μ†ŒμŠ€ 정리가 ν•„μš”ν•œ 경우:
  • 타이머/μΈν„°λ²Œ 정리
  • 이벀트 λ¦¬μŠ€λ„ˆ 제거
  • WebSocket μ—°κ²° μ’…λ£Œ
  • λ°μ΄ν„°λ² μ΄μŠ€ 컀λ„₯μ…˜ ν’€ 정리
  • 파일 ν•Έλ“€ λ‹«κΈ°
μ‹€μ œ μ‚¬μš© μ˜ˆμ‹œ:

decline() - 전체 μž¬μ‹œμž‘ μš”κ΅¬

νŠΉμ • λͺ¨λ“ˆμ„ HMRμ—μ„œ μ œμ™Έν•˜κ³  전체 μž¬μ‹œμž‘μ„ μš”κ΅¬ν•©λ‹ˆλ‹€:
decline()을 μ‚¬μš©ν•΄μ•Ό ν•˜λŠ” 경우:
  • μ „μ—­ μ„€μ • 파일
  • λ°μ΄ν„°λ² μ΄μŠ€ μ—°κ²° μ„€μ •
  • μ΄ˆκΈ°ν™”κ°€ λ³΅μž‘ν•œ 싱글톀
  • μƒνƒœ 관리가 κΉŒλ‹€λ‘œμš΄ λͺ¨λ“ˆ
μ‹€μ œ μ‚¬μš© μ˜ˆμ‹œ:

boundary 객체 - μƒνƒœ 곡유

Boundary κ°„ 데이터λ₯Ό κ³΅μœ ν•˜μ—¬ μž¬λ‘œλ“œ 후에도 μƒνƒœλ₯Ό μœ μ§€ν•©λ‹ˆλ‹€:
μ‹€μ œ μ‚¬μš© μ˜ˆμ‹œ:
boundary κ°μ²΄λŠ” HMR 사이클 κ°„ 데이터λ₯Ό μœ μ§€ν•˜μ§€λ§Œ, μ„œλ²„ μž¬μ‹œμž‘ μ‹œμ—λŠ” μ΄ˆκΈ°ν™”λ©λ‹ˆλ‹€. 영ꡬ μ €μž₯이 ν•„μš”ν•œ λ°μ΄ν„°λŠ” λ°μ΄ν„°λ² μ΄μŠ€λ‚˜ Redisλ₯Ό μ‚¬μš©ν•˜μ„Έμš”.

νƒ€μž… μ •μ˜

TypeScriptμ—μ„œ import.meta.hot을 μ‚¬μš©ν•˜λ €λ©΄ νƒ€μž… μ •μ˜κ°€ ν•„μš”ν•©λ‹ˆλ‹€:
Sonamu ν”„λ‘œμ νŠΈμ—λŠ” 이미 νƒ€μž… μ •μ˜κ°€ ν¬ν•¨λ˜μ–΄ μžˆμœΌλ―€λ‘œ 별도 섀정이 ν•„μš” μ—†μŠ΅λ‹ˆλ‹€.

디버깅

Boundary μ„€μ • 확인

νŠΉμ • 파일이 Boundary둜 μ„€μ •λ˜μ–΄ μžˆλŠ”μ§€ 확인:
좜λ ₯ μ˜ˆμ‹œ:

μ˜μ‘΄μ„± 트리 μ‹œκ°ν™”

좜λ ₯:
개발 쀑 HMR이 μž‘λ™ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄: 1. ν•΄λ‹Ή 파일이 Boundary둜 μ§€μ •λ˜μ–΄ μžˆλŠ”μ§€ 확인 2. λ™μ μœΌλ‘œ importλ˜λŠ”μ§€ 확인 3. μˆœν™˜ μ˜μ‘΄μ„±μ΄ μ—†λŠ”μ§€ 확인

μ„±λŠ₯ μ΅œμ ν™”

λΆˆν•„μš”ν•œ Boundary μ œμ™Έ

λͺ¨λ“  νŒŒμΌμ„ Boundary둜 μ„€μ •ν•˜λ©΄ μ˜μ‘΄μ„± νŠΈλ¦¬κ°€ μ»€μ Έμ„œ 느렀질 수 μžˆμŠ΅λ‹ˆλ‹€:

μ˜μ‘΄μ„± μ΅œμ†Œν™”

Model κ°„ μˆœν™˜ μ°Έμ‘°λ₯Ό ν”Όν•˜κ³ , ν•„μš”ν•œ κ²ƒλ§Œ import:

μš”μ•½

Sonamu의 Boundary μ‹œμŠ€ν…œ: βœ… μžλ™ 처리: Syncerκ°€ Entity 기반 νŒŒμΌμ„ μžλ™μœΌλ‘œ 동적 import
βœ… Boundary κ°„ μ°Έμ‘° κ°€λŠ₯: Model끼리 정적 import ν—ˆμš©
βœ… μ„Έλ°€ν•œ μ œμ–΄: import.meta.hot API둜 λ¦¬μ†ŒμŠ€ 정리, μƒνƒœ μœ μ§€
βœ… 디버깅 도ꡬ: hot.dump()둜 μ˜μ‘΄μ„± 트리 확인
λŒ€λΆ€λΆ„μ˜ 경우 Boundaryλ₯Ό μ‹ κ²½ μ“Έ ν•„μš” 없이 Sonamuκ°€ μžλ™μœΌλ‘œ μ²˜λ¦¬ν•©λ‹ˆλ‹€!