Skip to content

Conversation

@dasosann
Copy link
Contributor

@dasosann dasosann commented Jan 26, 2026

요약

🤖 Generated by PR Agent at 354fd18

  • 디자인 토큰 자동 생성 스크립트 추가 및 CSS 변수화
  • token.json에서 색상, 타이포그래피, 반경 등을 CSS 변수로 변환
  • 생성된 tokens.css를 전역 스타일에 통합하여 일관된 디자인 시스템 구축

구현 사항

Relevant files
Enhancement
generate-tokens.js
토큰 JSON을 CSS 변수로 변환하는 생성 스크립트                                                       

scripts/generate-tokens.js

  • token.json을 파싱하여 색상, 반경, 보더, 불투명도 등의 토큰을 추출
  • 토큰 참조({Grayscale.color-gray-0} 형태)를 CSS 변수로 해석 및 변환
  • text-{size}-{weight} 형태의 타이포그래피 유틸리티 클래스 자동 생성
  • 생성된 CSS를 app/tokens.css에 저장하는 Node.js 스크립트
+214/-0 
tokens.css
자동 생성된 CSS 변수 및 유틸리티 클래스                                                                 

app/tokens.css

  • 그레이스케일, 핑크, 플레임, 오렌지 색상 CSS 변수 정의
  • 반경(--radius-xs ~ --radius-full), 보더, 불투명도 변수 설정
  • text-{size}-{weight} 형태의 타이포그래피 유틸리티 클래스 (10px ~ 24px)
  • 배경, 버튼, 보더, 텍스트 색상 유틸리티 클래스 정의
+260/-0 
globals.css
토큰 CSS 임포트 추가 및 포맷 정리                                                                       

app/globals.css

  • @import "tailwindcss" 따옴표 스타일 통일 (싱글 → 더블)
  • 새로운 @import "./tokens.css" 추가하여 토큰 스타일 로드
+2/-1     
page.tsx
디자인 토큰 테스트 데모 페이지로 변경                                                                       

app/page.tsx

  • 기존 Next.js 보일러플레이트 코드 제거 (Image, 링크 등)
  • 디자인 토큰 테스트 페이지로 전환 (타이포그래피, 색상, 버튼 섹션)
  • text-24-700, bg-brand-secondary-pink, bg-button-primary 등 토큰 유틸리티 클래스
    사용
  • 토큰 시스템의 실제 동작을 시각적으로 검증하는 데모 페이지
+55/-57 
Configuration changes
settings.json
CSS 커스텀 at-rule 린트 경고 비활성화                                                             

.vscode/settings.json

  • "css.lint.unknownAtRules": "ignore" 설정 추가
  • CSS 린터가 @layer, @custom-variant 등 커스텀 at-rule 경고 무시하도록 설정
+2/-1     
Miscellaneous
token.json
기존 토큰 파일 제거                                                                                           

app/src/token.json

  • 기존 토큰 정의 파일 삭제 (1279줄 전체 제거)
  • 토큰 관리 위치 변경 (구조 재정리 예상)
+0/-1279

Need Review

  • ~ 부분 이렇게 구현했어요, 피드백 부탁해요!

Reference

📜 리뷰 규칙

Reviewer는 아래 P5 Rule을 참고하여 리뷰를 진행합니다.
P5 Rule을 통해 Reviewer는 Reviewee에게 리뷰의 의도를 보다 정확히 전달할 수 있습니다.

  • P1: 꼭 반영해주세요 (Comment)
  • P2: 적극적으로 고려해주세요 (Comment)
  • P3: 웬만하면 반영해 주세요 (Comment)
  • P4: 반영해도 좋고 넘어가도 좋습니다 (Approve)
  • P5: 그냥 사소한 의견입니다 (Approve)

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @dasosann, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 프로젝트에 디자인 토큰 시스템을 통합하여 UI 일관성을 높이고 개발 효율성을 개선하는 것을 목표로 합니다. 기존의 디자인 토큰 정의를 스크립트를 통해 CSS 변수 및 유틸리티 클래스로 자동 변환하고, 이를 애플리케이션에 적용하여 디자인 시스템의 기반을 마련합니다. 또한, 새로운 토큰의 적용을 시각적으로 검증할 수 있는 데모 페이지를 제공합니다.

