코드 블록 UI 시스템
목적
코드 블록 UI 시스템은 소스 코드 스니펫, API 요청/응답 페이로드, 멀티 파일 코드 예제, 터미널 명령어 및 코드 diff 비교를 표시하기 위한 표준화되고 접근 가능하며 가독성이 뛰어난 레이아웃 프레임워크를 제공합니다. 코드 블록은 기술 문서, 개발자 도구 마케팅 사이트, API 포털, 엔지니어링 블로그 및 SaaS 플랫폼 전반에 걸쳐 중요한 상호 작용 구성 요소입니다.
효과적인 코드 인터페이스를 디자인하려면 고정폭 타이포그래피 가독성, 라이트 및 다크 테마에서의 높은 대비 구문 토큰 하이라이트, 고정 헤더 액션 도구 모음(언어 배지, 탭 파일 탐색, 클립보드 복사 트리거), 줄 번호 매기기, 줄 수준 하이라이트/포커스, 줄 바꿈과 가로 스크롤 동작 및 접근 가능한 스크린 리더 경험 간의 균형을 맞춰야 합니다. 이 스킬은 코드 UI 프레젠테이션을 위한 공간 규칙, 토큰 색상 대비 표준, 상호 작용 메커니즘 및 WCAG AA 준수 지침을 수립합니다.
사용 사례
- 개발자 문서 및 API 참조 포털: 다국어 SDK 예제(예: cURL, Node.js, Python, Go, Rust) 및 API 응답 제시.
- 개발자 도구 랜딩 페이지: 히어로 코드 스니펫, CLI 설치 명령어 및 대화형 제품 데모 블록 선보이기.
- 엔지니어링 블로그 및 튜토리얼: 특정 줄 호출, 단계별 코드 하이라이트 및 인라인 주석이 포함된 인라인 및 블록 코드 예제 렌더링.
- 버전 관리 및 코드 검토 인터페이스: 코드 diff(
+추가,-삭제), 인라인 주석 및 커밋 스니펫 표시. - 코드 플레이그라운드 및 스니펫 공유 도구: 멀티 탭 파일 편집기, 미리보기 창 및 포함 가능한 스니펫 카드 구성.
사용하지 말아야 할 경우
- 전체 브라우저 내 코드 편집기(IDE): 캔버스 렌더링, 가상화 AST 트리, 멀티 커서 편집 및 LSP(언어 서버 프로토콜) 통합(예: Monaco Editor, CodeMirror)이 필요한 복잡한 대화형 웹 IDE의 경우 전용 편집기 구현을 사용하세요.
- 일반 양식 텍스트 입력: 구문 강조나 줄 번호가 없는 여러 줄 일반 텍스트 필드에는
form-design-system을 사용하세요. - 인라인 텍스트 코드 배지: 산문 단락 내의 간단한 한 단어 코드 참조(예:
npm install)에는article-layout-system내에서 인라인<code>스타일을 사용하세요. - 구조화된 데이터 테이블: 행과 열로 형식이 지정된 표 형식의 키-값 데이터 또는 데이터베이스 쿼리의 경우
data-table-ui-system또는property-and-attribute-system을 사용하세요.
입력
- 코드 콘텐츠 및 구문 유형: 언어 분류(예: TypeScript, JSON, Bash, YAML, GraphQL, SQL) 및 구조적 기능(단일 파일, 멀티 파일 탭, diff).
- 테마 컨텍스트: 라이트 모드 및 다크 모드에서 표면 배경, 테두리 및 구문 토큰에 대한 활성 색상 팔레트 토큰(
accessible-color-system및dark-theme-design-system에서 가져옴). - 고정폭 타이포그래피 토큰: 선호하는 글꼴 스택(예:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace), 글꼴 크기 및 줄 높이(fluid-typography-system에서 가져옴). - 액션 트리거: 블록별로 필요한 특정 대화형 기능(예: 원클릭 복사 버튼, 줄 번호 토글, 줄 바꿈 토글, 전체 화면 확장, 외부 샌드박스 링크).
출력
- 코드 컨테이너 및 헤더 도구 모음 명세: 코드 블록 컨테이너, 고정 헤더 바, 언어 표시기, 파일 경로 탭 및 액션 버튼 그룹을 위한 공간 레이아웃.
- 접근 가능한 구문 토큰 색상 팔레트: 라이트 및 다크 테마에서 키워드, 문자열, 함수, 변수, 주석, 연산자 및 유형에 대한 WCAG AA(최소 4.5:1 대비 비율) 토큰 색상 매핑.
- 줄 수준 계층 구조 및 주석 시스템: 줄 번호 매기기, 줄 하이라이트/포커스 오버레이, diff 표시기(
+/-) 및 줄 수준 앵커 링크를 위한 청사진. - 접근 가능한 스크린 리더 및 키보드 탐색 모델: ARIA 역할 속성, 키보드 포커스 경로, 줄 번호 마스킹(
aria-hidden="true") 및aria-live복사 상태 알림. - 반응형 오버플로우 및 스크롤 전략: 가로 스크롤바, 고정 액션 도구 모음, 줄 바꿈 토글 및 모바일 뷰포트 적응을 위한 규칙.
워크플로우
1. 코드 블록 셸 및 헤더 바 구조화
컨테이너와 헤더 액션 바를 통일되고 응집력 있는 단위로 설계합니다.
- 컨테이너 아키텍처: 둥근 컨테이너(
border-radius: 8px; border: 1px solid var(--border-subtle); overflow: hidden; background: var(--surface-code);)를 설정합니다. 고유한 표면 배경(일반적으로 기본적으로 다크 모드 또는 일치하는 테마 표면)을 사용합니다. - 헤더 도구 모음 레이아웃: 상단에 고정된 헤더 바(
display: flex; align-items: center; justify-content: space-between; padding: 8px 16px; background: var(--surface-code-header); border-bottom: 1px solid var(--border-subtle);)를 렌더링합니다. - 헤더 왼쪽 섹션(탭 및 메타데이터):
- 단일 파일: 미묘한 파일 형식 아이콘과 함께 파일 경로/이름(예:
src/auth/jwt.ts)을 표시하거나 대문자 언어 배지(예:TYPESCRIPT)를 표시합니다. - 멀티 파일 / 다중 언어: 탭 버튼(
role="tablist")을 렌더링합니다. 활성 탭은 높은 대비 텍스트와 하단 테두리/필 표시기(border-bottom: 2px solid var(--brand-primary))를 갖습니다.
- 단일 파일: 미묘한 파일 형식 아이콘과 함께 파일 경로/이름(예:
- 헤더 오른쪽 섹션(액션): 유틸리티 액션 트리거를 그룹화합니다.
- 복사 버튼: 32x32픽셀 아이콘 버튼(
aria-label="코드를 클립보드에 복사"). 더 넓은 뷰포트에서 명확한 복사 아이콘과 레이블을 사용합니다. - 줄 바꿈 / 스크롤 토글(선택 사항): 소프트 래핑(
white-space: pre-wrap)과 가로 스크롤(white-space: pre)을 전환하는 아이콘 버튼입니다. - 확장 / 샌드박스 링크(선택 사항): StackBlitz, CodeSandbox 또는 전체 화면에서 스니펫을 열기 위한 트리거입니다.
- 복사 버튼: 32x32픽셀 아이콘 버튼(
2. 고정폭 타이포그래피 및 레이아웃 그리드 설정
기술적 읽기 및 코드 스캔을 위한 최적의 가독성을 보장합니다.
- 글꼴 스택: 깔끔하고 가독성이 높은 고정폭 글꼴 스택을 정의합니다:
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace. 글꼴 기능 설정이0(영)과O(대문자 오),1(일),l(소문자 L) 및I(대문자 아이)를 명확하게 구분할 수 있도록 합니다. - 글꼴 크기 및 줄 높이:
font-size: 0.875rem(14px)과 넉넉한 줄 높이(line-height: 1.6/ 22.4px)를 설정합니다. 코드 괄호와 연산자가 충돌하는 좁은 줄 높이는 피합니다. - 코드 본문 컨테이너:
display: block; overflow-x: auto; padding: 16px 0; margin: 0; font-family: var(--font-mono);와 함께<pre class="code-block"><code class="language-typescript">를 사용합니다.
3. 줄 번호, 줄 하이라이트 및 Diff 설계
복사-붙여넣기 또는 스크린 리더 동작을 저하시키지 않고 줄 수준 요소를 구성합니다.
- 줄 구조: 각 줄을 별개의 블록 컨테이너(
display: table-row;또는display: flex; width: 100%;)로 형식화합니다. - 줄 번호: 왼쪽 거터에 줄 번호를 렌더링합니다(
display: table-cell; text-align: right; width: 40px; padding-right: 16px; user-select: none; color: var(--text-code-muted);).- 접근성 규칙: 줄 번호를
<span aria-hidden="true">로 감싸거나 CSS 카운터 콘텐츠(content: counter(line))를 사용하여 텍스트 선택 시 줄 번호가 복사되지 않고 스크린 리더가 코드 문 사이에서 읽지 못하도록 합니다.
- 접근성 규칙: 줄 번호를
- 하이라이트된 / 포커스된 줄: 튜토리얼이나 diff에서 주요 줄에 주의를 끌기 위해:
- 명시적 줄 하이라이트 배경(
background: var(--surface-code-highlight); border-left: 3px solid var(--brand-primary);)을 적용합니다. - 하이라이트 오버레이가 코드 컨테이너의 전체 스크롤 가능 너비(
min-width: 100%)에 걸쳐 있도록 합니다.
- 명시적 줄 하이라이트 배경(
- Diff 뷰 줄(
+추가 /-삭제):- 추가된 줄: 미묘한 녹색 배경(
background: rgba(34, 197, 94, 0.15); border-left: 3px solid var(--color-success);). 스크린 리더를 위해<span class="sr-only">추가됨:</span>으로 감싼+기호를 거터에 표시합니다. - 삭제된 줄: 미묘한 빨간색 배경(
background: rgba(239, 68, 68, 0.15); border-left: 3px solid var(--color-danger);). 스크린 리더를 위해<span class="sr-only">제거됨:</span>으로 감싼-기호를 거터에 표시합니다.
- 추가된 줄: 미묘한 녹색 배경(
4. 접근 가능한 구문 토큰 색상 팔레트 생성
구문 토큰은 코드 블록 배경(var(--surface-code))에 대해 WCAG AA 대비 비율(최소 4.5:1)을 충족해야 합니다.
- 기본 텍스트 / 변수: 중립적인 밝은 색상(예:
#0F172A배경에#E2E8F0; 비율 ~12.5:1). - 키워드 (
const,import,return,async): 선명한 보라색/마젠타(예:#C084FC; 비율 ~7.2:1). - 함수 및 메서드 (
fetchData,useState): 밝은 파란색/청록색(예:#38BDF8; 비율 ~8.5:1). - 문자열 (
"https://api.example.com"): 부드러운 녹색/에메랄드색(예:#4ADE80; 비율 ~9.1:1). - 숫자 및 불리언 (
404,true): 따뜻한 주황색/호박색(예:#FB923C; 비율 ~7.8:1). - 주석 (
// Handle token response): WCAG AA를 준수하는 부드러운 차가운 회색(예:#94A3B8; 비율 ~5.1:1). 주석에 낮은 대비 회색(예: 2:1)을 절대 사용하지 마십시오. - 연산자 및 구두점 (
=>,{,},;): 중간 중립 색상(예:#CBD5E1; 비율 ~10.2:1).
5. 클립보드 복사 및 액션 피드백 상태 구축
복사 작업에 대한 즉각적인 피드백을 제공하면 중복 클릭과 사용자 불만을 방지할 수 있습니다.
- 기본 상태: 복사 아이콘(겹치는 두 개의 직사각형)과 선택적 레이블("복사")이 있는 아이콘 버튼을 표시합니다.
- 호버 / 포커스 상태: 높아진 표면 배경 또는 테두리 하이라이트(
background: var(--surface-hover); outline: 2px solid var(--focus-ring)). - 활성 / 성공 상태: 클릭 시 아이콘을 확인 표시 아이콘으로 변경하고 버튼 레이블을 "복사됨!"으로 업데이트하며 성공 색상 색조(
color: var(--color-success))를 적용합니다. - 스크린 리더 알림: 보이지 않는
aria-live="polite"영역을 통해 복사 상태를 동적으로 알립니다: "코드가 클립보드에 복사되었습니다". - 시간 초과 재설정: 2000ms 후에 버튼을 기본 상태로 재설정합니다.
6. 모바일 및 반응형 적응
긴 코드 스니펫이 작은 뷰포트에서도 기능적으로 유지되도록 합니다.
- 가로 스크롤 범위 제한: 모바일에서 긴 줄의 경우 페이지 수준 가로 스크롤바 오버플로우를 트리거하지 않고 가로 스크롤(
overflow-x: auto)을 허용합니다. - 고정 헤더 도구 모음: 헤더 도구 모음을 고정(
position: sticky; top: 0; z-index: 10;)하여 100줄 이상의 코드를 스크롤할 때도 복사 버튼과 활성 파일 탭에 계속 액세스할 수 있도록 합니다. - 모바일 터치 대상: 복사 버튼, 줄 바꿈 토글 및 멀티 파일 탭이 터치 장치에서 최소 44x44px의 터치 대상을 충족하는지 확인합니다.
의사 결정 규칙
구문 토큰 대비 및 테마 모드
| 구문 범주 | 권장 토큰 역할 | 라이트 테마 색상(#F8FAFC 배경) | 다크 테마 색상(#0F172A 배경) | 최소 대비 비율 |
|---|---|---|---|---|
| 키워드 | --token-keyword | 진한 보라색(#6B21A8) | 밝은 보라색(#C084FC) | ≥ 4.5:1 |
| 함수 | --token-function | 진한 청록색(#0369A1) | 하늘색(#38BDF8) | ≥ 4.5:1 |
| 문자열 | --token-string | 포레스트 그린(#15803D) | 밝은 에메랄드색(#4ADE80) | ≥ 4.5:1 |
| 숫자 / 불리언 | --token-number | 진한 호박색(#C2410C) | 밝은 호박색(#FB923C) | ≥ 4.5:1 |
| 주석 | --token-comment | 음소거 슬레이트(#475569) | 부드러운 슬레이트(#94A3B8) | ≥ 4.5:1 |
| 기본 / 변수 | --token-base | 숯색(#0F172A) | 선명한 밝은색(#F8FAFC) | ≥ 7.0:1 |
줄 바꿈 대 가로 스크롤 전략
- 가로 스크롤(
white-space: pre) (기본 권장): 코드 레이아웃 무결성, 들여쓰기 정렬 및 여러 줄 형식을 유지합니다. 들여쓰기가 의미 구조를 전달하는 Python, YAML 및 코드 diff에 필수적입니다. - 소프트 줄 바꿈(
white-space: pre-wrap) (선택적 모드): 긴 터미널 출력 문자열, 명령줄 예제 또는 가로 스크롤이 읽기 흐름을 방해하는 좁은 사이드바 위젯에 권장됩니다.
제약 조건
- 접근성 (WCAG 2.1 AA):
- SC 1.4.3 대비 (최소): 모든 구문 강조 토큰 색상 및 주석은 코드 배경에 대해 최소 대비 비율 4.5:1을 달성해야 합니다.
- SC 2.1.1 키보드: 사용자는
Tab및Space/Enter를 사용하여 코드 블록 헤더 버튼(탭, 복사 버튼)으로 이동하고 활성화할 수 있어야 합니다. - SC 4.1.3 상태 메시지: 복사 버튼 피드백은
aria-live="polite"영역을 통해 보조 기술에 알려야 합니다. - SC 1.3.1 정보 및 관계: 줄 번호는 읽는 동안 숫자가 섞이는 것을 방지하기 위해 스크린 리더에서 숨겨야 합니다(
aria-hidden="true"또는 CSS 카운터 사용).
- 텍스트 선택 및 복사: 코드 블록 내에서 텍스트를 선택할 때 줄 번호나 diff 표시기(
+/-)가 절대 클립보드 버퍼에 선택되어서는 안 됩니다. - 레이아웃 이동 방지: 멀티 파일 탭 확장 또는 줄 바꿈 토글은 누적 레이아웃 이동(CLS)을 방지하기 위해 고정된 줄 높이 또는 컨테이너 경계를 지정해야 합니다.
일반적인 실패 패턴
- 읽을 수 없는 낮은 대비 주석: 주석이 중요하지 않다고 가정하고 WCAG AA 지침을 위반하면서 희미한 회색 텍스트(예:
#1A202C배경에#4A5568, 2.8:1 대비)를 사용합니다. - 줄 번호 복사:
<pre>내부에 줄 번호를 일반 텍스트로 렌더링하여1 2 3 4가 접두사로 붙은 잘못된 코드 스니펫을 복사-붙여넣기하게 만듭니다. - 알림 없는 복사 작업:
aria-label을 업데이트하거나aria-live알림을 보내지 않고 복사 버튼의 시각적 아이콘을 변경하여 스크린 리더 사용자가 작업이 성공했는지 확신하지 못하게 합니다. - 페이지 수준 오버플로우 누출:
<pre>에max-width: 100%및overflow-x: auto를 설정하지 않아 120자 코드 줄이 모바일 화면에서 페이지 레이아웃을 벗어나게 합니다. - 가로 스크롤의 접근 불가능한 포커스 트랩: 명확한 키보드 시각적 윤곽 표시기 없이 스크롤 가능한 코드 블록에
tabindex="0"을 배치하여 키보드 사용자가 긴 코드 블록 내부에 갇히게 만듭니다.
검증 기준
- 코드 블록에는 언어, 파일 경로 및 액션(복사, 줄 바꿈 토글)을 위한 고정 헤더 도구 모음이 있는 구조화된 컨테이너가 있습니다.
- 구문 토큰은 라이트 및 다크 테마 모두에서 WCAG AA(≥4.5:1 대비)를 충족합니다.
- 줄 번호는 복사 시 선택되지 않으며 스크린 리더에서 읽히지 않습니다(
aria-hidden="true"). - diff 표시기(
+,-)는 복사 시 선택되지 않습니다. - 복사 버튼은 성공 시 "복사됨!" 시각적 피드백과
aria-live알림을 제공합니다. - 모바일 뷰포트에서 코드 블록은 페이지를 넘기지 않고 가로로 스크롤됩니다.
- 탭 간 전환 및 버튼 클릭은 키보드(
Tab,Enter,Space)로 액세스할 수 있습니다. - 줄 바꿈 활성화 시 소프트 래핑으로 인한 레이아웃 이동이 없습니다.
종속성
accessible-color-system(라이트 및 다크 모드용 표면, 텍스트, 테두리 토큰)fluid-typography-system(고정폭 글꼴 스택,font-size토큰, 줄 높이 스케일)dark-theme-design-system(다크 모드에서 코드 블록을 올바르게 렌더링하기 위한 보충 색상 토큰)icon-library-system(복사, 확인 표시, 확장, 외부 링크 아이콘)form-design-system(코드 블록과 관련 없는 여러 줄 텍스트 입력용)