백엔드 개발자가 프론트엔드를 바라볼 때
1. 백엔드 개발자가 프론트엔드 CSS 테마를 바라볼 때
- "CSS/HTML도 아키텍처가 필요하다": 하드코딩된 색상 코드가 유발하는 스파게티 코드
- 백엔드의 객체 지향 및 재활용성 관점에서 접근하는 CSS 테마 시스템
- 핵심 요약: Class Selector와 CSS 변수를 조합한 확장 가능한 테마 구조 백엔드와 프론트엔드의 경계를 넘어 화면단 데이터 표현과 효율적인 CSS 관리를 고민하며 도달한 개인 견해입니다.
실무에서 프론트엔드 영역을 함께 다루다 보면, 화면에 데이터를 어떻게 배치하고 CSS를 어떻게 유지보수할지 깊은 고민에 빠지게 됩니다. 이때 레이아웃을 구조화된 섹션 단위로 나누어 재활용하고, CSS를 백엔드의 properties나 YAML 설정 파일처럼 Key-Value 형태의 변수로 관리할 수 있다는 점에 주목했습니다. React나 Vue 같은 현대적인 프레임워크가 등장한 배경도 이러한 컴포넌트 기반의 재활용성과 구조화에 있지만, 실제 내부 메커니즘을 명확히 이해하지 못하면 결국 화면마다 하드코딩된 원시 값(Primitive Value)을 중복해서 주입하는 레거시를 반복하게 됩니다.
이러한 한계를 극복하기 위해 CSS를 단순한 스타일 선언이 아닌, 백엔드에서 데이터베이스 타입을 전환하듯 테마(Theme) 단위로 동적 교체가 가능한 변수 체계에 대해 생각해보았습니다. 스타일의 물리적 수치를 정의하는 '원시 레이어(Primitive Layer)'와 값이 사용될 맥락과 의도를 담은 '의미론적 레이어(Semantic Layer)'의 2단계로 추상화하는 방식입니다. 이 구조를 도입하면 컴포넌트는 오직 의미론적 변수만 바라보게 되므로, 마치 설정 파일의 매핑을 바꾸듯 테마 변수 체계를 변경하는 것만으로 전체 UI의 톤앤매너를 안전하고 유연하게 전환할 수 있었습니다.
2. OOP 관점으로 해석하는 CSS 변수(Custom Properties)
-
인터페이스와 구현의 분리: 변수명(Interface)과 실제 색상값(Implementation) 정의하기
-
재활용성을 극대화하는 2단계 토큰 레이어 설계
-
Primitive Layer (원시 값:
-gray-100**,-blue-500**) -
Semantic Layer (의미론적 값:
-bg-main**,-text-primary**) -
백엔드의 환경 설정(Properties/YAML) 파일 관리와 CSS 변수 관리의 유사성
1) 디자인 토큰 2단계 레이어 설계
디자인 토큰을 Primitive(원시) 레이어와 Semantic(의미론적) 레이어로 나누어 관리하면, 스타일의 재활용성을 극대화하고 향후 디자인 시스템의 유지보수 비용을 획기적으로 줄일 수 있습니다.
- Primitive Layer (원시 레이어): 스타일의 가장 구체적인 물리적 값을 정의합니다. 색상명이나 숫자를 기반으로 명명하며, 시스템 전체에서 사용할 '원자(Atom)' 역할을 합니다.
- Semantic Layer (의미론적 레이어): 원시 토큰이 "어디에, 어떤 의도로 사용되는지" 의미를 부여하는 레이어입니다. 다크 모드 전환이나 브랜드 개편 시 이 레이어의 참조값만 변경하면 화면 전체에 반영됩니다.
2) 백엔드 환경 설정 관리와의 유사성
이러한 2단계 구조는 백엔드 개발에서 환경 설정(Properties 또는 YAML) 파일을 관리하는 방식과 매우 닮아 있습니다.
- Primitive ≒ 인프라 및 전역 환경 변수: 데이터베이스 호스트 주소나 포트 번호처럼 변하지 않는 고유한 물리적 값입니다.
- Semantic ≒ 애플리케이션 추상화 변수:
datasource.primary.url과 같이 애플리케이션 내부 로직에서 참조하는 논리적 이름입니다. 개발자는 실제 DB 주소가 로컬에서 스테이징, 운영 환경으로 바뀌더라도 코드 내부를 수정하지 않고 설정 파일의 매핑만 변경합니다. CSS 변수 설계 역시 이와 같습니다. 컴포넌트 코드는 Semantic 토큰만 바라보고, 디자인 테마가 바뀔 때는 Semantic 토큰이 가리키는 Primitive 토큰만 교체합니다.
3) 예시 코드
CSS 변수(Custom Properties)를 활용하여 2단계 레이어를 구현한 예시 코드입니다. 백엔드의 YAML 구조와 비교하기 쉽도록 주석을 포함했습니다.
토큰 정의 (CSS)
/* 백엔드의 application.yaml에서 전역 변수를 정의하는 것과 유사합니다. */
:root {
/* ==========================================================================
1. Primitive Layer (원시 값)
========================================================================== */
--primitive-gray-100: #f3f4f6;
--primitive-gray-900: #111827;
--primitive-blue-500: #3b82f6;
--primitive-blue-600: #2563eb;
/* ==========================================================================
2. Semantic Layer (의미론적 값) - 기본 라이트 모드
========================================================================== */
--bg-main: var(--primitive-gray-100);
--text-primary: var(--primitive-gray-900);
--button-accent: var(--primitive-blue-500);
--button-accent-hover: var(--primitive-blue-600);
}
/* 다크 모드 변환 시, Semantic 토큰이 바라보는 Primitive 토큰의 매핑만 바꿉니다. */
@media (prefers-color-scheme: dark) {
:root {
--bg-main: var(--primitive-gray-900);
--text-primary: var(--primitive-gray-100);
/* 다크모드에서는 액센트 색상을 조금 더 밝은 블루로 대체 가능 */
--button-accent: var(--primitive-blue-600);
}
}컴포넌트 적용 (HTML/CSS)
실제 UI 컴포넌트를 작성할 때는 구체적인 색상인 --primitive-blue-500을 절대 직접 쓰지 않고, 의미를 담고 있는 --button-accent를 사용합니다.
<div class="card">
<h1 class="title">디자인 토큰 시스템</h1>
<button class="btn-submit">확인</button>
</div>/* 컴포넌트 스타일링 */
.card {
/* 컴포넌트는 오직 Semantic 토큰만 참조합니다. */
background-color: var(--bg-main);
color: var(--text-primary);
padding: 24px;
border-radius: 8px;
}
.btn-submit {
background-color: var(--button-accent);
color: #ffffff;
border: none;
padding: 10px 20px;
cursor: pointer;
}
.btn-submit:hover {
background-color: var(--button-accent-hover);
}3. Class Selector 중심의 테마 스위칭 아키텍처
-
왜 속성(Attribute)이나 미디어 쿼리 대신
Class Selector를 중심에 두었는가? -
명시성과 제어의 용이성, 그리고 멀티 테마 확장성 고려
-
최상위 요소(
<body>또는#app)의 클래스 전환을 통한 하위 요소 스타일 일괄 제어 원리 -
단일 클래스 추가/제거로 전체 도메인의 테마가 바뀌는 결합도 낮추기 전략 수 많은 selector 중에서 class selector를 중점적으로 설계해야한다는 의견은 다음과 같은 이유 때문입니다.
화면의 특정 영역(div, grid)을 섹션 단위로 나누어 재활용하겠다는 접근 방식은, CSS 선택자 중 오직 class 선택자를 통해서만 구현되는 것이 조금 더 효과적일 수 있습니다. 페이지 내에서 단 하나의 고유한 요소에만 적용되는 id 선택자와 달리, class 선택자는 동일한 스타일 규격을 여러 컴포넌트에 반복해서 부여할 수 있어 높은 재활용성을 보장하기 때문입니다. 더불어 데이터베이스 타입을 바꾸듯 테마 단위로 스타일을 한 번에 전환하기 위해서도 class 기반의 설계가 필수적입니다. 여러 컴포넌트 군이 동일한 의미론적 규격(Key-Value)을 공유하고 있어야, 상위 레이어의 클래스나 테마 변수가 바뀔 때 하위 요소들이 유기적으로 함께 움직이게 됩니다. 결국 개별 요소를 고정하는 id 방식보다는, 컴포넌트 구조를 그룹화하여 유연하게 제어할 수 있는 class 단위의 접근 방식이 위에 고민했던 메커니즘과 가장 자연스럽게 맞물립니다.
댓글
GitHub 계정으로 의견이나 질문을 남길 수 있습니다.