λ””μžμΈ 토큰 쀑볡 μ—†μ• κΈ°

우리 νšŒμ‚¬λŠ” μ—¬λŸ¬ 개의 ν”„λ‘œμ νŠΈ λ ˆν¬μ§€ν† λ¦¬λ₯Ό μš΄μ˜ν•˜κ³  μžˆλŠ”λ°, λͺ¨λ°”일 μ•±, μ›Ή μ„œλΉ„μŠ€ λ“± 각각의 ν”„λ‘œμ νŠΈλ§ˆλ‹€ Tailwind config 파일이 μžˆμ—ˆκ³ , λͺ¨λ“  νŒŒμΌμ— λ™μΌν•œ λ””μžμΈ 토큰 값듀이 μ€‘λ³΅λ˜μ–΄ μžˆμ—ˆλ‹€. λ¬Έμ œλŠ” λ””μžμΈ 토큰이 변경될 λ•Œλ§ˆλ‹€ 각 레포의 tailwind.config.js에 ν•˜λ“œμ½”λ”©λœ 값을 일일이 μˆ˜μ •ν•΄μ•Ό ν–ˆλ‹€λŠ” μ μ΄μ—ˆλ‹€. μž…μ‚¬ ν›„ 처음 λ””μžμΈνŒ€κ³Ό μ§„ν–‰ν•œ νšŒμ˜μ—μ„œ μ—¬λŸ¬ 레포λ₯Ό 일일이 μˆ˜μ •ν•΄μ•Ό ν•˜λŠ” λΉ„νš¨μœ¨μ΄ λ…Όμ˜λ˜μ—ˆκ³ , 이λ₯Ό κ°œμ„ ν•΄λ³΄κ³ μž ν•˜μ˜€λ‹€.

ν•΄κ²°μ±…: λ””μžμΈ 토큰을 νŒ¨ν‚€μ§€λ‘œ λΆ„λ¦¬ν•˜κΈ°

μ€‘λ³΅λœ 토큰을 ν•œ κ³³μ—μ„œ 관리할 수 μžˆλŠ” ꡬ쑰λ₯Ό λ§Œλ“€κΈ° μœ„ν•΄ μ—¬λŸ¬ 고민을 ν–ˆμ—ˆλŠ”λ°, κ²°λ‘ μ μœΌλ‘œλŠ” npm νŒ¨ν‚€μ§€λ‘œ λΆ„λ¦¬ν•˜λŠ” 게 κ°€μž₯ λͺ…ν™•ν–ˆλ‹€. 마침 Tailwind v4둜 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜μ„ 마친 μƒνƒœμ˜€κ³ , @theme λ””λ ‰ν‹°λΈŒλ₯Ό 톡해 CSS λ³€μˆ˜ 기반으둜 토큰을 μ •μ˜ν•  수 μžˆμ—ˆλ‹€. 즉, tailwind.config.js λŒ€μ‹  순수 CSS 파일만으둜 토큰을 μ„ μ–Έν•˜κ³ , 각 ν”„λ‘œμ νŠΈμ—μ„œ @import ν•œ μ€„λ‘œ 곡톡 μŠ€νƒ€μΌμ„ κ°€μ Έμ˜¬ 수 있게 됐닀.
(Tailwind v4 λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ 과정은 λ³„도 κΈ€μ—μ„œ μ •λ¦¬ν–ˆλ‹€.)

νŒ¨ν‚€μ§€ μ €μž₯μ†Œ ꡬ쑰 작기

λ‚˜μ€‘μ— λ””μžμΈ μ‹œμŠ€ν…œ μ»΄ν¬λ„ŒνŠΈλ„ μ—¬λŸ¬ μ•±μ—μ„œ κ³΅ν†΅μœΌλ‘œ μ“Έ 수 μžˆλ„λ‘ ν™•μž₯ν•  κ³„νšμ΄ μžˆμ—ˆκΈ° λ•Œλ¬Έμ—, Yarn Workspace 기반의 λͺ¨λ…Έλ ˆν¬ ꡬ쑰둜 κ΅¬μ„±ν–ˆλ‹€.

company-packages/
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ themes/        # λ””μžμΈ 토큰 νŒ¨ν‚€μ§€
β”‚       β”œβ”€β”€ src/
β”‚       β”‚   β”œβ”€β”€ brands/
β”‚       β”‚   β”‚   β”œβ”€β”€ mobile/   # λͺ¨λ°”일 μ•±μš©
β”‚       β”‚   β”‚   └── web/      # μ›Ήμš©
β”‚       β”œβ”€β”€ package.json
β”‚       └── README.md
β”‚  
β”œβ”€β”€ scripts/
β”‚   β”œβ”€β”€ publish.js         # 배포 μžλ™ν™”
β”‚   β”œβ”€β”€ publish-all.js
β”‚   └── test-publish.js
└── package.json           # 루트 workspace μ„€μ •

λΈŒλžœλ“œλ³„ μ»€μŠ€ν„°λ§ˆμ΄μ§•

우리 μ„œλΉ„μŠ€λŠ” μ—¬λŸ¬ λΈŒλžœλ“œμ‚¬μ™€ 제휴λ₯Ό ν•˜κ³  μžˆμ–΄μ„œ, 같은 앱이라도 λΈŒλžœλ“œλ³„λ‘œ μƒ‰μƒμ΄λ‚˜ ν…Œλ§ˆλ₯Ό λ‹€λ₯΄κ²Œ λ³΄μ—¬μ€˜μ•Ό ν•˜λŠ” κ²½μš°κ°€ μžˆλ‹€. 이런 μš”κ΅¬μ‚¬ν•­μ„ μœ„ν•΄ 곡톡 λͺ¨λ°”일 토큰을 κ·ΈλŒ€λ‘œ μœ μ§€ν•˜λ©΄μ„œ, νŠΉμ • 제휴 λΈŒλžœλ“œλ§Œ CSS λ³€μˆ˜ λ ˆλ²¨μ—μ„œ 색상 토큰을 μ˜€λ²„λΌμ΄λ“œν•  수 μžˆλŠ” ꡬ쑰λ₯Ό λ§Œλ“€μ—ˆλ‹€.

:root[data-brand="PARTNER_A"] {
  --color-filled-red: var(--color-red01);
}

μ‚¬μš©ν•˜λŠ” μ•±μ˜ HTML 루트 μ—˜λ¦¬λ¨ΌνŠΈμ— data-brand μ†μ„±λ§Œ μ§€μ •ν•΄μ£Όλ©΄ λœλ‹€.

<html data-brand="PARTNER_A">

배포 μžλ™ν™” 슀크립트

νŒ¨ν‚€μ§€λ₯Ό 직접 λ°°ν¬ν•˜λ‹€ λ³΄λ‹ˆ, 버전을 올리고 μ»€λ°‹ν•˜κ³  νƒœκ·Έλ₯Ό λ§Œλ“œλŠ” κ³Όμ •μ—μ„œ 휴먼 μ—λŸ¬κ°€ λ°œμƒν•  μ—¬μ§€κ°€ μžˆμ—ˆλ‹€. 이런 반볡적인 과정을 쀄이기 μœ„ν•΄ 배포 μžλ™ν™” 슀크립트λ₯Ό λ§Œλ“€μ—ˆλ‹€.

{
  "scripts": {
    "publish:themes:patch": "node scripts/publish.js themes patch",
    "publish:themes:minor": "node scripts/publish.js themes minor",
    "publish:themes:major": "node scripts/publish.js themes major"
  }
}

μŠ€ν¬λ¦½νŠΈκ°€ ν•˜λŠ” 일

1. package.json의 버전을 μžλ™μœΌλ‘œ 올리고

- patch: `2.0.2` → `2.0.3`
- minor: `2.0.2` → `2.1.0`
- major: `2.0.2` → `3.0.0`

2. 변경사항을 μ»€λ°‹ν•˜κ³  νƒœκ·Έλ₯Ό μƒμ„±ν•œ λ‹€μŒ

   git add .
   git commit -m "chore: release @company@2.0.3"
   git tag @company-theme@2.0.3

3. npm publish둜 GitHub Packages에 배포
4. λ§ˆμ§€λ§‰μœΌλ‘œ main λΈŒλžœμΉ˜μ™€ νƒœκ·Έλ₯Ό push

덕뢄에 μ‹€μˆ˜ 없이, λˆ„κ΅¬λ‚˜ 같은 λ°©μ‹μœΌλ‘œ 배포할 수 있게 λ˜μ—ˆλ‹€.

GitHub Packages 인증 μ„€μ •

νŒ€μ›λΆ„λ“€μ΄ νŒ¨ν‚€μ§€λ₯Ό μ„€μΉ˜ν•˜λ €λ©΄ GitHub 인증이 ν•„μš”ν–ˆλ‹€.

