posts

스타일 네이밍 컨벤션

Oct 13, 2025 updated Oct 13, 2025 architectureconventionsexporeact-nativestyling

아래 문서는 그동안 논의·개선한 내용을 처음부터 끝까지 정리한 최종 보고서입니다. React Native + Unistyles v3 환경을 전제로 하며, 하이픈(-)은 사용하지 않고 언더바(_)만 사용, BEM 개념을 간결하게 차용한 스타일 네이밍 규칙을 확정합니다.


화면 로컬 스타일 네이밍 컨벤션 — 최종 보고서 (v2.4)

목차

  1. 배경 및 목표
  2. 변천사 요약(v1 → v2.4)
  3. 핵심 결론(TL;DR)
  4. 최종 문법(Syntax)
  5. 표기 원칙(camelCase & _/__ 경계)
  6. 스코프/슬러그/블록/엘리먼트/모디파이어 정의
  7. 어휘 세트(권장 단어장)
  8. Modifier 정책(“기본 1, 최대 2”)과 결정 트리
  9. 적용 예시(실전 코드 치환)
  10. Link/Button 등 자식 요소 스타일링 원칙
  11. 정규식/린팅(자동 검증)
  12. 리뷰 체크리스트(PR용)
  13. 마이그레이션 가이드(치환 원칙)
  14. 의사결정 근거(왜 level/role을 단순화했는가)
  15. 부록: 패턴 스니펫/팀 운영 팁

1) 배경 및 목표

  • 다양한 화면에서 로컬 스타일 키가 중구난방으로 늘어나 검색·리뷰·유지보수가 어려웠습니다.
  • 목표는 짧고 일관적이며, 키만 봐도 “어디/무엇/어떻게”를 파악할 수 있는 의도 중심 네이밍입니다.
  • RN 제약(하이픈 사용 곤란)과 Unistyles v3 사용 방식을 반영해 현실적 규칙을 확정합니다.

2) 버전 요약 (v1 → v2.4)

v1 (초기안)

  • 문법: scr_<level>_<role>[_position][_layout][_modifier]

  • 문제:

    • level(page/section/block/…)·role 조합이 장황해지고 판단 비용↑
    • 화면이 늘수록 scr_section_* 검색이 충돌 (구체성이 낮음)

v1.1~v1.3

  • 슬러그(slug) 도입: scr_<slug>_…로 검색 충돌 완화
  • strip(가로 스크롤 contentContainerStyle 전용) 용어 확정
  • Modifier 분리 아이디어 등장(가독성·정규식 분리를 위해)

v2.0

  • BEM 개념 간결 차용: Block/Element/Modifier
  • level 제거 시도 → 이름 단순화·판단 분기 축소

v2.2

  • RN 제약 반영: 언더바 전용 규칙으로 확정
  • 스코프 접두사 확정: scr_(화면), w_(위젯), ui_(전역)

v2.3

  • 세그먼트 내부를 camelCase로, 세그먼트 경계는 _, **모디파이어 블록 시작은 __**로 확정
  • 슬러그는 선택(화면 많을수록 권장)

v2.4 (최종)

  • Modifier 정책을 **“기본 1개, 최대 2개(서로 다른 축일 때만)”**로 확정
  • Element는 0~1개 권장(element of element 금지)
  • container/wrapper 금지, 역할을 드러내는 block 사용

3) TL;DR

  • 문법: styles.<scope>_<slug?>_<block>[_<element>] [__<modifier>[_<modifier>]]
  • 스코프: scr=화면 로컬 / w=위젯 로컬 / ui=전역 UI
  • 세그먼트 내부 표기: camelCase (경계는 _ / modifier 블록 시작만 __)
  • Modifier 수: 기본 1개, 예외적으로 2개까지(서로 다른 축일 때만)

4) 문법

styles.<scope>_<slug?>_<block>
       [ _<element> ]
       [ __<modifier>[_<modifier>] ]
  • <scope>: scr | w | ui (필수)
  • <slug>: 2~4자 화면/도메인 축약(선택, 화면 로컬에서 권장)
  • <block>: 역할 중심 명명(필수)
  • <element>: 블록 내부 하위 단위(선택, 0~1개 권장)
  • __<modifier>: 변형/상태(선택, 1개 기본/최대 2개)

