Skip to content

13장 이름 짓기 ​

이름은 생김새가 아니라 책임을 말합니다. 같은 뜻에는 한 단어만 쓰고, 그 단어는 웹 표준·Tailwind의 말과 부딪히지 않게 고릅니다.

왜 필요한가 ​

Leysys에서는 코드의 대부분을 AI 에이전트가 씁니다. 같은 뜻의 단어가 둘이면 에이전트는 그때마다 다른 쪽을 고릅니다. 방향 클래스가 그랬습니다. -row·-col 계열 16종 이상과 -horizontal·-vertical 계열 6종이 시기마다 섞여 있었습니다. 위치 어휘는 start·end로 정했지만 그 결정이 컴포넌트 주석 한 줄에만 있었습니다. 그래서 에이전트가 문서에 남아 있던 leading·trailing을 정본으로 알고 복제했습니다. 이름 결정은 이름 규칙 문서와 결정 기록(ADR)에 적혀 있어야 같은 실수가 멈춥니다.

다섯 원칙 ​

원칙뜻예
EDS-first진영 접두를 붙입니다. MDS 어휘를 새로 만들 때는 EDS와 맞는지 먼저 봅니다.e-button, EButton, --e-button-radius
구조화이름을 축으로 나눕니다e-{component}-{size}, e-{component}-{color}-{weight}
일관화같은 뜻에는 같은 단어를 씁니다방향은 horizontal·vertical 하나
범용화위치·업무 영역의 단어를 컴포넌트 이름에 넣지 않습니다m-bottom-nav → m-navbar, vote-list 대신 list
글로벌화한국 시장에만 맞는 말을 피합니다「주민번호」 → national-id

클래스와 어휘 축 ​

html
<button class="e-button e-button-md e-button-primary-bold">저장</button>
  • 루트 클래스는 .e-{component} 하나입니다(-root를 붙이지 않음). 하위 요소는 -header·-item처럼 접미사로 구별하고, BEM의 __·-- 표기는 쓰지 않습니다.
  • 상태는 클래스 이름에 넣지 않습니다. :hover 같은 의사 클래스, ARIA 속성, primitive가 붙이는 data-*가 먼저입니다. 상태를 부를 때도 hover·focus·active를 쓰고 pressed·hovered 같은 말은 쓰지 않습니다.
  • 색의 강도(weight)와 형태(form) 어휘는 9장에서 다룹니다.

줄임말 금지 ​

금지정본
btnbutton
dialog-w-mde-dialog-width-md
--addon-square-h--e-addon-square-height
측정값 h=40 / w=72height=40 / width=72

예외는 표준이 이미 줄여 쓴 말뿐입니다. HTML 태그(nav, img, td), HTML 속성(src, href), CSS 속성·단위(bg, px, rem, dvh)가 여기에 해당합니다. Tailwind 유틸리티(w-32, p-4)도 외부 표준 어휘이므로 그대로 씁니다.

방향은 horizontal·vertical ​

컴포넌트 prop은 orientation: 'horizontal' | 'vertical', CSS modifier는 -horizontal·-vertical만 씁니다. shadcn/ui·Radix·Reka UI·Base UI 네 곳의 prop이 모두 이 어휘입니다. -row·-col 접미사는 폐지했습니다. 다만 그룹 전체의 방향이 아니라 그룹 안의 한 줄(item)을 뜻하는 이름은 유지합니다(m-key-value-row, e-calendar-grid-row).

위치는 start·end ​

아이콘·addon·slot의 좌우 위치는 start·end만 씁니다. leading·trailing을 쓰지 않는 이유는 둘입니다.

  • Tailwind에서 leading-*는 행간(line-height)입니다. 같은 코드에서 한 단어가 두 뜻을 갖게 됩니다.
  • CSS 논리 속성(inline-start, inline-end)이 웹 표준 어휘입니다. 오른쪽에서 왼쪽으로 쓰는 언어(RTL)에서도 저절로 맞습니다.

클래스(e-input-group-addon-inline-start), slot(#start·#end), prop(iconStart·iconEnd), 문서 서술까지 같은 규칙입니다. Nuxt UI의 #leading slot처럼 외부 API를 인용할 때만 원문을 둡니다.

쌍 클래스는 둘 다 정의 ​

방향·변형처럼 짝이 있는 modifier는 기본값과 같은 쪽도 정의합니다. base와 두 modifier로 된 3-class 패턴입니다.

css
/* e-field.css 요약 */
.e-field            { display: flex; flex-direction: column; } /* base는 세로 */
.e-field-horizontal { flex-direction: row; }
.e-field-vertical   { flex-direction: column; }                /* 기본과 같아도 정의 */

사람이나 에이전트가 어느 쪽 이름을 쓰든 동작하고, 나중에 기본값이 바뀌어도 화면이 깨지지 않습니다.

구조 컴포넌트의 이름 ​

화면의 뼈대를 이루는 구조 컴포넌트는 무엇을 소유하는지로 이름을 정합니다. 기준은 수명주기(lifecycle), 상태, 스크롤, 표면, 오버레이 가운데 어느 책임을 가지느냐입니다. 둥근 상자라서 Card, 옆에서 나온다고 Panel, 감싼다고 Wrapper라고 부르지 않습니다.

이름소유하는 것소유하지 않는 것
App·Shell실행 단위의 최상위 provider와 가장 높은 지속 경계페이지 안의 간격
Layout둘 이상의 지속 영역 배치저장, 열기·닫기, 포커스
Pagenavigation·본문·aside 영역 구성<main>, 폭·여백
Main문서에 하나뿐인 <main> landmark일반 본문 감싸기
PageBody머리글과 바닥글 사이의 본문(div)landmark
Group관련된 항목들의 의미 경계간격만 주는 감싸기
Panel모달이 아닌 지속 작업 영역Card의 모양, 열기·닫기, 포커스 가두기
Card관련 콘텐츠를 담는 경계 있는 표면앱 구조, 화면 스크롤
Container폭 제한, 가운데 정렬, 좌우 여백자식의 흐름, 표면
Stack·Grid바로 아래 자식의 1차원·2차원 흐름페이지의 의미
Dialog·Sheet임시 오버레이의 포커스와 닫기(Sheet는 가장자리에 붙은 Dialog)지속 영역
Drawer끌기(gesture)와 스냅의 수명주기Sheet의 시각적 별칭
  • Navbar는 위·아래 가로, Sidebar는 시작·끝 세로가 기본일 뿐입니다. 실제 방향과 위치는 orientation과 position으로 밝힙니다. 데스크톱에서 늘 보이는 내비게이션은 Sidebar이고, 모바일에서 잠깐 열리는 것은 실제 Sheet입니다. 지속 영역을 Sheet라고 부르지 않습니다.
  • Wrapper, Frame, Box, 수식어 없는 Surface는 새 공개 구조 이름으로 쓰지 않습니다. 책임을 말하지 않기 때문입니다. Wrapper는 framework adapter(Vue wrapper), 내부 helper, 기존 높이 단계 이름(Wrapper 단계, 10장)에만 남깁니다.
  • 새 이름은 순서대로 판정합니다. 수명주기의 주인이면 App·Shell, 지속 영역 배치만 하면 Layout, 관련 항목의 경계면 Group, 지속 작업 영역이면 Panel, 폭만 정하면 Container, 경계 있는 표면이면 Card, 포커스·닫기 오버레이면 Dialog·Sheet, 끌기·스냅이 본질이면 Drawer입니다. 어디에도 해당하지 않고 감싸기만 한다면 공개 컴포넌트를 만들지 않고 Tailwind로 해결합니다.

정본이 허용하는 구성의 예입니다.

text
App
└─ Shell
   └─ Layout
      └─ Main
         └─ Container
            └─ Page
               ├─ navigation / PageBody / aside
               └─ Card | Section

Vue 파일명 ​

역할이름예
라우터 진입점{이름}View.vueDefaultView.vue
문서·시연 페이지 본문{이름}Page.vueEButtonPage.vue
레이아웃{이름}Layout.vueDesignLayout.vue
라우터 outletAppRouteOutlet.vue—
컴포넌트·블록역할 이름InfoHint.vue

계층 약어 접미사(Ato·Mol·Org)는 붙이지 않습니다. 계층은 파일 이름이 아니라 실제 의존과 소유 경계가 말합니다. 파일명의 Page는 「본문」이라는 역할이고, 영역 구성을 소유하는 구조 컴포넌트 EPage·MPage와는 다릅니다.

헷갈리기 쉬운 축 ​

비슷한 이름이 둘이면 먼저 서로 다른 축인지 의심합니다. 정본 「주의사항」 문서의 대표 사례입니다.

  • outline과 outlined: 품사가 축을 가릅니다. 명사 outline은 버튼·배지 같은 동작·라벨의 형태(e-button-blue-outline)이고, 형용사 outlined는 카드·입력 같은 컨테이너의 외형(e-card-outlined)입니다.
  • Content와 Body: Content는 Root와 구분되는 별도 경계(패널, 펼침, 팝업)이고, Body는 Header·Body·Footer의 가운데 절입니다. 그래서 EDialogContent 안에 EDialogHeader·EDialogBody·EDialogFooter가 들어갑니다.
  • -horizontal 클래스와 [data-orientation]: 하위 부품까지 방향 상태를 전달하는 컴포넌트(accordion 등)는 [data-orientation]으로, 나머지는 클래스 modifier로 스타일을 정합니다.

경계와 예외 ​

  • 이름 규칙과 다른 코드는 위치와 근거를 단 내부 알림(alert)으로 보고합니다. 그 사실만으로 병합이나 배포를 막지 않습니다. 실행으로 재현된 고장만 막습니다.
  • 외부 provider가 정한 철자(material-symbols-outlined)는 바꾸지 않고, Tailwind 표준 클래스는 다시 정의하지 않습니다.
  • 저장소와 호스트의 이름은 19장에서 다룹니다.

정리 ​

  • 같은 뜻에는 한 단어를 씁니다. 방향은 horizontal·vertical, 위치는 start·end입니다.
  • 줄임말은 쓰지 않습니다. 표준 약어와 Tailwind 유틸리티는 외부 어휘로 그대로 둡니다.
  • 짝이 있는 modifier는 기본값과 같은 쪽도 정의합니다.
  • 구조 컴포넌트는 책임으로 이름을 정하며, Wrapper·Frame·Box를 공개 이름으로 쓰지 않습니다.
  • Vue 파일명의 접미사는 라우터 진입점 View와 본문 Page만 남깁니다.

정본 ​

  • leysys-design docs/specs/NAMING-CONVENTION.md — 이름 규칙의 진입점, 어휘 축, 금지 어휘
  • leysys-design docs/decisions/STRUCTURAL-UI-VOCABULARY-2026-08-16.md — 구조 컴포넌트 어휘와 판정 순서
  • leysys-design docs/decisions/DIRECTION-VOCABULARY-UNIFICATION-2026-04-28.md — horizontal·vertical과 쌍 클래스
  • leysys-design docs/decisions/POSITION-VOCABULARY-START-END-2026-06-12.md — start·end
  • leysys-design docs/decisions/COMPONENT-FILE-SUFFIX-VIEW-ONLY-2026-09-30.md — Vue 파일명
  • leysys-design docs/specs/DS-GOTCHAS.md — 헷갈리기 쉬운 축과 어휘
  • 저장소·호스트 네이밍 — Leysys Docs 공개 표준