피그마 파일을 예쁜 그림 모음으로만 두면 색과 간격이 화면마다 제각각 흩어집니다. 저는 피그마를 그림판이 아니라 코드가 참조할 명세서, 즉 단일 진실 소스로 봅니다. 그 관점이 CSS에서 어떻게 드러나는지 값 하나부터 보여드리겠습니다.
61.1 피그마는 그림판이 아니라 명세서
디자인 툴이 뱉는 값을 화면마다 손으로 옮겨 적으면, 비슷하지만 서로 다른 값이 슬금슬금 늘어납니다. 아래 세 색은 다 파란색 같지만 실은 전부 다릅니다.
.card-title { color: #2563eb; }
.link { color: #2564ec; }
.badge { color: #1d4fd7; }
눈으로는 구분이 안 되지만 브랜드 색을 바꾸는 날, 이 세 자리를 따로따로 찾아 고쳐야 합니다. 값이 흩어질수록 수정은 술래잡기가 됩니다. 그래서 저는 화면을 그리기 전에, 이 파일이 나중에 코드로 옮겨질 명세서라는 사실을 먼저 떠올립니다.
같은 값을 여러 화면이 함께 쓴다면, 그 값에는 이름이 필요합니다. 이름 없는 숫자는 복사되고, 이름 붙은 값은 참조됩니다. 복사된 숫자는 언젠가 서로 어긋나지만, 참조된 값은 늘 하나입니다. 피그마의 스타일과 컴포넌트가 하는 일이 바로 이 참조입니다.
61.2 흩뿌린 값 대 단일 소스
같은 값이 여러 규칙에 반복되면, 먼저 한곳에 정의하고 나머지는 그것을 가리키게 만듭니다. 나쁜 예부터 보겠습니다.
.btn {
background: #2563eb;
padding: 12px 16px;
}
.tag {
background: #2563eb;
padding: 12px 16px;
}
같은 파랑과 같은 여백이 두 번 적혀 있습니다. 이제 CSS 변수로 진실을 한 곳에 모읍니다.
:root {
--brand: #2563eb;
--pad-y: 12px;
--pad-x: 16px;
}
.btn {
background: var(--brand);
padding: var(--pad-y) var(--pad-x);
}
.tag {
background: var(--brand);
padding: var(--pad-y) var(--pad-x);
}
이제 브랜드 색을 바꾸려면 --brand 한 줄만 고치면 됩니다. 피그마에서 색 스타일 하나를 고치면 연결된 모든 화면이 함께 바뀌는 것과 똑같은 이치입니다.
61.3 색과 간격을 토큰으로 모으기
피그마의 색 스타일과 간격 규칙은 CSS에서 토큰, 즉 이름 붙은 변수 묶음이 됩니다. 자주 쓰는 값을 계단처럼 정리해 둡니다.
:root {
--space-1: 4px;
--space-2: 8px;
--space-3: 16px;
--space-4: 24px;
--color-text: #1f2937;
--color-muted: #6b7280;
}
본문 화면에서는 이 이름만 불러다 씁니다. 숫자 대신 뜻이 남습니다.
.card {
padding: var(--space-3);
color: var(--color-text);
}
.card .desc {
margin-top: var(--space-2);
color: var(--color-muted);
}
16px 대신 var(--space-3) 라고 적으면, 이 여백이 어떤 등급의 간격인지가 코드에 그대로 남습니다. 나중에 간격 체계를 조정할 때도 뿌리 한 곳만 손보면 됩니다.
61.4 개발 모드가 뽑아준 CSS 다시 쓰기
피그마 개발 모드는 요소를 고르면 CSS를 대신 뽑아 줍니다. 다만 그 결과는 대개 숫자가 박힌 날것이라, 참고값으로만 받고 관계형으로 다시 씁니다. 아래가 툴이 뱉어 준 원본입니다.
.hero {
padding-top: 24px;
padding-bottom: 24px;
padding-left: 16px;
padding-right: 16px;
background: #2563eb;
}
값은 맞지만 왜 24px이고 왜 이 파랑인지가 사라져 있습니다. 우리가 정한 토큰으로 바꿔 뜻을 되살립니다.
.hero {
padding-block: var(--space-4);
padding-inline: var(--space-3);
background: var(--brand);
}
줄 수도 줄었고, 다른 요소와 같은 언어를 쓰게 되었습니다. 개발 모드의 출력은 정답이 아니라 초안입니다. 그대로 붙여 넣지 않고 토큰으로 옮기는 이 한 단계가, 흩어진 화면들을 하나의 소스로 묶어 줍니다.
61.5 글자 크기와 컴포넌트도 같은 방식으로
토큰은 색과 간격만의 이야기가 아닙니다. 글자 크기, 모서리 둥글기, 그림자까지 같은 방식으로 이름을 붙여 둡니다. 피그마의 텍스트 스타일이 CSS에서는 이렇게 옮겨집니다.
:root {
--text-sm: 14px;
--text-base: 16px;
--text-lg: 20px;
--radius: 8px;
--shadow-card: 0 1px 3px rgba(0, 0, 0, 0.1);
}
이렇게 모아 두면 컴포넌트 하나는 토큰만 조립해 만들어집니다. 날숫자가 한 곳도 보이지 않는 카드입니다.
.card {
padding: var(--space-3);
border-radius: var(--radius);
box-shadow: var(--shadow-card);
}
.card h3 {
font-size: var(--text-lg);
color: var(--color-text);
}
.card p {
font-size: var(--text-base);
color: var(--color-muted);
}
이 카드를 읽으면 어떤 등급의 글자와 여백을 쓰는지가 그대로 보입니다. 피그마에서 컴포넌트가 스타일을 물려받듯, CSS에서도 규칙이 토큰을 물려받는 셈이지요. 화면이 백 개로 늘어도 진실은 여전히 :root 한 곳에 있습니다.
61.6 정리
피그마를 명세서로 대한다는 말은, 코드에서도 값을 한곳에 모아 두고 나머지가 그것을 참조하게 만든다는 뜻입니다. 마지막으로 토큰을 실제로 갈아 끼우는 장면을 봅니다.
:root {
--brand: #2563eb;
}
/* 리브랜딩: 이 한 줄만 교체 */
:root {
--brand: #16a34a;
}
버튼도 태그도 히어로도 새 색을 따라옵니다. 값을 흩뿌리면 수정이 술래잡기가 되지만, 단일 소스로 모으면 한 줄이 온 화면을 움직입니다.
여기서 한 걸음 더 나가면, 다크 모드처럼 상황이 바뀔 때도 토큰만 갈아 끼워 대응할 수 있습니다. 규칙은 그대로 두고 값의 출처만 바꾸는 것이지요.
:root {
--color-text: #1f2937;
--color-muted: #6b7280;
}
@media (prefers-color-scheme: dark) {
:root {
--color-text: #f9fafb;
--color-muted: #9ca3af;
}
}
카드도 히어로도 코드를 한 줄 고치지 않았는데 어두운 화면에 맞춰 색이 바뀝니다. 피그마를 명세서로 대하고 그 명세를 토큰으로 옮겨 두면, 나중의 큰 변화도 뿌리 한 곳에서 조용히 처리됩니다. 흩어진 값은 짐이 되고, 모인 값은 지렛대가 됩니다.