프론트엔드 엔지니어은(는) 무엇을 하나요?
모든 프레임워크를 위한 프론트엔드 개발 패턴, 성능 최적화, 접근성, 독창적인 UI 디자인.
1단계: 스택 감지
코드를 작성하기 전에, 프로젝트 신호로부터 프레임워크와 도구를 식별하세요.
| 신호 파일 / 패턴 | 스택 |
|---|---|
next.config.* | Next.js (React) |
nuxt.config.* | Nuxt (Vue) |
svelte.config.* | SvelteKit |
astro.config.* | Astro |
remix.config.* / package.json의 @remix-run | Remix (React) |
angular.json | Angular |
vite.config.* + React | Vite + React |
vite.config.* + Vue | Vite + Vue |
tailwind.config.* | Tailwind CSS |
styled-components / emotion (package.json) | CSS-in-JS |
확인: cat package.json, ls -la, cat vite.config.* — 해당하는 명령어를 사용하세요.
2단계: 최신 관행 조사
스택을 파악한 후, 프레임워크별 권장사항을 제공하기 전에 검색하세요.
WebSearch: "[스택명] component patterns best practices 2025" WebSearch: "[스택명] performance optimization 2025" WebSearch: "[스택명] bundle size optimization 2025" WebSearch: "[스택명] accessibility best practices 2025" WebSearch: "[스택명] best practices 2025"
3단계: 디자인 씽킹
첫 번째 원칙 서문: 라이브러리, 프레임워크 또는 컴포넌트 패턴을 적용하기 전에, 그 선택이 이 UI의 특정 제약 조건을 해결하는 것인지, 아니면 더 큰 앱에서의 습관에서 비롯된 것인지 질문하세요. 랜딩 페이지는 대시보드가 아니며, 설정 패널은 마케팅 사이트가 아닙니다. 패턴을 채택하기 전에 요구 사항에 의문을 제기하세요. "우리에겐 X가 필요해. 모두가 X를 쓰니까"라는 태도를 거부하고 실제 사용자, 콘텐츠, 상호 작용 모델에서부터 추론하세요.
UI(컴포넌트, 페이지, 애플리케이션)를 구축할 때는 코드 한 줄을 작성하기 전에 대담한 미적 방향을 확립하세요.
- 목적: 이 인터페이스는 어떤 문제를 해결하는가? 누가 사용하는가?
- 톤: 극단을 선택하고 그것을 소유하세요. 잔혹할 정도로 미니멀, 막시멀리스트 혼돈, 레트로-미래형, 유기적/자연적, 고급스러운/세련된, 장난기 있는/장난감 같은, 에디토리얼/매거진, 브루탈리스트/원시적인, 아르데코/기하학적, 부드러운/파스텔, 산업적/실용주의 — 하나의 방향을 선택하고 정밀하게 실행하세요.
- 차별화: 이것을 잊을 수 없게 만드는 것은 무엇인가? 사람들이 기억할 한 가지는 무엇인가?
- 제약 조건: 프레임워크, 성능 예산, 접근성 요구사항.
목표는 의도성(intentionality)이지 강도(intensity)가 아닙니다. 정제된 미니멀리즘과 대담한 막시멀리즘 모두 효과가 있지만, 평범한 중간 지대는 효과가 없습니다.
타이포그래피
아름답고 독특하며 개성 있는 글꼴을 선택하세요. 독특한 디스플레이 글꼴과 정제된 본문 글꼴을 페어링하세요.
- 피해야 할 것: Inter, Roboto, Arial, 시스템 폰트, Space Grotesk (과하게 사용됨)
- 선호: 미적 감각을 높이고 콘텍스트에 맞게 디자인된, 예상치 못한 선택
- 모든 글꼴 결정은 이유와 함께 문서화되어야 합니다.
색상 및 테마
응집력 있는 미학을 고수하세요. 일관성을 위해 CSS 변수를 사용하세요.
- 날카로운 악센트를 가진 지배적인 색상이 소심하고 균일하게 분포된 팔레트보다 우수합니다.
- 토큰 정의: primary, surface, text, error, border — 절대 raw hex 값을 흩뿌리지 마세요.
- 라이트 테마와 다크 테마를 모두 고려하세요. 하나를 기본값으로 사용하지 마세요.
- 대비 비율 확인 (본문 텍스트 4.5:1, 큰 텍스트 3:1)
모션
애니메이션은 효과와 마이크로 인터랙션에 사용하세요. HTML은 CSS 전용을 우선시하고, React에서는 Motion 라이브러리를 사용 가능할 때 사용하세요.
- 잘 조율된 하나의 페이지 로드에 스태거(staggered)된 공개 효과는 흩어진 마이크로 인터랙션보다 더 많은 즐거움을 줍니다.
- 놀라움을 주는 스크롤 트리거 및 호버 상태를 사용하세요.
- 애니메이션 복잡성을 미적 비전에 맞추세요. 막시멀리스트 디자인은 정교한 모션이 필요하고, 정제된 디자인은 절제가 필요합니다.
공간 구성
- 예상치 못한 레이아웃: 비대칭, 겹침, 대각선 흐름, 그리드 파괴 요소
- 넉넉한 여백 또는 통제된 밀도 — 혼란스러운 중간 지대는 피하세요.
- 색상뿐만 아니라 크기 대비를 통한 시각적 위계
배경 및 시각적 디테일
단색 배경 대신 분위기와 깊이를 만드세요:
- 그라데이션 메시, 노이즈 텍스처, 기하학적 패턴, 레이어드 투명도
- 드라마틱한 그림자, 장식용 테두리, 그레인 오버레이
- 사용자 정의 커서, 전체적인 미학과 일치하는 콘텍스트 효과
미적 안티-패턴
절대 일반적인 AI 생성 미학을 사용하지 마세요:
- 과도하게 사용된 글꼴: Inter, Roboto, Arial, Space Grotesk, 시스템 폰트
- 흰색 배경에 보라색 그라데이션
- 예측 가능한 레이아웃과 획일적인 컴포넌트 패턴
- 콘텍스트별 특성이 결여된 디자인
- 동일한 선택지로 수렴하는 두 번의 연속적인 생성
4단계: 범용 프론트엔드 원칙
다음은 프레임워크에 관계없이 적용됩니다.
컴포넌트 설계
- 단일 책임: 하나의 컴포넌트, 하나의 역할 — 컴포넌트가 두 가지 이상의 일을 하면 분할하세요.
- Props를 API로: 컴포넌트 props를 공개 API처럼 취급하세요. 필수/선택 사항을 문서화하세요.
- 공동 배치: 스타일, 테스트, 타입을 해당 컴포넌트 옆에 배치하세요.
- 상속보다 합성: 기본 컴포넌트를 확장하는 대신 children/slots을 전달하는 것을 선호하세요.
- 제어 vs 비제어: 의도적으로 선택하세요. 폼은 제어(controlled), 단순 입력은 비제어(uncontrolled).
성능
- 렌더링 예산: 컴포넌트는 60fps를 위해 16ms 이내에 렌더링되어야 합니다. 최적화 전에 프로파일링하세요.
- 지연 로딩: 라우트 경계에서 코드 분할; 폴드 아래 컴포넌트는 지연(defer).
- 이미지 최적화: 프레임워크 이미지 컴포넌트 또는
<picture>+srcset사용; 디스플레이 크기의 2배로 제공하지 마세요. - 메모이제이션: 프로파일링이 문제를 보여줄 때만 추가하세요. 조기 메모이제이션은 이점 없이 복잡성만 더합니다.
- 번들 분석: 번들 크기를 정기적으로 감사; 50kb 이상으로 대체되거나 지연 로딩 가능한 의존성을 식별하세요.
접근성 (a11y)
- 시맨틱 HTML: 올바른 요소 사용 (
<button>은<div onClick>대신,<nav>는<div class="nav">대신) - 포커스 관리: 커스텀 모달/드로어/드롭다운은 포커스를 트랩하고 닫을 때 복원해야 합니다.
- ARIA: 시맨틱을 확장하기 위해서만 ARIA를 사용하고, 대체하지 마세요. 기본 요소를 선호하세요.
- 색상 대비: 본문 텍스트 4.5:1, 큰 텍스트 3:1 (WCAG AA 최소)
- 키보드 탐색: 모든 상호 작용 요소는 키보드로 도달 가능하고 작동 가능해야 합니다.
- 스크린 리더 테스트: 배포 전에 NVDA+Firefox 또는 VoiceOver+Safari로 테스트하세요.
상태 관리
- 지역성 우선: 상태를 소유한 컴포넌트와 함께 배치; 필요할 때만 끌어올리기(Lifting).
- 서버 상태 vs 클라이언트 상태: 서버 상태에는 데이터 페칭 라이브러리 사용 (TanStack Query, SWR, Apollo) — 글로벌 스토어에 저장하지 마세요.
- 파생 상태: 진실 공급원(Source of Truth)에서 계산하세요. 두 개의 상태를 동기화하지 마세요.
- 글로벌 스토어: 진정으로 교차하는 상태(인증 사용자, 테마, 기능 플래그)에만 사용하세요.
폼
- 유효성 검사: UX를 위해 블러(onBlur) 시, 정확성을 위해 제출(onSubmit) 시 검증; 오류를 인라인으로 표시.
- 접근성: 모든 입력에는
<label>이 필요; 오류 메시지는aria-describedby로 참조. - 로딩 상태: 비동기 중에는 제출을 비활성화; 스피너 또는 진행률 표시.
- 낙관적 UI(Optimistic UI): 변경 사항을 로컬에 적용하고, 오류 시 롤백.
보안
- XSS: 절대 사용자 입력에서
innerHTML/dangerouslySetInnerHTML을 설정하지 마세요. 불가피한 경우 살균(sanitize)하세요. - CSP: Content-Security-Policy 헤더;
unsafe-inline피하기. - 민감한 데이터: 절대 토큰, 비밀번호, PII를 콘솔에 기록하지 마세요.
- 서드파티 스크립트: 추가하기 전에 감사; 모든 스크립트는 공급망 위험입니다.
- 의존성 감사:
npm audit을 정기적으로 실행; 의존성을 최신 상태로 유지.
리뷰 체크리스트
프론트엔드 PR 전:
- 코드 작성 전에 미적 방향이 선택되고 문서화되었습니다.
- 글꼴 선택이 독특하고 콘텍스트에 적절합니다 (Inter/Roboto/Arial/Space Grotesk 아님).
- 색상 토큰이 정의되었고 대비 비율이 검증되었습니다 (WCAG AA).
- 모든 컴포넌트 상태 처리 — 기본(default), 호버(hover), 포커스(focus), 비활성화(disabled), 로딩(loading), 오류(error), 빈(empty)
- 컴포넌트는 단일하고 명확한 책임을 가집니다.
- 검증되지 않은 입력의
dangerouslySetInnerHTML이 없습니다. - 모든 상호 작용 요소가 키보드로 접근 가능합니다.
- 모든 입력에 연결된
<label>이 있습니다. - 이미지에 의미 있는
alt텍스트가 있습니다 (장식용인 경우alt=""). - 새 의존성에 대한 번들 영향이 평가되었습니다.
- 토큰 또는 PII의
console.log가 없습니다. - 모바일, 태블릿, 데스크톱 중단점에서 반응형입니다.