ghdtjgus

이번 주 과제는 토큰 관리 방법 및 자동화에 대해서 생각해 보는 시간이었다.
 
GDSC 와우 디자인 시스템에서도 warrr-ui처럼 panda css를 사용해서 개발하고 있었기 때문에 와우 디자인 시스템의 토큰 관리 방법을 많이 참고해서 생각해 볼 수 있었다.
 

와우 디자인 시스템 토큰 관리 방법

일단, 와우 디자인 시스템에서는 wow-tokens라는 패키지에서 토큰 값들을 객체나 다른 구조가 아니라 string 값으로 관리하고 있다.
이는, 사용자가 원하는 대로 커스텀해서 사용하기 용이하게 하기 위해서 그렇다.
아래 링크를 들어가보면 어떤 방식으로 관리하고 있는지 한 번에 알아챌 거다.
https://github.com/GDSC-Hongik/wow-design-system/tree/main/packages/wow-tokens/src
 
어쨌든 이 토큰은 우리가 이 디자인 시스템을 이용해서 개발할 스터디 서비스에도 사용할 예정이고 우리 디자인 시스템을 사용하는 사람들도 필요하다면 쓸 수 있으니 여러 경우를 고려해서 배포하게 되었다.
하지만, 그렇게 string 값으로 관리하다 보니, 우리도 토큰을 사용하기 위해서는 약간의 가공 과정이 필요하다.
 
한편, panda css에서는 color, semantic color, radius, spacing 등 토큰을 사용하기 위해서는 아래와 같이 config에 등록시켜 주는 과정이 필요하다.

export * from "./color.ts";
export * from "./typography.ts";
import { defineTokens } from "@pandacss/dev";

import { colors, gradients } from "./color.ts";
import { radii } from "./radius.ts";
import { spacing } from "./space.ts";
import { borderWidths } from "./stroke.ts";

export const tokens = defineTokens({
  colors,
  gradients,
  spacing,
  radii,
  borderWidths,
});
import { defineConfig } from "@pandacss/dev";
import { semanticTokens, textStyles, tokens } from "theme";
import { removeUnusedCssVars, removeUnusedKeyframes } from "theme/utils";

export default defineConfig({
  preflight: true,
  minify: true,
  watch: true,
  outExtension: "js",
  polyfill: true,
  jsxFramework: "react",
  include: ["./src/**/*.{js,jsx,ts,tsx}"],
  exclude: [],
  hooks: {
    "cssgen:done": ({ artifact, content }) => {
      if (artifact === "styles.css") {
        return removeUnusedCssVars(removeUnusedKeyframes(content));
      }
    },
  },
  outdir: "styled-system",
  theme: {
    tokens,
    textStyles,
    semanticTokens,
  },
});

 
우리는 theme이라는 패키지에서 그 과정을 처리하고 있는데, 이 theme 패키지는 우리가 내부적으로 사용하는 panda css 관련 config들이라 별도로 npm에 배포하지는 않는다.
링크에 들어가보면 우리가 어떻게 theme을 관리하는지 알 수 있다.
https://github.com/GDSC-Hongik/wow-design-system/tree/main/packages/theme/src/tokens
 
만약, 우리가 토큰을 배포할 때 이 방식이 아니라 preset이라는 방식으로 배포한다면, 사용자는 선택의 여지없이 무조건 panda css를 사용해야만 한다.
물론 panda css 공식 문서에서는 디자인 시스템 만들 거면 preset이 가장 간단하고 편한 방식이라고 가장 추천하기는 한다.
https://panda-css.com/docs/guides/component-library
 
우리는 살짝? 불편하지만 사용자가 css 라이브러리를 선택할 수 있었으면 했고, 편하게 토큰을 가져다 쓸 수 있을 것이라는 생각에 이렇게 관리하고 있다.
 

내가 생각하기에 가장 괜찮은 warrr-ui 토큰 관리 방식

나는 근데 위 방식을 사용함에 있어서 불편함이 있었고 앞으로도 있을지도 모른다는 생각이 든다.
만약 우리가 몇 달 뒤 개발할 스터디 서비스에 panda css를 사용한다면 저 theme이라는 패키지와 동일한 과정을 거쳐서 panda css에 theme을 등록해 주는 과정이 필요하지 않을까?라는 의문이 하나 있었고, 또 하나는 tokens에서 토큰을 추가하거나 삭제한다면 theme 패키지에서도 그 과정이 동일하게 필요할 것인데 그걸 수동으로 해야 할까?라는 생각이 들었다.
 
그래서 내 결론은 와우 디자인 시스템처럼 string 값으로 관리하되 theme 패키지처럼 panda css에 맞게 토큰을 정의한 후 preset으로 배포하는 것이다.
사실 지금 우리가 정의한 theme 패키지나 preset이나 거의 다를 바 없다.
그래서 추후 확장성을 생각한다면 결국 와우 디자인 시스템도 preset으로 변경해야 하지 않을까 싶긴 하다.
 
이렇게 하면 panda css 사용 안 하는 유저 입장에서는 원하는 css 라이브러리를 쓰면서 원하는 구조로 토큰을 관리할 수 있어서 좋고, panda css 사용하는 유저는 아래처럼 설치 후 preset 등록하는 과정만 거쳐도 돼서 되게 편할 거라고 생각한다.
https://panda-css.com/docs/customization/presets
 
이렇게 관리 방식은 해결됐는데, tokens를 수정해도 theme 패키지를 매번 수정해야 하는 문제는 그대로 있었다.
이전 글에서 아이콘 관련 자동화 스크립트를 짠 적이 있었는데 토큰도 자동화 스크립트로 관리하면 좋지 않을까 하는 생각이 들어 이번에도 자동화 스크립트를 짰다.
 
typography, spacing, color 등 tokens 패키지의 각 파일을 불러와서 theme 패키지에 각각 파일로 분리해서 써주도록 하는 스크립트다.
그런데 다들 string 값으로 정의한 것들을 panda css에서 쓸 수 있는 객체 형식으로 변환하는 거라 로직이 거의 비슷하다.
그래서 typography를 변환하는 한 예시만 보도록 하자.
 
일단 아래는 tokens/typography.ts 파일, 즉 우리가 직접 수정할 파일이다.

export const h1 = {
  fontSize: "2rem",
  lineHeight: "130%",
  fontWeight: 500,
  letterSpacing: "-0.02rem",
};

export const h2 = {
  fontSize: "1.5rem",
  lineHeight: "130%",
  fontWeight: 500,
  letterSpacing: "-0.015rem",
};

 
이제 아래 자동화 스크립트를 작동시키면 textStyle이라는 객체 구조로 변경할 수 있다.

const generateTextStyleTokens = async (fileContent: string) => {
  const objectRegex = /export const (\w+) = \{([\s\S]*?)\};/g;
  const objects: Record<string, string> = {};
  let match;

  while ((match = objectRegex.exec(fileContent)) !== null) {
    const objectName = match[1] as string;
    objects[objectName] = `typography.${objectName}`;
  }

  const textStyleFileContent = [
    'import { defineTextStyles } from "@pandacss/dev";',
    'import { typography } from "warrrui-test-tokens";',
    "",
    "export const textStyles = defineTextStyles({",
    ...Object.keys(objects).map(
      (key) => `  ${key}: { value: ${objects[key]} },`
    ),
    "});",
  ].join("\n");
  const presetFilePath = `${PRESET_DIR}/typography.ts`;

  await fs.writeFile(presetFilePath, textStyleFileContent);
};
import { defineTextStyles } from "@pandacss/dev";
import { typography } from "warrrui-test-tokens";

export const textStyles = defineTextStyles({
  h1: { value: typography.h1 },
  h2: { value: typography.h2 },
});

 
스크립트에 대해서 자세히 알아보자면, 주요 로직은 다음과 같다.
1. 우리가 변환하고자 하는 형식의 정규 표현식을 지정한다.
2. 해당 정규 표현식을 사용해서 원하는 구조로 변환한다.
3. 지정된 경로에 해당 파일 내용을 작성한다.
 
이게 끝이다.
너무 간단해서 잉?스럽지만 어쨌든 그렇다.
 
이렇게 해서 다른 토큰들에도 동일한 로직의 스크립트를 작성해 주면 완성이다.
 
아래는 스크립트 작동시켜서 presets 패키지에 가공된 토큰 파일들이 생성되는 걸 보여주는 영상이다.
아주 잘 동작한다.

 
다음 주에는 직접 아이콘/토큰 자동화 피그마 플러그인을 만들어보려고 한다.
재밌겠지만 어려울 거 같은 느낌이다.

profile

ghdtjgus

@gugu76

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그