1. GitHub Personal Access Token 생성
2. ν”„λ‘œμ νŠΈ λ£¨νŠΈμ—. npmrc 파일 생성

@company:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}

3. ν™˜κ²½λ³€μˆ˜ μ„€μ •

export NPM_TOKEN=ghp_xxxxxxxxxxxxx

터미널을 μž¬μ‹œμž‘ν•  λ•Œλ§ˆλ‹€ 토큰이 μ΄ˆκΈ°ν™”λ˜λŠ” λ¬Έμ œκ°€ μžˆμ—ˆλ‹€. 맀번 μˆ˜λ™μœΌλ‘œ μž…λ ₯ν•΄μ•Ό ν–ˆκΈ° λ•Œλ¬Έμ—, macOS의 Keychain을 μ‚¬μš©ν•΄ 토큰을 μžλ™μœΌλ‘œ λΆˆλŸ¬μ˜€λŠ” λ°©μ‹μœΌλ‘œ ν•΄κ²°ν–ˆλ‹€.

κ²°κ³Ό

Before
νŒ¨ν‚€μ§€ν™”λ₯Ό ν•˜κΈ° μ „μ—λŠ” 단 ν•˜λ‚˜μ˜ μƒ‰μƒλ§Œ μˆ˜μ •ν•΄λ„ λͺ¨λ“  λ ˆν¬μ§€ν† λ¦¬μ˜ tailwind.config.jsλ₯Ό μ—΄μ–΄ 같은 값을 반볡 μˆ˜μ •ν•΄μ•Ό ν–ˆλ‹€. 색상 ν•˜λ‚˜ λ°”κΎΈλ €λ©΄ → λͺ¨λ“  레포 μˆ˜μ • + 배포 ν•„μš” -> μž‘μ—… μ‹œκ°„μ΄ λŠ˜μ–΄λ‚˜κ³ , μ‹€μˆ˜ κ°€λŠ₯성도 λ†’μ•˜λ‹€.

After
μ΄μ œλŠ” λͺ¨λ“  ν”„λ‘œμ νŠΈκ°€ 곡톡 νŒ¨ν‚€μ§€μ˜ 토큰을 κ·ΈλŒ€λ‘œ μ°Έμ‘°ν•œλ‹€.

/* app.css */
@import '@company/themes/mobile';
레포 A: @import '@company/themes/mobile';
레포 B: @import '@company/themes/mobile';
레포 C: @import '@company/themes/web';

색상 ν•˜λ‚˜λ₯Ό λ°”κΎΈλ €λ©΄ themes νŒ¨ν‚€μ§€μ—μ„œ λ³€μˆ˜ 값을 μˆ˜μ •ν•˜κ³  yarn publish:themes:patch둜 λ°°ν¬ν•œ λ’€, 각 λ ˆν¬μ—μ„œ yarn upgrade @company/themesλ₯Ό μ‹€ν–‰ν•˜λ©΄ 끝이닀.

---

이번 ν”„λ‘œμ νŠΈλ₯Ό ν•˜λ©΄μ„œ λ§Žμ€ 고민이 μžˆμ—ˆλ‹€. 사싀 μ²˜μŒμ—λŠ” νŒ¨ν‚€μ§€λ‘œ λ§Œλ“œλŠ” 것이 κ³Όν•œ 선택은 μ•„λ‹κΉŒ, μœ μ§€λ³΄μˆ˜κ°€ 더 μ–΄λ €μ›Œμ§€μ§€λŠ” μ•Šμ„κΉŒ ν•˜λŠ” 생각도 ν–ˆλ‹€. ν•˜μ§€λ§Œ μ‹€μ œλ‘œ νŒ¨ν‚€μ§€λ‘œ κ΄€λ¦¬ν•˜κ²Œ λ˜λ©΄μ„œ "ν•œ κ³³μ—μ„œ λ°”κΎΈλ©΄ λͺ¨λ“  곳에 λ°˜μ˜λœλ‹€" λŠ” μ‹ λ’°κ°€ 생겼고, λ””μžμΈνŒ€κ³Ό κ°œλ°œνŒ€ λͺ¨λ‘ 훨씬 더 μΌκ΄€λœ μ–Έμ–΄λ‘œ μ†Œν†΅ν•  수 있게 λ˜μ–΄ λΏŒλ“―ν•˜λ‹€. πŸ™‚