디자인 시스템이 AI를 만났을 때 - 디자이너의 반복 질문 줄이기

디자인 시스템의 코드에 기반하여 답변해주는 슬랙 봇을 만들었습니다.

12
조회

디자인 시스템의 코드에 기반하여 답변해주는 슬랙 봇을 만들었습니다.



작년 말, 저희 회사의 디자인 시스템 TF에 합류하게 됐습니다. 합류하고 얼마 지나지 않아 디자이너 8분을 대상으로 만족도 조사를 돌렸는데, 결과가 흥미로웠어요.

전반적인 만족도는 평균 4.5점으로 나쁘지 않았는데, 학습 난이도와 시스템 이해도 항목만 유독 3.8점이었습니다. 즉, 사용은 하고 있는데 충분히 이해한 채로 쓰고 있는 건 아니라는 뜻이었어요.

이어서 디자이너 6분과 인터뷰를 했는데 공통적으로 막히는 지점이 있었습니다.

뭘 어디까지 수정해도 되는지 모르겠어요.

커스텀을 해야 하는 상황인데, 스스로 판단하기가 어려워요.

이와 같이 디자이너분들은 주로 "이 컴포넌트를 어디까지 변형해도 되는가", 즉 커스텀의 가능 범위에서 많이 막히곤 하셨습니다.

커스텀 가능 범위는 주로 코드를 봐야 알 수 있기에 디자이너분들은 자연스럽게 개발자에게 질문을 하게 됩니다.

승준님, RadioGroup에서 padding 값을 커스텀 할 수 있나요?

제가 아는 영역이면 수십 초 안에 답변이 가능했어요. 하지만 모르는 영역이라면 스토리북을 켜고 코드를 수정해가면서 확인하는 데까지 수십 분이 걸리곤 했습니다. 아는 영역이더라도 틀릴 때가 있기도 했구요.

저희 개발팀은 디자인 시스템 팀이 따로 없고 TF로 구성되어 있기에 디자인 시스템 개발자 모두 각 스쿼드에서 해야 하는 일이 있었어요. 그렇기에 이러한 질문에 답을 많이 하게 되면 스쿼드 업무에 지장이 가곤 했고, 그에 따라 질문하는 디자이너분들도 미안해하시곤 했어요.

그래서 이러한 병목을 없애보고자 디자인 시스템의 코드에 기반하여 답변해주는 슬랙 봇을 만들었습니다. AI에 익숙하지 않은 디자이너라도 슬랙은 모두 익숙했고 코드에 기반하여 AI가 답변을 해준다면 오히려 사람보다 정확할 수 있다고 생각했어요.



구현

자세한 설명에 앞서, 슬랙 봇이 답변해주는 전체 흐름은 대략 다음과 같습니다.

청킹

봇이 답변을 잘 하려면 우선 검색이 잘 되어야 합니다. 검색이 잘 되려면 인덱싱 단위, 즉 청크가 잘 잘려있어야 해요.

인덱싱하는 대상은 크게 두 종류였습니다.

  • 마크다운
    • AI_*_SPEC.md — 디자인 시스템 MCP가 참고하는 문서로 Props, 사용 예시, 제약사항 등이 정리되어 있어요. 코드만 봐서는 드러나지 않는 작성자의 의도(권장 사용법, 피해야 하는 패턴, 그렇게 정한 이유)가 함께 담겨 있어서, 사람이 의도한 방향으로 추론하기가 쉬워져요.
    • STACK_GUIDELINE.md — 디자인 시스템 전반의 철학과 원칙(기본값 우선, 유연한 커스터마이징, 접근성 등)을 담은 단일 가이드 문서에요.
  • 코드 — packages/*/src/**/*.{tsx,ts}

마크다운은 단순하게 인덱싱했습니다. ##, ### 헤더를 기준으로 나눴어요.

### 1. 기본값 우선 원칙
 
> 불필요한 Props 선언을 지양하고 시스템이 제공하는 기본값을 적극 활용합니다.
 
- **원칙**:
 
  - 컴포넌트의 기본값은 가장 일반적인 사용 사례에 최적화되어 있습니다.
  - 명시적으로 다른 값이 필요한 경우에만 Props를 선언합니다.
 
- **예시**:
  - `<Button>확인</Button>` → 권장 (기본값 활용)
  - `<Button size="md" variant="primary">확인</Button>` → 지양 (불필요한 명시)

코드는 처음엔 그냥 줄 수 기반으로 자를까 했는데, 함수 한가운데가 잘려나가면 그 청크는 의미가 많이 떨어질 거라고 생각했어요. 그래서 중괄호를 바탕으로 컴포넌트의 경계를 추정하는 방식으로 청킹을 했습니다. 완벽하진 않지만, 컴포넌트 단위로 청크가 나뉘니 검색 품질이 훨씬 좋아졌어요.