Highlights

  • 디자인 토큰 시스템 도입: 디자인 토큰을 관리하고 적용하기 위한 새로운 시스템이 도입되었습니다. app/src/token.json 파일은 더 이상 직접 사용되지 않고, scripts/generate-tokens.js 스크립트를 통해 app/tokens.css 파일로 변환됩니다.
  • 자동 생성된 CSS 토큰 파일 추가: app/tokens.css 파일이 새로 추가되었으며, 이 파일은 색상, 폰트 크기, 테두리 반경 등 디자인 시스템의 핵심 요소를 CSS 변수와 유틸리티 클래스 형태로 포함합니다. 이 파일은 app/globals.css에 임포트되어 전역적으로 사용됩니다.
  • 디자인 토큰 데모 페이지 구현: app/page.tsx 파일의 내용이 완전히 재작성되어, 새로 도입된 디자인 토큰(타이포그래피, 색상, 버튼 스타일 등)이 실제 UI에서 어떻게 적용되는지 시각적으로 확인할 수 있는 데모 페이지로 변경되었습니다.
  • VS Code 설정 업데이트: VS Code 설정에 css.lint.unknownAtRules: "ignore"가 추가되어, 디자인 토큰 시스템에서 사용될 수 있는 사용자 정의 CSS at-rule에 대한 린트 경고를 무시하도록 설정되었습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@qodo-code-review
Copy link

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🟢
No security concerns identified No security vulnerabilities detected by AI analysis. Human verification advised for critical code.
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing error handling: The token generation script performs file IO and JSON parsing without try/catch or input
shape checks, so missing/invalid token.json or unexpected token structure will crash
without actionable context.

Referred Code
const tokensPath = path.join(__dirname, "../app/token.json");
const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8"));

// Semantic tokens에서 실제 색상값 추출
const semanticMode1 = tokens["Sementic/Mode 1"] || {};
const systemMode1 = tokens["System/Mode 1"] || {};

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Unvalidated external input: The script consumes an external JSON file (../app/token.json) and assumes specific nested
properties exist without validation/sanitization, which may be acceptable for a trusted
build-time pipeline but needs confirmation.

Referred Code
const tokensPath = path.join(__dirname, "../app/token.json");
const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8"));

// Semantic tokens에서 실제 색상값 추출
const semanticMode1 = tokens["Sementic/Mode 1"] || {};
const systemMode1 = tokens["System/Mode 1"] || {};

// Grayscale, Colors, Transparent 값 추출
const grayscale = semanticMode1.Grayscale || {};
const colors = semanticMode1.Colors || {};
const transparent = semanticMode1.Transparent || {};

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link

qodo-code-review bot commented Jan 26, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix token JSON path

Update the file path in scripts/generate-tokens.js from ../app/token.json to
../app/src/token.json to match the file's actual location.

scripts/generate-tokens.js [9-10]

-const tokensPath = path.join(__dirname, "../app/token.json");
+const tokensPath = path.join(__dirname, "../app/src/token.json");
 const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8"));

[Suggestion processed]

Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies that the script is pointing to a non-existent file path, which would cause it to fail. Correcting the path is a critical fix for the script to function as intended.

High
Simplify and fix token reference resolver

Simplify the resolveValue function to make it more scalable and fix a bug where
a broad if condition could incorrectly handle specific token references.