5) 표기 원칙 (camelCase & _/__ 경계)

  • 세그먼트 내부( block / element / modifier )는 camelCase: navQuick, headerRow, metaRow, gapSm, focusRing

  • 세그먼트 경계: _

  • 모디파이어 블록 시작: __ (딱 1번)

    • 예) __compact, __dense_android
    • __를 반복하지 않습니다.

6) 스코프/슬러그/블록/엘리먼트/모디파이어 정의

  • Scope

    • scr_: 화면 로컬(파일·도메인 많을수록 slug 권장)
    • w_: 재사용 위젯(파일 문맥상 slug 불필요)
    • ui_: 전역 UI(디자인시스템 레벨)
  • Slug

    • 2~4자 축약(자음 중심): forums→frm, profile→prf, search→srch
    • 충돌 시 1자 추가: forum-home→frmh, forum-post→frmp
    • screen-slugs.ts로 팀 공유 권장
  • Block

    • container/wrapper 금지, 왜 묶였는지(의도/역할) 를 드러낼 것
    • 예) nav, navQuick, actions, form, content, list, filters
  • Element (0~1개 권장)

    • 구조/위치/스크롤 컨테이너: row, column, stack, strip, content, headerRow, footerRow, item, metaRow
    • element of element 금지 (체인 방지)
  • Modifier (기본 1, 최대 2)

    • 밀도/여백: compact, dense, spacious, padded, gapSm/md/lg
    • 시각: muted, elevated, outlined, seamless
    • 동작: sticky, scrollable, collapsible
    • 플랫폼/방향: ios, android, web, rtl

7) 어휘 세트(권장 단어장)

  • 내비/행동/입력: nav, navQuick, actions, form, toolbar
  • 콘텐츠/미디어: content, media
  • 목록/표: list, grid, table
  • 탐색 보조: tabs, breadcrumbs, filters, sort, pagination
  • 상태/피드백: status, feedback, loading, empty
  • 오버레이/도구: dialog, sheet, menu, popover, tooltip
  • 시각화: carousel, map, chart
  • Element: row, column, stack, cluster, strip, content, headerRow, footerRow, item, metaRow

8) Modifier 정책과 결정 트리

정책

  • 기본 1개

  • 최대 2개(단, 서로 다른 축일 때만)

    • 예) __compact_android, __sticky_rtl
    • 금지: __compact_dense(둘 다 밀도), __dense_muted_sticky(3개↑)

결정 트리

  1. 변형이 정말 필요한가?
  • 컴포넌트 변형(variants)로 해결 가능하면 거기서 해결.
  1. 로컬 레이아웃 보정인가?
  • 네 → modifier 1개로 충분한지 먼저 검토(__compact, __padded)
  1. 플랫폼/방향 등 다른 축이 추가 필요한가?
  • 네 → 1개 더 허용(__compact_android)
  • 아니오 → 1개 유지
  1. 3개 이상 필요?
  • 네 → 스타일 쪼개기 또는 컴포넌트 변형 재고

9) 적용 예시 (실전 코드 치환)

“바로가기(빠른 내비)” 섹션

// Before
styles.scr_forums_section_nav_short
styles.scr_forums_group_nav_strip

// After (slug=frm)
styles.scr_frm_navQuick                  // 섹션 전체
styles.scr_frm_navQuick_leadText         // 안내 텍스트
styles.scr_frm_navQuick_strip            // 가로 스크롤(contentContainerStyle)
styles.scr_frm_navQuick_strip__compact   // 밀도↑ 변형(필요 시)

헤더/CTA/푸 터

styles.w_header_actions_row                    // 위젯 로컬
styles.scr_frm_actions_headerRow               // 화면 로컬 헤더 액션 줄
styles.scr_frm_actions_footerRow__sticky_ios   // 하단 고정 CTA(iOS)

검색/필터

styles.scr_srch_filters_strip__dense
styles.scr_srch_form_column__padded

10) Link/Button 등 자식 요소 스타일링 원칙

  • element chain 금지: …_strip_link_button ×

  • 필요한 경우 형제 엘리먼트로 선언:

    • scr_frm_navQuick_link (링크 래퍼가 필요할 때만)
    • scr_frm_navQuick_button (버튼 로컬 레이아웃 보정)
    • 선택 상태 등 다른 축 하나 추가 시: scr_frm_navQuick_button__selected
  • 색/톤/타이포 등 컴포넌트 성격UiButton/UiText variants로 처리. 로컬 스타일은 레이아웃(간격/정렬/최소폭) 위주.


11) 정규식/린팅 (자동 검증)

허용 패턴(슬러그 선택, modifier 0~2개):

^(scr|w|ui)_[a-z0-9]{0,4}_[a-z][a-zA-Z0-9]*       # <scope>_<slug?>_<block>
(?:_[a-z][a-zA-Z0-9]*)?                           # _<element> (0~1)
(?:__[a-z][a-zA-Z0-9]*(?:_[a-z][a-zA-Z0-9]*){0,1})?$  # __<modifier>[_<modifier>] (0~2)

금지 룰(별도 검사)

  • container|wrapper 포함
  • _gap\d+ 등 숫자 변형
  • 접두사 u_(→ ui_만 허용)

12) 리뷰 체크리스트 (PR용)

  • scr|w|ui 스코프를 올바르게 사용했습니까?
  • (scr일 때) 슬러그가 필요한 화면이라면 2~4자 축약을 붙였습니까?
  • Block이 역할을 명확히 드러냅니까? (container/wrapper 금지)
  • Element는 필요한 경우에만 1개 이내 사용했습니까?
  • Modifier는 __ 블록에, **1개 기본/최대 2개(서로 다른 축)**입니까?
  • 세그먼트 내부는 camelCase입니까?
  • 숫자·매직넘버가 이름에 없고 값은 토큰으로 처리했습니까?
  • strip은 가로 contentContainerStyle 전용으로 썼습니까?

13) 마이그레이션 가이드

  1. *_container/*_wrapper역할형 Block으로 치환(nav, actions, content …)
  2. *_item이 컨테이너 의미일 때 → strip(가로)/content(세로)로 교정
  3. short/long__compact/__spacious
  4. 숫자 접미 제거 → __gapSm/md/lg + 실제 값은 t.spacing.*
  5. 다중 수식 → 최대 2개만 남기고 나머지는 스타일 분리 또는 variants로 이동

14) 의사결정

문제 인식

  • level(page/section/block/…)를 이름에 강제하면 판단 분기↑, 길이↑, 검색 중복↑
  • role은 필요하지만, level과 결합 시 冗長해지는 경향

대안 비교

  • A. level 유지: 의미는 정밀해지나, 실제 유지보수 시 장점 < 부담
  • B. level 제거, role만: 이름 짧아지고, 역할 중심으로 의도가 선명해짐

최종 채택

  • level 제거, role 중심 + slug + element(필요 시)
  • “구조적 깊이 표기”는 파일 구조·컴포넌트 트리로 충분히 드러남
  • 대신 **modifier 블록(__)**과 slug로 검색성·분류성을 보완

15) 부록: 패턴 스니펫/팀 운영 팁

VSCode 스니펫(예시)

  • scr_<slug>_<block>
  • scr_<slug>_<block>_<element>
  • scr_<slug>_<block>_<element>__<modifier>

슬러그 레지스트리

// screen-slugs.ts
export const SCREEN_SLUGS = {
	forums: 'frm',
	profile: 'prf',
	search: 'srch',
	// …
} as const;

운영 팁

  • 새 화면 추가 시 슬러그를 먼저 등록
  • PR 템플릿에 체크리스트 포함
  • ESLint + 정규식으로 금칙/허용 패턴 자동 검사
  • strip항상 가로 contentContainerStyle 용도로만 사용

결론

  • 본 컨벤션(v2.4)은 RN 제약을 지키며 BEM의 장점(경계·의도·확장성) 을 살립니다.
  • scope + (slug) + block + [element] + __modifier만으로 대부분의 화면을 짧고 명료하게 표현할 수 있습니다.
  • Modifier 1(최대 2), element 0~1, container/wrapper 금지, 토큰 기반 값 관리—이 네 가지 원칙으로 가독성·재현성·자동검증을 동시에 확보하십시오.