화면 로컬 스타일 네이밍 컨벤션 v2.4
목차
- 목표와 철학
- 규칙 TL;DR (바로 쓰는 요약)
- 문법(Syntax) — 스코프/슬러그/블록/엘리먼트/모디파이어
- 세그먼트 표기법 — camelCase 원칙
- 어휘 세트 — Block / Element / Modifier
- Modifier 정책 — “기본 1, 최대 2”와 적용 기준
- 예시 — Before/After, 실전 패턴
- 정규식/린팅 — 자동검증 규칙
- 리뷰 체크리스트 — PR용
- 마이그레이션 가이드 — 기존 이름 치환 원칙
- FAQ — 왜 slug가 선택? 왜 모디파이어를 묶어 쓰나?
1) 목표와 철학
- 단순·일관: 누구나 바로 이해·검색 가능해야 합니다.
- 의도 중심: container/wrapper 같은 모호어 금지, “왜 묶였는지”를 드러내는 이름만.
- BEM 간결 차용: Block/Element/Modifier 개념은 살리되, 언더바만으로 구현.
2) 규칙 TL;DR
형식
styles.<scope>_<slug?>_<block>[_<element>] [__<modifier>[_<modifier>]]스코프(scope)
scr= 화면 로컬w= 위젯 로컬ui= 전역 UI 컴포넌트 (혼동 위험 때문에u금지)
세그먼트 내부 표기: camelCase (예:
headerRow,footerRow,focusRing)모디파이어 수: 기본 1개, 최대 2개(서로 다른 축일 때만)
3) 문법(Syntax)
styles.<scope>_<slug?>_<block>
[ _<element> ]
[ __<modifier>[_<modifier>] ]
<scope>:scr|w|ui(필수)<slug>: 2–4자 화면/도메인 축약(선택, 화면 로컬에서만 권장)<block>: 역할(필수, camelCase)<element>: 블록 내부 단위(선택, 0~1개 권장, camelCase)__<modifier>: 변형/상태(선택, 1개 기본/최대 2개, camelCase)
모디파이어는 항상 한 번의
__로 블록을 열고, 그 안에서_로 이어붙입니다. 예)__dense/__dense_android__를 여러 번 반복하지 않습니다.
4) 세그먼트 표기법 — camelCase
- 세그먼트 내부(블록/엘리먼트/모디파이어)는 camelCase.
예)
nav,headerRow,footerRow,metaRow,focusRing,gapSm - 숫자·치수 금지:
_gap10같은 이름 금지. 값은 토큰(t.spacing.sm)으로.
5) 어휘 세트
Block (필수, 1개 / “역할”)
- 내비/행동/입력:
nav,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
container/wrapper 사용 금지. 왜 묶였는지(역할)를 써야 합니다.
Element (선택, 0~1개 권장 / “구조·위치”)
- 배치/구조:
row,column,stack,cluster - 스크롤 컨테이너:
strip(가로 contentContainerStyle),content(세로) - 위치/라인:
headerRow,footerRow,lead,trail,aside,main - 항목:
item,metaRow…
Modifier (선택, 기본 1 · 최대 2)
- 밀도/여백:
dense,compact,spacious,padded,gapSm/md/lg - 시각:
muted,elevated,outlined,seamless - 동작:
sticky,scrollable,collapsible - 플랫폼/방향:
ios,android,web,rtl
조합 원칙: 서로 다른 축만 조합. 예)
dense + android(밀도+플랫폼) ✅ /dense + compact(둘 다 밀도) ❌
6) Modifier 정책 — “기본 1, 최대 2” 왜?
기본 1개: 이름 길이/복잡성·검색성을 모두 고려한 기본값.
최대 2개 허용: 아주 드물게, 서로 다른 축이 동시에 필요할 때만.
- 예)
__dense_android,__sticky_rtl
- 예)
금지 케이스
- 같은 축 반복:
__dense_compact(둘 다 밀도) - 3개 이상:
__dense_muted_sticky→ 개별 스타일 분리/조합으로 해결
- 같은 축 반복:
우선순위(표기 순서 권장):
density/spacing → visual → behavior → platform/dir- 예)
__compact_sticky_android
- 예)
7) 예시
7.1 기존 코드 리팩터링
// Before
scr_forums_section_nav_short
scr_forums_section_nav
scr_forums_group_nav_strip
// After (slug=frm)
styles.scr_frm_nav__compact // “short”의 의도를 compact로
styles.scr_frm_nav // 기본 네비 묶음
styles.scr_frm_nav_strip__dense // 가로 스크롤(contentContainerStyle)
7.2 헤더/CTA/푸터
styles.w_header_actions_row // 위젯 로컬
styles.scr_frm_actions_headerRow // 화면 로컬 헤더 액션 줄
styles.scr_frm_actions_footerRow__sticky_ios // 하단 고정 CTA(iOS)
7.3 검색/필터
styles.scr_srch_filters_strip__dense
styles.scr_srch_form_column__padded
7.4 두 개 모디파이어(서로 다른 축 조합)
styles.scr_frm_nav_strip__dense_android // 밀도 + 플랫폼
styles.scr_frm_actions_footerRow__sticky_rtl // 동작 + 방향
8) 정규식/린팅
허용 패턴(슬러그 선택/모디파이어 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> (optional)
(?:__[a-z][a-zA-Z0-9]*(?:_[a-z][a-zA-Z0-9]*){0,1})?$ # __<modifier>[_<modifier>] (0~2)
- 예:
scr_frm_nav_strip__dense,scr_srch_form_column__padded,w_header_actions_row,ui_button_root
금지 룰(별도 검사):
container|wrapper포함_gap[0-9]+등 숫자 변형- 접두사
u_(→ui_만 허용)
9) 리뷰 체크리스트 (PR용)
-
scr|w|ui스코프 적절히 사용? - (scr일 때) 슬러그 필요하면 2–4자로 붙였는가?
- Block이 역할을 명확히 드러내는가? (container/wrapper 금지)
- Element는 필요한 경우에만 1개 이내 사용했는가?
- Modifier는
__블록에, 1개 기본/2개 이내인가? - 세그먼트 내부는 camelCase인가?
- 숫자/매직넘버는 이름에 없고 값은 토큰으로?
-
strip은 가로 contentContainerStyle 전용으로 썼는가?
10) 마이그레이션 가이드
*_container/*_wrapper→ 역할형 Block으로:nav,actions,content등*_item(컨테이너 의미로 오용) →strip(가로) /content(세로)short/long→__compact/__spacious- 숫자 접미 →
__gapSm/md/lg+ 실제 값은t.spacing.* - 기존 다중 수식 → 최대 2개만 남기고 나머지는 스타일 분리
11) FAQ
Q. 모디파이어는 왜 여러 개가 필요한가요? A. 대부분 1개면 충분합니다. 다만 서로 다른 축이 동시에 요구될 때(예: “compact” + “android”)가 드물게 존재합니다. 이때만 2개를 허용합니다. 그 이상은 유지보수 비용만 커집니다.
Q. slug는 항상 붙여야 하나요?
A. 화면이 적고 충돌 우려가 없으면 생략 가능. 다만 장기적으로는 scr_<slug>_…가 전역 검색·리팩터에 유리합니다(권장).
Q. 왜 camelCase인가요? A. 언더바는 세그먼트 경계·모디파이어 연결 전용으로 두고, 내부 단어는 camelCase로 읽기 좋게 유지하기 위함입니다.