scripts/generate-tokens.js [98-140]

 // 토큰 참조 해석
 function resolveValue(value, depth = 0) {
   if (depth > 10 || typeof value !== "string") return value;
 
   const match = value.match(/^\{(.+)\}$/);
   if (!match) return value;
 
   const ref = match[1];
+  const parts = ref.split(".");
+  
+  // The last part of the reference is the token key.
+  const key = parts[parts.length - 1];
 
-  // Grayscale 참조
-  if (ref.startsWith("Grayscale.")) {
-    const key = ref.replace("Grayscale.", "");
-    return `var(--${key})`;
-  }
-
-  // Colors 참조
-  if (ref.startsWith("Colors.Pink.")) {
-    const key = ref.replace("Colors.Pink.", "");
-    return `var(--${key})`;
-  }
-  if (ref.startsWith("Colors.Flame.")) {
-    const key = ref.replace("Colors.Flame.", "");
-    return `var(--${key})`;
-  }
-  if (ref.startsWith("Colors.Orange.")) {
-    const key = ref.replace("Colors.Orange.", "");
-    return `var(--${key})`;
-  }
-
-  // Transparent 참조
-  if (ref.startsWith("Transparent.")) {
-    const key = ref.replace("Transparent.", "");
-    return `var(--${key})`;
-  }
-
-  // System/Mode 1의 Colors 참조
-  if (ref.startsWith("Colors.")) {
-    const key = ref.replace("Colors.", "");
-    return `var(--${key})`;
+  if (key) {
+    return `var(--${sanitizeKey(key)})`;
   }
 
   return value;
 }
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies a potential bug and non-scalable code in resolveValue, proposing a more robust and simplified implementation that improves both correctness and maintainability.

Medium
High-level
Use a standard token-processing tool

Instead of using a custom script to convert JSON design tokens to CSS, adopt an
industry-standard tool like Style Dictionary or Tokens Studio's CLI. This
improves maintainability, provides more features, and reduces the custom code
burden.

Examples:

scripts/generate-tokens.js [1-214]
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// token.json 읽기
const tokensPath = path.join(__dirname, "../app/token.json");
const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8"));

 ... (clipped 204 lines)

Solution Walkthrough:

Before:

// scripts/generate-tokens.js
import fs from "fs";

const tokens = JSON.parse(fs.readFileSync(".../token.json"));
let cssVariables = [];
let tailwindUtilities = [];

// Manual parsing for each token type (Grayscale, Colors, Radius, etc.)
Object.entries(tokens["Sementic/Mode 1"].Grayscale).forEach(...)
Object.entries(tokens["System/Mode 1"].Radius).forEach(...)

function resolveValue(value) {
  // Manual, hardcoded reference resolution based on string matching
  if (ref.startsWith("Grayscale.")) { ... }
  if (ref.startsWith("Colors.Pink.")) { ... }
  // ...
}

// Manual CSS string construction and file writing
const cssContent = `... ${cssVariables.join('\n')} ...`;
fs.writeFileSync(".../tokens.css", cssContent);

After:

// package.json (conceptual)
{
  "scripts": {
    "build:tokens": "sd-transforms" // or style-dictionary build
  },
  "devDependencies": {
    "@tokens-studio/sd-transforms": "latest" // or "style-dictionary"
  }
}

// sd.config.js (conceptual config for Tokens Studio CLI)
export default {
  source: ["app/token.json"],
  platforms: {
    css: {
      transformGroup: "css",
      buildPath: "app/",
      files: [{
        destination: "tokens.css",
        format: "css/variables",
        // Configuration handles token resolution, formatting,
        // and utility class generation automatically.
      }],
    },
  },
};
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies that the custom scripts/generate-tokens.js script reinvents a solved problem, and replacing it with a standard tool would significantly improve long-term maintainability and scalability.

Medium
General
Refactor color processing for scalability

Refactor the repetitive color token processing logic into a scalable helper
function to improve maintainability.

scripts/generate-tokens.js [29-57]

-// Grayscale 색상
-Object.entries(grayscale).forEach(([key, value]) => {
-  if (key.startsWith("color-gray-")) {
-    cssVariables.push(`  --${sanitizeKey(key)}: ${value.$value};`);
-  }
-});
-
-// Colors (Pink, Flame, Orange)
-if (colors.Pink) {
-  Object.entries(colors.Pink).forEach(([key, value]) => {
-    if (key.startsWith("color-pink-")) {
+const processColorGroup = (group) => {
+  if (!group) return;
+  Object.entries(group).forEach(([key, value]) => {
+    // Process only entries that are token objects with a $value
+    if (value && typeof value === 'object' && value.hasOwnProperty('$value')) {
       cssVariables.push(`  --${sanitizeKey(key)}: ${value.$value};`);
     }
   });
-}
-if (colors.Flame) {
-  Object.entries(colors.Flame).forEach(([key, value]) => {
-    if (key.startsWith("color-flame-")) {
-      cssVariables.push(`  --${sanitizeKey(key)}: ${value.$value};`);
-    }
-  });
-}
-if (colors.Orange) {
-  Object.entries(colors.Orange).forEach(([key, value]) => {
-    if (key.startsWith("color-orange-")) {
-      cssVariables.push(`  --${sanitizeKey(key)}: ${value.$value};`);
-    }
-  });
+};
+
+// Grayscale 색상
+processColorGroup(grayscale);
+
+// Colors (Pink, Flame, Orange)
+if (colors) {
+  Object.values(colors).forEach(processColorGroup);
 }
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: The suggestion correctly points out repetitive code and proposes a good refactoring that improves maintainability and scalability by using a helper function.

Low
  • More

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

디자인 토큰을 자동 생성하는 스크립트를 도입하여 CSS 변수와 유틸리티 클래스를 만드는 변경 사항 잘 보았습니다. 이를 통해 디자인 시스템의 일관성을 높이고 유지보수성을 개선하려는 방향은 매우 긍정적입니다. 다만, 새로 추가된 generate-tokens.js 스크립트의 토큰 참조 해석 로직이 특정 경로에 의존하고 있어 확장성이 떨어질 우려가 있습니다. 또한, 데모 페이지에서 아직 정의되지 않은 클래스를 사용하거나 하드코딩된 값을 사용하는 부분이 있어 수정이 필요해 보입니다. 아래에 몇 가지 구체적인 피드백을 남겼으니 확인 부탁드립니다.

Comment on lines +48 to +56
<button className="btn-primary text-16-600 px-8 py-3 transition-opacity hover:opacity-90">
Primary Button
</button>
<button className="btn-slate text-brand-black border-light text-16-600 rounded-2xl border px-8 py-3">
Secondary Button
</button>
<button className="btn-disabled text-16-400 cursor-not-allowed px-8 py-3">
Disabled Button
</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

버튼에 사용된 btn-primary, btn-slate, btn-disabled 클래스가 tokens.css에 정의되어 있지 않아 버튼 스타일이 올바르게 적용되지 않습니다. generate-tokens.js 스크립트는 bg-button-* 형태의 배경 유틸리티 클래스를 생성하므로 이를 사용해야 합니다.

또한, 버튼들의 border-radius가 일관성 있게 적용되지 않았습니다. rounded-2xl을 공통으로 적용하고, text-white, text-disabled 같은 텍스트 색상 토큰을 사용하여 스타일을 완성하는 것을 제안합니다.

Suggested change
<button className="btn-primary text-16-600 px-8 py-3 transition-opacity hover:opacity-90">
Primary Button
</button>
<button className="btn-slate text-brand-black border-light text-16-600 rounded-2xl border px-8 py-3">
Secondary Button
</button>
<button className="btn-disabled text-16-400 cursor-not-allowed px-8 py-3">
Disabled Button
</button>
<button className="bg-button-primary text-white text-16-600 rounded-2xl px-8 py-3 transition-opacity hover:opacity-90">
Primary Button
</button>
<button className="bg-button-slate text-brand-black border-light text-16-600 rounded-2xl border px-8 py-3">
Secondary Button
</button>
<button className="bg-button-disabled text-disabled text-16-400 rounded-2xl cursor-not-allowed px-8 py-3">
Disabled Button
</button>

Comment on lines +99 to +140
function resolveValue(value, depth = 0) {
if (depth > 10 || typeof value !== "string") return value;

const match = value.match(/^\{(.+)\}$/);
if (!match) return value;

const ref = match[1];

// Grayscale 참조
if (ref.startsWith("Grayscale.")) {
const key = ref.replace("Grayscale.", "");
return `var(--${key})`;
}

// Colors 참조
if (ref.startsWith("Colors.Pink.")) {
const key = ref.replace("Colors.Pink.", "");
return `var(--${key})`;
}
if (ref.startsWith("Colors.Flame.")) {
const key = ref.replace("Colors.Flame.", "");
return `var(--${key})`;
}
if (ref.startsWith("Colors.Orange.")) {
const key = ref.replace("Colors.Orange.", "");
return `var(--${key})`;
}

// Transparent 참조
if (ref.startsWith("Transparent.")) {
const key = ref.replace("Transparent.", "");
return `var(--${key})`;
}

// System/Mode 1의 Colors 참조
if (ref.startsWith("Colors.")) {
const key = ref.replace("Colors.", "");
return `var(--${key})`;
}

return value;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

resolveValue 함수가 Grayscale., Colors.Pink. 등 특정 문자열 prefix에 의존하여 토큰 참조를 해석하고 있습니다. 이 방식은 새로운 토큰 그룹이 추가될 때마다 코드를 수정해야 하므로 확장성과 유지보수성이 떨어집니다.

점(.)으로 구분된 경로(a.b.c)를 파싱하여 토큰 객체를 동적으로 탐색하는 범용적인 해석 함수로 리팩터링하는 것을 강력히 권장합니다. 이렇게 하면 토큰 구조가 변경되거나 확장되어도 스크립트를 수정할 필요가 없어집니다.

References
  1. 중복 코드를 발견하면 재사용 가능한 유틸리티나 컴포넌트로 추출할 것을 제안하세요. 현재 resolveValue 함수는 각 토큰 그룹에 대한 처리 로직이 중복되어 있어 유지보수가 어렵습니다. 이를 범용적인 함수로 추출하여 개선할 수 있습니다. (link)

<div className="bg-surface-base flex min-h-screen items-center justify-center font-sans">
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center gap-8 px-8 py-12">
{/* 토큰 테스트 섹션 */}
<div className="w-full space-y-8 rounded-lg border border-gray-200 bg-white p-8 shadow-sm">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

이 컴포넌트에서 border-gray-200bg-white 같은 하드코딩된 스타일 값을 사용하고 있습니다. 디자인 토큰 시스템을 도입한 만큼, 모든 스타일은 토큰을 통해 관리하는 것이 일관성 및 유지보수 측면에서 바람직합니다. border-light와 같은 시맨틱 토큰을 사용하거나, border-gray-200에 해당하는 토큰을 추가하여 사용하시는 것을 권장합니다.

References
  1. 중복 코드를 발견하면 재사용 가능한 유틸리티나 컴포넌트로 추출할 것을 제안하세요. 이 경우, 하드코딩된 값을 사용하는 대신 토큰 기반의 유틸리티를 사용하여 코드의 일관성과 재사용성을 높여야 합니다. (link)

{/* 1. Typography */}
<section className="space-y-4">
<h2 className="text-20-600">1. Typography</h2>
<div className="space-y-2 rounded bg-gray-50 p-4">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

타이포그래피 섹션의 배경색으로 bg-gray-50이 하드코딩되어 있습니다. 이 또한 color-gray-50 토큰을 활용한 유틸리티 클래스(예: bg-gray-50)로 대체하여 일관성을 유지하는 것이 좋습니다. 현재 스크립트에서는 해당 유틸리티 클래스를 생성하지 않으므로, generate-tokens.js 스크립트에 Grayscale 색상에 대한 배경 유틸리티 클래스 생성 로직을 추가하는 것을 고려해 보세요.

References
  1. 중복 코드를 발견하면 재사용 가능한 유틸리티나 컴포넌트로 추출할 것을 제안하세요. 이 경우, 하드코딩된 값을 사용하는 대신 토큰 기반의 유틸리티를 사용하여 코드의 일관성과 재사용성을 높여야 합니다. (link)

Comment on lines +108 to +111
if (ref.startsWith("Grayscale.")) {
const key = ref.replace("Grayscale.", "");
return `var(--${key})`;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

resolveValue 함수 내에서 토큰 참조를 var() 함수로 변환할 때 sanitizeKey 함수를 사용하지 않고 있습니다. 현재 token.json의 참조 대상 키들은 이미 CSS 변수명으로 사용하기에 적합한 형태이지만, 만약 토큰 이름에 공백이나 특수문자가 포함될 경우 (예: {'My Color': ...}) 유효하지 않은 CSS 변수 참조(var(--My Color))가 생성될 수 있습니다. 코드의 안정성을 높이기 위해 var() 내부에서도 sanitizeKey를 적용하는 것을 권장합니다.

Suggested change
if (ref.startsWith("Grayscale.")) {
const key = ref.replace("Grayscale.", "");
return `var(--${key})`;
}
if (ref.startsWith("Grayscale.")) {
const key = ref.replace("Grayscale.", "");
return `var(--${sanitizeKey(key)})`;
}

tailwindUtilities.push(`${className} {
font-size: ${size}px;
font-weight: ${weight};
line-height: 1.5;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

타이포그래피 유틸리티 클래스 생성 시 line-height 값이 1.5로 하드코딩되어 있습니다. line-height 역시 디자인 시스템의 중요한 요소이므로, token.json에 토큰으로 정의하고 이를 스크립트에서 읽어 사용하도록 수정하는 것이 좋습니다. 이렇게 하면 타이포그래피 스타일을 중앙에서 일관되게 관리할 수 있습니다.

@dasosann dasosann closed this Jan 26, 2026
Comment on lines +9 to +10
const tokensPath = path.join(__dirname, "../app/token.json");
const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8"));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion: Fix token JSON path

Suggested change
const tokensPath = path.join(__dirname, "../app/token.json");
const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8"));
const tokensPath = path.join(__dirname, "../app/src/token.json");
const tokens = JSON.parse(fs.readFileSync(tokensPath, "utf-8"));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants