안녕하세요 메이토입니다 🍅 사실 이제는 우아한 테크코스가 작년에 끝나버렸기 때문에 더이상 메이토라는 이름을 쓰지는 않지만,, 그래도 이 개발 세계관에서는 여전히 토마토로 존재하니까요 (?) 저는 우아한 테크코스가 끝나갈 무렵, 봄봄 프로젝트 팀에 프론트엔드로 합류하게 되었습니다 ! 이미 4개월 동안 개발이 진행되고 있던 팀에 합류한다는 것,, 그것은 곧 도메인과 코드 컨텍스트, 컨벤션 등에 대해 모두 파악하고 바로 피처 개발에 들어가야 하는 상황이었습니다 🥲
...
그렇게 합류한지 두달이 된 지금 ! 저는 컨벤션을 아주 잘 지키고 있을까요? 안타깝게도,, 한번씩 까먹어서 리뷰에서 피드백을 받기도 합니다.. 그래서 이 글의 제목 '디자인 컨벤션 좀 지켜!!' 는 곧 저에게 하는 말이었습니다 ㅎㅎ 라이브러리를 개발하게 된 계기가 바로 이러한 이유였고, 각설하고 본론으로 들어가보도록 하죠
개발 목적
새로운 컴포넌트를 만들 때 기존 디자인 시스템을 따르지 않는 경우, 경고를 통해 기존 디자인 시스템을 지키도록 보장하기 위함
V 1.
- styleLint 처럼 ‘npm run stylelint’ 의 명령어로 디자인 시스템을 지키지 않은 스타일 코드에 대해서 경고 예정
- Emotion 라이브러리 작성 및 기본 css에 대해서 대응 예정 (tailwind 나 다른 디자인 라이브러리는 이후버전에서)
- 경고 및 어떤 것으로 바꿔야할지 제안 예정
예시 룰(Emotion + css 기준)
- Color: #, rgb(), hsl() 사용 금지 → theme.colors.*로 제안
- Typography: font-size: 14px 금지 → theme.typography.*
- Spacing: margin: 8px 금지 → theme.spacing.*
- Border radius / shadow: 하드코딩 금지 → theme.radius., theme.shadow

🤔 여기서 짚고가는 가장 큰 고민,
팀 마다, 프로젝트 마다 디자인 시스템 파일 형식도 다르고,, 라이브러리도 다르고,, 디자인 시스템을 정해둔 범위도 다를텐데 어떻게 대응하지?
였습니다. 사실 개인 프로젝트 차원에서 빠르게 적용해보기 위해 만들려면 저 범용성을 다 챙기기엔 현실적으로 불가능합니다. stylelint를 하나 만드는 것과도 같은 규모인 셈이죠,, 그래서 우선 버전 1은 제가 속해있는 아인슈타임 팀에 적용 가능하도록 만드는 것이었습니다.
아인슈타임에서 디자인 시스템을 만들었기 때문에 구조를 가장 잘 파악하고 있기도 하고, 만들면서 어떤 것들이 필요할지를 고민해보기 위함이었습니다.
우선 저희 아인슈타임은 emotion/styled를 사용중이고, 디자인 시스템의 경우 theme.ts 라는 파일에 정해두고 ThemeProvider를 통해서 각 컴포넌트에서 theme을 사용하는 방식입니다.
theme.ts 파일 내부를 뜯어보면 ,, 아래와 같은 형식입니다!
export type Theme = typeof LIGHT_THEME;
export type ColorsKey = keyof typeof LIGHT_THEME.colors;
export type TypographyKey = keyof typeof LIGHT_THEME.typography;
export const LIGHT_THEME = {
colors: {
background: '#FFFFFF',
text: '#000000',
primary: '#8052E1',
secondary: '#E2A86A',
// ....
},
typography: {
h1: {
fontSize: '2.25rem',
fontWeight: 'bold',
},
h2: {
fontSize: '1.5rem',
fontWeight: 'bold',
},
mobileCaption: {
fontSize: '1.25rem',
fontWeight: 'bold',
},
},
// ....
};
결론적으로 제가 하고 싶은 것은 제가 만든 라이브러리를 사용할 떄 config 설정 파일에 이 theme.ts라는 파일에 대한 경로를 삽입해주면 알아서 파싱해서 디자인 시스템에 대한 맵을 만들어주는 것입니다.(물론 파싱하는 로직이 제가 만들 라이브러리에 들어가겠죠?) 그 맵을 바탕으로 모든 스타일 파일을 읽어서 규칙에 어긋난 것은 없는지 사전에 검증을 하는 lint의 역할을 하는 것이었죠
🤔 왜 stylelint를 기반으로 만들기로 했을까?
처음에는 이 라이브러리를 완전히 독립적인 도구로 만들 수도 있었을 것 같습니다.
예를 들어, styled-components / emotion 코드를 직접 파싱하고, CSS AST를 만들고, 파일 시스템을 순회하면서
에러 포맷팅과 출력까지 전부 직접 구현하는 방식 말이죠.
하지만 곰곰이 생각해보니, 이건 사실상 “stylelint를 하나 더 만드는 것” 과 크게 다르지 않은 일이었습니다.
제가 만들고 싶은 건 “새로운 lint 도구” 가 아니라,
“이미 잘 만들어진 lint 생태계 위에 디자인 시스템 규칙만 얹는 것” 이었기 때문입니다.
stylelint는 이미,
CSS 파싱 (PostCSS 기반), emotion / styled-components 문법 파싱 (postcss-styled-syntax)
파일 탐색, ignore 처리, 에디터 연동 (VSCode extension 등) 등등 ...
같은 정적 분석 도구로서 필요한 인프라를 전부 갖추고 있는 상태였습니다.
즉, 제가 직접 reporter와 parser, CLI를 만드는 대신 규칙만 작성하면 되는 구조위에 올라타는 쪽이 훨씬 현실적인 선택이었습니다.
그러면 이제 한 가지 질문이 생깁니다.
“stylelint는 도대체 언제 이 설정 파일을 읽고, 언제 이 규칙들을 적용하는 걸까?”
이걸 이해하지 못하면, 제가 만들 플러그인이 어디에 끼어들어야 하는지도 감이 오지 않는데 ,, 그래서 먼저 stylelint의 동작 흐름부터 간단히 살펴볼 필요가 있었습니다.
🤔 그러면 stylelint는 어느 시점에 이 파일을 읽고 규칙을 적용시킬까?
실제로 stylelint는 아래와 같은 순서로 동작합니다.
1. npx stylelint ... 를 실행하면, 가장 먼저 stylelint.config.js (또는 .stylelintrc) 를 탐색합니다.
2. 설정 파일에 customSyntax: "postcss-styled-syntax" 가 있다면,(styled.div 같은 코드도 내부적으로는 전부 CSS AST가 됩니다)
→ “아, 이 프로젝트는 styled-components / emotion 문법이구나” 하고 판단한 뒤, 해당 문법을 CSS AST로 변환합니다.
3. 그 다음 plugins 에 등록된 플러그인들을 로드하고, rules 에 명시된 룰들을 stylelint 내부 룰 레지스트리에 등록합니다.
이러한 과정을 통해 stylelint를 기반으로 한 저의 라이브러리가 동작하는 것이죠 ! 다음편 블로그에서는 제가 만들었던 버전 1의 규칙을 살펴보고, 어떤 로직을 가지고 있는지 설명해보도록 하겠습니다 -!
'궁금증 해결소' 카테고리의 다른 글
| [라이브러리 개발 일기] Stylelint 가 어떻게 하드코딩을 막을까? (0) | 2026.03.21 |
|---|---|
| ‘깨져도 괜찮은 웹’을 만드는 법 – 우아한 낮춤 (0) | 2025.10.20 |
| 프론트 개발자가 바라보는 멱등성🔥 (0) | 2025.10.17 |
| TroubleShoot Ep.1 험난했던 빌드 오류 해결의 과정.. (2) | 2025.01.22 |
| [자바스크립트] 정적 메서드, 인스턴스 메서드 뭐가 달라? (3) | 2024.11.30 |