그리고 모든 코드 청크 맨 위엔 출처 파일 경로를 한 줄 박아뒀습니다. 출처 한 줄을 박아두면 검색 결과로 끌려나온 청크만 봐도 어디에서 온 코드인지 AI가 알 수 있어서, "이건 Tag 컴포넌트의 일부이고…" 같은 맥락 잡힌 답변을 만들기 쉬워졌습니다.

예를 들면 다음과 같아요.

// File: packages/tag/src/Tag.tsx
export const Tag = forwardRef<HTMLDivElement, TagProps>(
  (
    {
      size: sizeFromProps = 'md',
      bgColor = vars.neutral[10],
      color = vars.neutral[60],
      radius = 'default',
      leftAddon,
      children,
      style: styleFromProps,
      ...restProps
    },
    ref,
  ) => {
    ...
 
    return (
      <div ref={ref} css={[tagContainerCss, tagSizeCss(sizes)]} style={style} {...restProps}>
        {leftAddon && <span css={css(leftAddonStyles)}>{leftAddon}</span>}
        {children}
      </div>
    );
  },
);

임베딩

처음엔 OpenAI 임베딩으로 시작했는데, 운영해보니 굳이 1536차원이 필요 없겠다 싶더라고요. 디자인 시스템 도메인이 그렇게 넓지 않고 컴포넌트와 토큰 정도가 핵심이라, 의미 공간이 비교적 협소했어요.

그래서 Voyage AI의 voyage-3-lite(512차원)으로 갈아탔습니다. 비용이 크게 줄었고 검색 품질은 체감 차이가 거의 없었어요. 다만 무료 티어 Rate Limit이 3 RPM이라 엄청 느리다는 것이 단점이었습니다. 우아하진 않지만 무료인 점이 매력적이고 일주일에 한 번 임베딩하는 것만으로도 충분해서 감수하기로 했어요.


UX 개선

봇을 만들고 난 후 슬랙에서 동작은 잘 되었는데 아쉬운 점이 하나 있었어요. 느려 보였습니다.

LLM 추론이 보통 5초에서 10초 정도 걸리는데, 그 사이 사용자 화면엔 아무 반응이 없으니 봇이 죽은 줄 알고 질문자가 이탈하진 않을까 걱정되었습니다.

그래서 답변에 걸리는 시간 동안 피드백을 주기 위해 다음과 같은 요소들을 추가했어요.

  • 👀 이모지 reaction — 봇이 메시지를 받자마자 원본 메시지에 👀를 붙이고, 답변이 끝나면 떼어냅니다. 처리 중이라는 신호를 즉시 줄 수 있어요.
  • 로딩 메시지 → 답변으로 업데이트 — "답변을 생성하고 있습니다…" 메시지를 스레드에 먼저 보내두고, 답변이 완성되면 메시지를 답변으로 수정해요.

운영하면서 느낀 것들

도입 이후 8명의 디자이너 전원이 스택봇을 사용했어요. 총 56건의 질문이 들어왔고, 별다른 홍보 없이도 매일 1건 이상 질문이 이어졌어요. 전체 질문의 58%가 "이거 커스텀해도 돼?"였고, 컴포넌트별로는 Modal이 1위(29%)였어요.

스택봇 만족도는 4.5 / 5.0이었어요. (7명 응답) 특히 "스택봇이 없었다면 어떻게 했을 것 같나요?"라는 질문에서 스택봇의 효과를 알 수 있었어요.

  • 전원이 "담당자에게 질문하고 1~2일 기다렸을 것"을 선택
  • "큰 문제 없었을 것"을 선택한 사람은 0명

질문 빈도도 전원이 줄었다고 답했고, 전원이 스택봇을 근거로 커스텀 여부를 스스로 판단한 경험이 있다고 했어요. 도입 전에는 불가능했던 일이에요.

다른 디자이너가 올리는 질문을 참조하는 것만으로도 간접적으로 많은 도움이 됐어요.

답변과 관련된 컴포넌트를 스토리북·피그마로도 확인할 수 있으면 좋겠어요.




그냥 한 번 해보면 되지 않을까 싶어서 만들어본 건데, 생각보다 효과가 좋아서 놀랐어요. 디자이너분들이 봇을 통해 스스로 답을 찾아가셔서 뿌듯했고, AI를 활용해서 실제로 누군가의 문제를 해결해주는 경험이 재밌었습니다.

아직 해결해야 할 것들이 남아있긴 해요. 지금은 임베딩을 제가 일주일마다 수동으로 돌려주고 있어요. 디자인 시스템 코드가 변경될 때 달라진 부분만 임베딩을 돌리거나, 매주 자동으로 임베딩이 돌아가도록 해볼 생각이에요.