같은 규칙이 화면마다 반복되면 사용자는 한 번 배운 방식을 계속 씁니다. 값을 흩뿌리는 대신 변수와 클래스로 묶어 두면 일관성은 저절로 따라옵니다. 아래 코드는 그대로 복사해 확인할 수 있습니다.

06.1 값을 토큰으로 묶기

색과 간격, 반경을 각 요소에 직접 적으면 나중에 손댈 곳이 수십 군데로 흩어집니다. 한 곳에 변수로 모아 둡니다.


:root {
--color-brand: #2563eb;
--radius: 10px;
--space: 16px;
--border: 1px solid #e5e7eb;
}
.card {
border: var(--border);
border-radius: var(--radius);
padding: var(--space);
}


디자인 토큰이라 부르는 이 변수들을 한 번 정해 두면 모든 카드가 같은 반경과 여백을 공유합니다. 브랜드 색을 바꿀 때도 --color-brand 한 줄만 고치면 전 화면이 따라옵니다. 값을 여기저기 직접 박아 두었다면 색 하나 바꾸는 데도 파일을 뒤지며 빠짐없이 찾아 고쳐야 하지만, 토큰으로 모아 두면 그 수고가 통째로 사라집니다.

06.2 버튼을 한 규칙으로 통일

버튼마다 색과 패딩을 새로 적으면 화면마다 미묘하게 다른 버튼이 생깁니다. 공통 뼈대를 base 클래스에 몰아 둡니다.


.btn {
padding: 10px 18px;
border-radius: var(--radius);
font-weight: 600;
cursor: pointer;
}
.btn-primary {
background: var(--color-brand);
color: #fff;
}


모든 버튼이 btn의 패딩과 반경을 물려받고, 변형만 뒤에 덧붙입니다. 새 버튼을 만들 때도 btn 하나만 붙이면 나머지와 자동으로 결이 맞습니다.

06.3 반복되는 목록에 같은 리듬

목록 항목마다 간격이 조금씩 다르면 눈이 흔들립니다. 같은 규칙을 형제 전체에 한 번에 겁니다.


.feed > * + * {
margin-top: var(--space);
}
.feed .item {
display: flex;
gap: 12px;
align-items: center;
}


형제 사이에만 같은 위 여백을 주니 항목이 몇 개로 늘어도 리듬이 흐트러지지 않습니다. 각 항목 안의 배치도 같은 flex 규칙을 공유해 어느 줄이나 같은 모양으로 읽힙니다.

06.4 상태 표시를 한 벌로

성공과 경고, 정보 배지를 그때그때 다른 색으로 칠하면 사용자가 의미를 새로 배워야 합니다. 한 세트로 정해 반복합니다.


.badge {
padding: 2px 8px;
border-radius: 999px;
font-size: 12px;
}
.badge-ok { background: #dcfce7; color: #166534; }
.badge-warn { background: #fef9c3; color: #854d0e; }


배지의 모양은 badge가 통일하고 의미별 색만 갈아 끼웁니다. 초록은 늘 정상, 노랑은 늘 주의라는 약속이 화면마다 지켜지면 사용자는 색만 보고도 상태를 압니다.

06.5 간격 체계를 반복하기

간격 값을 매번 눈대중으로 정하면 화면마다 리듬이 어긋납니다. 몇 배씩 오르는 단계를 변수로 두고 골라 씁니다.


:root {
--s1: 4px;
--s2: 8px;
--s3: 16px;
--s4: 32px;
}
.section { padding: var(--s4) var(--s3); }
.field { margin-bottom: var(--s3); }
.tag + .tag { margin-left: var(--s2); }


같은 눈금에서 간격을 꺼내 쓰면 서로 다른 영역도 한 리듬으로 묶입니다. 임의의 13px, 19px 같은 값이 섞이지 않으니 화면 전체가 한 사람 손에서 나온 듯 보입니다.

06.6 폰트 규칙을 한 곳에서

글자 크기와 줄 간격을 요소마다 새로 적으면 제목마다 톤이 달라집니다. 타이포 규칙도 변수와 공통 클래스로 모읍니다.


:root {
--font-body: 16px/1.7 system-ui, sans-serif;
}
body { font: var(--font-body); }
.h-title {
font-size: 24px;
font-weight: 700;
line-height: 1.3;
}


본문 폰트를 한 줄로 정의해 두면 모든 문단이 같은 크기와 줄 간격을 공유합니다. 제목은 h-title 하나로 어느 화면에서나 같은 무게로 등장합니다. 글자 규칙이 흔들리지 않으면 페이지를 넘겨도 같은 목소리로 말하는 인상을 주어, 사용자는 매번 새 화면에 적응하는 대신 읽던 흐름을 이어 갑니다.

06.7 예외는 규칙 위에 얹기

일관성을 지킨다고 예외를 아예 없앨 수는 없습니다. 다만 예외도 공통 규칙 위에 최소한만 덧대야 관리가 됩니다.


.card { padding: var(--space); }
.card.compact {
padding: var(--s2);
}
.card.flush {
padding: 0;
}


기본 카드는 공통 여백을 쓰고, 촘촘한 변형과 여백 없는 변형만 클래스를 덧붙여 조절합니다. 예외를 새 규칙으로 흩뿌리지 않고 기존 토큰 안에서 처리하니 결이 흐트러지지 않습니다.

06.8 다크 모드도 같은 토큰으로

어두운 화면을 위해 색을 통째로 다시 적으면 두 벌을 따로 관리하게 됩니다. 토큰 값만 바꿔 끼우면 규칙은 그대로 둘 수 있습니다.


@media (prefers-color-scheme: dark) {
:root {
--color-brand: #60a5fa;
--border: 1px solid #374151;
}
}


카드와 버튼의 코드는 손대지 않고 변수 값만 어두운 톤으로 바꿉니다. 규칙을 한 번만 짜 두면 밝은 화면과 어두운 화면이 같은 뼈대를 나눠 쓰니 어긋날 일이 없습니다.

06.9 조각을 하나로 모으기

지금까지의 토큰과 클래스를 한 컴포넌트에 얹으면 이렇게 맞물립니다. 값은 전부 변수에서 나오니 마크업엔 숫자가 거의 없습니다.


<div class="card">
<span class="badge badge-ok">정상</span>
<h3 class="h-title">서버 상태</h3>
<button class="btn btn-primary">새로고침</button>
</div>


카드의 여백과 반경, 배지의 색, 버튼의 무게가 전부 공용 토큰에서 나옵니다. 다른 화면에 같은 클래스를 붙이면 똑같은 결의 컴포넌트가 곧바로 재현됩니다. 반복은 지루함이 아니라 사용자가 매번 새로 배우지 않아도 되는 편안함입니다.

06.10 일관성 정리

일관성은 취향을 억누르는 규제가 아니라 판단을 줄여 주는 장치입니다. 색과 간격, 폰트, 컴포넌트를 토큰과 공통 클래스로 한 번 묶어 두면, 새 화면을 만들 때마다 무슨 값을 쓸지 고민할 필요가 없습니다. 규칙이 반복될수록 사용자는 빨리 익숙해지고, 만드는 쪽은 고칠 곳이 한 군데로 줄어듭니다.