Communitygithub.com

portfolio-skill: 이력서+레포 → 맞춤 개인 포트폴리오

이력서·레포·링크로 수상급 개인 포트폴리오를 설계·구축. 사람별 아트 디렉션, 실콘텐츠, 안무 모션, 케이스 스터디, 연락 폼, SEO, a11y, 배포. 일반 회사 랜딩용이 아님.

portfolio-skill: 이력서+레포 → 맞춤 개인 포트폴리오란 무엇인가요?

Personal Website 레시피 3단계(개인 브랜드 고정). PRABHUSIDDARTH/portfolio-skill(2026-10-11). 이력서+레포를 흔한 AI 포트폴리오가 아닌 사이트로 — awwwards·liquid-glass 이후.

지원 대상~Claude Code~Codex CLI✓Cursor
npx skills add PRABHUSIDDARTH/portfolio-skill

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

포트폴리오 스킬

탭을 닫은 후에도 채용 담당자, 리크루터, 또는 클라이언트가 기억하는 포트폴리오를 만드세요: 하나의 확신 있는 시각적 아이디어, 구체적인 카피, 이유 있는 모션, 그리고 누군가 DevTools를 열었을 때 버틸 수 있는 엔지니어링.

테마는 사람에 따라 선택됩니다. 여기에는 색상, 글꼴 또는 레이아웃 스타일이 고정되어 있지 않습니다. 이 파일의 모든 구체적인 값은 패턴의 예시일 뿐, 복사할 기본값이 아닙니다.


1. 품질 기준 (완료 전에 모두 확인)

  1. 하나의 아트 디렉션, 일관되게 실행. 명명된 컨셉이 서체, 색상, 레이아웃, 모션, 카피 톤을 결정합니다. 한 사이트에 관련 없는 스타일(유리 + 네온 + 브루탈리즘 + 그라데이션)을 절대 섞지 마세요.
  2. 실제적이고 구체적인 콘텐츠. 모든 주장은 사용자의 이력서, 리포지토리, 프로필 또는 메시지에서 가져옵니다. 구체적인 숫자, 스택 이름, 역할, 날짜. 로렘 입숨, 지어낸 지표, "열정적인 개발자, 코딩을 사랑합니다"는 쓰지 마세요.
  3. 작업이 주인공입니다. 상위 2-4개 프로젝트가 가장 많은 공간을 차지하며, 이상적으로는 각각 대화형 요소가 있는 자체 케이스 스터디 페이지를 갖습니다. 나머지는 훑어보고 필터링 가능한 인덱스에 있습니다.
  4. 타이포그래피가 디자인을 이끕니다. 표현적인 디스플레이 서체 + 가독성 좋은 텍스트 서체 + 선택적 모노/유틸리티 서체. 유동적인 clamp() 크기. Inter, Roboto, Arial 또는 시스템 스택은 디스플레이 목소리가 될 수 없습니다.
  5. 모션은 안무되어 있고, 뿌려진 것이 아닙니다. 인트로, 스크롤 리빌, 그리고 1-2개의 시그니처 모먼트. 모든 것은 prefers-reduced-motion을 존중하고 깔끔하게 저하됩니다.
  6. 모든 곳에서 작동합니다. 360px부터 울트라와이드까지, 키보드 조작 가능, WCAG AA 대비, 빠른 최초 페인트, WebGL이나 JS 애니메이션 없이도 완전히 읽을 수 있습니다.
  7. 출시합니다. 제로 타입 오류, 프로덕션 빌드 통과, 경로별 메타/OG 태그, 이력서 링크, 전달되는 연락처 경로, 배포 구성.

2. 작업 흐름

  1. 자료 수집. 제공된 모든 것을 읽으세요: 이력서 PDF/DOCX, 기존 사이트, README, GitHub 데이터, 노트. 누락된 필수 항목(이름, 역할, 대상 고객, 2-4개의 플래그십 프로젝트, 링크, 시각적 선호도)에 대해서만 물어보세요. 선호도가 주어지지 않으면 직접 방향을 선택하고 어떤 방향인지, 왜 그런지 말하세요.
  2. 아키타입과 야망 수준(섹션 6A.2)을 사람과 일정에 맞게 선택한 다음, UI 코드를 작성하기 전에 디자인 브리프(섹션 3)를 작성하세요.
  3. 기초 구축(섹션 5): 콘텐츠 모듈, 토큰, 서체, 라우터, 부드러운 스크롤.
  4. 제시 가능한 순서로 페이지 구성: 콘텐츠 -> 토큰/서체 -> 탐색/푸터 -> 히어로 -> 플래그십 -> 작업 인덱스 -> 소개/역량/연혁 -> 연락처 -> 케이스 스터디 페이지 -> 404. 그런 다음 모션(섹션 6). WebGL과 시그니처 효과는 마지막에.
  5. 실제 브라우저(섹션 9)에서 ~1440px 및 ~390px로 확인하세요. 코드만 읽고 완료되었다고 선언하지 마세요.

리포지토리가 이미 스택(Next.js, Astro, SvelteKit, 일반 HTML)을 사용하는 경우 유지하세요. 아래 모든 패턴은 변환 가능합니다.


3. 아트 디렉션

3.1 사람으로부터 테마 도출하기

질문: 누가 이것을 볼 것인가, 5초 안에 무엇을 느껴야 하는가, 이 사람의 작업은 어떻게 생겼는가? 그것을 컨셉에 매핑하세요. 사용자가 지정한 브랜드 색상, 글꼴 또는 테마는 항상 우선합니다.

사람 / 신호예시 방향 (하나 선택하거나 새로 고안)
백엔드 / 시스템 / 인프라에디토리얼 종이 + 잉크; 청사진/기술 도면; 터미널 브루탈리즘; 데이터 시각화 악센트가 있는 스위스 그리드
프론트엔드 / 크리에이티브 개발대담한 운동성 서체; WebGL 주도 몰입형; 장난기 있는 스티커/진; 하나의 네온이 있는 고대비 단색
제품 / UX 디자이너차분한 갤러리 여백; 따뜻한 스튜디오(크림, 테라코타, 부드러운 세리프); 케이스 스터디 매거진
ML / 연구 / 데이터연구실 노트(모눈종이, 단색 주석); 과학 저널; 플롯된 선이 있는 어두운 천문대
모바일 개발자디바이스 중심 쇼케이스; 부드러운 촉감 표면; 라이브 폰 목업이 있는 앱 스토어 수준의 완성도
사진작가 / 아티스트이미지 우선 풀블리드; 미니멀 크롬; 다크 시네마; 접촉 사진 그리드
창업자 / 제너럴리스트자신감 있는 에디토리얼; 선언문 타이포그래피; 지표 기반 신뢰도
학생 / 초기 경력자깔끔하고, 활기차고, 정직함; 프로젝트와 학습 경로를 직함보다 강조

AI 생성으로 읽히는 기본값은 피하세요: 흰색 바탕에 보라색-파란색 그라데이션, 일반적인 글래스모피즘 카드, "안녕하세요, 저는 X입니다" + 웨이브 이모지가 있는 중앙 히어로, 세 개의 동일한 기능 카드, 재고 3D 블롭.

3.2 디자인 브리프 템플릿 (먼저 작성)

컨셉:        <이름 + 의도 한 문장>
대상:        <누구, 그들이 무엇을 가져가야 하는가>
팔레트:        배경, 배경-2, 전경, 전경-2, 음소거, 라인, 강조 (+ 사용된 경우 프로젝트별 강조)
서체:         디스플레이 / 텍스트 / 단색 (폴백 포함), 스케일 비율
레이아웃 문법: 그리드, 거터, 섹션 리듬, 규칙/테두리 vs 카드
모션:         성격 (선명함/탄력적/느림/기계적), 주요 이징, 지속 시간
시그니처:      사람들이 기억할 1-2개의 순간
텍스처:        입자 / 그리드 라인 / 없음 / 셰이더

3.3 토큰 (구조는 고정, 값은 테마별)

:root {
  /* 팔레트: 테마별로 값 교체 */
  --bg: #eeeae2;  --bg-2: #e5e0d5;
  --fg: #121210;  --fg-2: #2a2925;
  --muted: #6d695f;
  --line: rgba(18,18,16,.14);
  --accent: #ff4d1c;
  /* 서체 음성 */
  --display: 'Instrument Serif', 'Times New Roman', serif;
  --text: 'Geist', 'Helvetica Neue', sans-serif;
  --mono: 'Geist Mono', ui-monospace, monospace;
  /* 리듬 */
  --gutter: clamp(1.1rem, 3.2vw, 2.75rem);
  --ease: cubic-bezier(.16, 1, .3, 1);
  /* 케이스 스터디 페이지가 이것들을 재정의하여 리테마할 수 있도록 하는 페이지 수준 별칭 */
  --page-bg: var(--bg); --page-fg: var(--fg); --page-muted: var(--muted);
  --page-line: var(--line); --page-accent: var(--accent);
}

컴포넌트는 --page-*만 참조합니다. 케이스 스터디 페이지는 <main>에 새 --page-* 값을 설정하고 전체 UI(버튼, 규칙, 커서, 선택)가 무료로 리테마됩니다.

3.4 타이포그래피 규칙

  • 대비로 페어링: 세리프 디스플레이 + 그로테스크 텍스트, 또는 헤비 그로테스크 디스플레이 + 단색, 또는 콘덴스드 디스플레이 + 휴머니스트 텍스트. display=swap 및 preconnect와 함께 Google Fonts 또는 자체 호스팅 woff2를 통해 로드하세요.
  • clamp를 사용한 유동적 스케일, 예: h-xl: clamp(3.6rem, 14.5vw, 15rem), h-lg: clamp(2.8rem, 8vw, 8.5rem), h-md: clamp(2.1rem, 5vw, 4.6rem), lede: clamp(1.05rem, 1.45vw, 1.3rem).
  • 디스플레이: 타이트한 행간(0.85-0.95) 및 네거티브 자간(-0.02 ~ -0.04em). 본문: 1.5-1.65 행간, max-width 38-62ch.
  • 메타데이터는 약간의 자간이 있는 작은 대문자 단색으로 ("(02) Selected work", "2024 - Present").
  • 헤드라인에서 한 단어에 이탤릭체 또는 무게 변화를 사용하여 음성을 추가하세요 ("The ones I'd demo first.").
  • 카운터와 통계에는 font-variant-numeric: tabular-nums.

3.5 레이아웃 문법

  • 풀블리드 히어로 (min-height: 100svh), 콘텐츠는 정중앙이 아닌 왼쪽 하단 또는 그리드 전체에 고정.
  • 섹션 헤더는 얇은 규칙과 왼쪽에 번호가 매겨진 단색 레이블, 오른쪽에 컨텍스트로.
  • 그림자 카드보다는 가는 라인과 그리드를 선호하세요 (컨셉이 촉각적/부드러운 경우는 제외).
  • 섹션 리듬을 다양화: 큰 진술, 밀집 인덱스, 가로 릴, 두 컬럼 분할. 결코 여섯 개의 동일한 섹션을 연속으로 배치하지 마세요.
  • 모든 곳에서 일관된 --gutter; 섹션 패딩 clamp(5rem, 13vw, 11rem).

3.6 텍스처 옵션

필름 그레인 (body::after에 SVG feTurbulence 데이터-URI, 불투명도 0.04-0.08, pointer-events:none), 청사진 그리드 라인, 미묘한 방사형 그라데이션, 또는 WebGL 필드. 하나를 선택하고 쌓지 마세요.


4. 콘텐츠 전략

4.1 정보 아키텍처

홈 (단일 스크롤):

  1. 히어로: 이름, 한 줄 포지셔닝, 1-2 문장 레드, 기본 CTA (작업 보기) + 보조 (이력서 / 연락처), 작은 메타 행 (역할, 전문 분야, 위치, 가용성).
  2. 진술 / 소개: 당사자 목소리로 2-4 문장, 참된 3-4개의 통계 (출시된 프로젝트, 연수, 사용자, 별표, 학생인 경우 CGPA).
  3. 플래그십: 2-4개의 히어로 프로젝트, 큰 카드, 각각 케이스 스터디 페이지로 연결.
  4. 작업 인덱스: 다른 모든 프로젝트를 행으로 (번호, 이름, 한 줄 요약, 스택, 연도/링크), 종류별로 필터 가능.
  5. 역량: 그룹화된 기술 (예: 백엔드, 모바일, AI, 도구), 면접에서 방어할 수 있는 것만.
  6. 경로 / 연혁: 교육, 역할, 주목할 만한 성과.
  7. 연락처: 큰 CTA 헤드라인, 이메일, 양식, 소셜 링크, 이력서 다운로드.

플래그십당 케이스 스터디 페이지: 테마가 있는 히어로 (이름, 태그라인, 역할, 스택, 링크), 문제, 구축된 것, 대화형 데모 (시뮬레이터, 놀이터, 라이브 목업, 호버 가능한 아키텍처 다이어그램), 주요 결정/트레이드오프, 지표/결과, 그런 다음 "다음 프로젝트" 핸드오프 및 연락처.

같은 음성의 404 페이지.

4.2 카피 규칙

  • 1인칭, 평이, 구체적. 무엇이 구축되었고 왜 중요한지로 시작하고, 그 다음에 어떻게.
  • 좋은 예: "자신의 AWS, GCP 및 Azure 계정을 연결하면 무료 티어가 하나의 디스크처럼 작동합니다." 나쁜 예: "최첨단 기술을 활용한 혁신적인 클라우드 솔루션."
  • 금지된 채우기 단어: 열정적인, 최첨단, 활용, 원활한, 견고한, 혁신적인, 여정, 탐구하다, "저는 코딩을 사랑합니다".
  • 모든 지표는 출처가 있거나 생략됩니다. 절대 지어내지 마세요.
  • 마이크로카피는 개성이 있지만 명확해야 함 (("Lost in the reel." 404에서, "Scroll to pan" 힌트).

4.3 단일 콘텐츠 모듈

모든 카피와 데이터는 src/content.ts에 있습니다. 컴포넌트는 절대 전기 텍스트를 하드코딩하지 않습니다.

export const PROFILE = { name, role, location, email, github, linkedin, resume: '/resume.pdf', statement };
export type Metric = { value: string; label: string };
export type Flagship = {
  slug: string; path: string; index: string; name: string; kicker: string; tagline: string;
  summary: string; role: string; stack: string[]; metrics: Metric[]; repo: string;
  accent: string; bg: string; fg: string;          // 프로젝트별 테마
};
export const FLAGSHIPS: Flagship[] = [ /* 2-4 */ ];
export type WorkKind = 'Systems' | 'AI' | 'Mobile' | 'Web'; // 사람에 맞게 조정
export const WORKS: { name: string; blurb: string; stack: string[]; kind: WorkKind; year: string; href: string; route?: string }[] = [];
export const CAPABILITIES: { title: string; items: string[] }[] = [];
export const PATH: { when: string; what: string; detail: string }[] = [];
export const STATS: Metric[] = [];

5. 아키텍처

5.1 기본 스택

Vite + React + TypeScript; 사용자 정의 속성을 사용한 일반 CSS (팀이 선호하는 경우 Tailwind 허용); gsap + @gsap/react (ScrollTrigger); 부드러운 스크롤을 위한 lenis; 방향이 WebGL을 사용하는 경우에만 three; 연락처를 위한 nodemailer; Vercel/Netlify에 배포.

5.2 구조

index.html                 글꼴, 기본 메타/OG, noscript 대체 텍스트
public/                    favicon.svg, resume.pdf, og-image
src/content.ts             모든 카피와 데이터
src/index.css              토큰, 서체, 레이아웃, 컴포넌트, 반응형, 축소 모션
src/lib/smooth.ts          Lenis + GSAP 티커, 축소 모션 플래그, 스크롤 속도
src/lib/motion.tsx         useReveals, useHeroIntro, <Split>, useMeta
src/lib/router.tsx         히스토리 라우터 + 커튼 전환 + <Link>
src/components/Chrome.tsx  탐색, 모바일 메뉴, 커서, 프리로더, 푸터/연락처
src/components/Field.tsx   선택적 WebGL 히어로 배경
src/components/CaseShell.tsx 공유 케이스 스터디 스캐폴드
src/pages/*.tsx            홈, 플래그십당 한 페이지, NotFound
api/contact.ts             서버리스 메일 핸들러
vercel.json                SPA 재작성

5.3 라우팅

작은 히스토리 라우터는 포트폴리오에 충분하며 전환을 소유할 수 있게 합니다:

  • normalizePath (후행 슬래시 제거, 소문자화).
  • navigate(to): 동일한 경로 + 해시 -> 앵커로 부드러운 스크롤; 다른 경로 -> 커튼 재생, 덮인 상태에서 페이지 교체, 맨 위로 스크롤, 그런 다음 표시.
  • popstate 수신; 각 경로 변경 후 ScrollTrigger.refresh() 호출; 교체 후 보류 중인 #hash 처리.
  • <Link>: 외부 (http, mailto)는 target="_blank" rel="noopener noreferrer"와 함께 일반 앵커를 렌더링합니다. 내부는 metaKey/ctrlKey/shiftKey 또는 왼쪽이 아닌 버튼이 아닌 한 클릭을 가로채므로 새 탭이 계속 작동합니다.
  • Next.js/Astro: 해당 라우터를 사용하고 레이아웃/전환 훅에서 커튼을 구현합니다.

5.4 경로별 SEO

useMeta(title, description, themeColor)는 각 경로에서 document.title, description, og:*, twitter:*, theme-color 및 canonical을 업데이트합니다. index.html에는 <noscript> 텍스트 요약과 함께 완전한 기본값이 포함되어 있습니다. 가능하면 summary_large_image Twitter 카드와 OG 이미지를 추가하세요. JSON-LD Person 스키마를 고려하세요.

5.5 연락처 API (서버리스, api/contact.ts)

요구 사항:

  • POST만 허용 (그 외는 405), Cache-Control: no-store.
  • 허니팟 필드 (예: 숨겨진 website): 채워지면 200을 반환하고 드롭.
  • 모든 필드를 트림하고 길이 제한; 간단한 정규식으로 이메일 검증; 최소 메시지 길이.
  • 헤더/제목에 사용되는 모든 항목에서 \r\n 제거 (헤더 인젝션); HTML 본문에 있는 모든 것을 HTML 이스케이프.
  • replyTo = 발신자; from = 사용자의 SMTP 사용자.
  • IP당 최선의 노력 속도 제한 (예: 메모리 내 Map을 통해 10분당 3회, IP는 x-forwarded-for에서).
  • SMTP 환경 변수가 없으면 친숙한 "email me directly" 메시지와 함께 503을 반환합니다. UI는 대체 수단으로 이메일을 표시해야 합니다.
  • 환경 변수: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS, CONTACT_TO. .env.example을 제공하세요. 절대 시크릿을 커밋하지 마세요.
  • 프론트엔드 폼: 유휴/전송 중/전송됨/오류 상태, aria-live="polite" 상태, 전송 중 제출 비활성화, 모든 입력에 레이블.

5.6 배포

Vercel vercel.json:

{ "cleanUrls": true,
  "rewrites": [{ "source": "/((?!api/|assets/|.*\..*).*)", "destination": "/" }] }

Netlify: _redirects에 /* /index.html 200. 이력서는 public/resume.pdf에 있습니다; 모든 이력서 버튼은 download와 함께 그곳으로 링크됩니다.


6. 모션 시스템

6.1 원칙

  • 하나의 하우스 이징 (예: expo.out / cubic-bezier(.16,1,.3,1)), 리빌은 0.6-1.4초, 호버는 0.3-0.6초.
  • transform, opacity, clip-path만 애니메이션. 절대 레이아웃 속성을 애니메이션하지 마세요.
  • 마스크된 리빌 (overflow:hidden 상자에서 텍스트가 올라오는 것)은 고급스러워 보이고, 일반 페이드는 싸 보입니다.
  • 안무: 히어로 인트로는 프리로더/커튼이 사라질 때까지 기다립니다 (공유 intro.delay).
  • 모든 효과는 prefersReducedMotion 플래그에 의해 게이트됩니다.

6.2 모션 패턴

  1. 히어로 인트로: 각 요소(배경, 이름, 역할, lede, CTA)가 0.1초 지연으로 연속적으로 올라갑니다. 전체 시퀀스 약 1.2초.
  2. 스크롤 리빌: useReveals(ref, { from: 'y 48' | 'opacity 0' | 'clip' | 'scale' }). 기본값: y 48 + opacity 0, 지속 시간 0.8초, 이징 --ease, 트리거 top 85%.
  3. 작업 카드 호버: 덮개가 올라가고/페이드 인. 또는 마우스를 따라 카드가 살짝 기울어짐. 프레임워크에 의해 캡처된 경우에만 --ease를 존중하세요.
  4. 커서: 개념이 단색/브루탈리스트가 아닌 경우 점/원 커서, 호버 시 크기 조정 또는 색상 변경. Machinel/느린 개념에서는 사라집니다.
  5. 카운터 / 스크롤 진행: 단색 숫자, 오른쪽 상단에 고정. 또는 단색 숫자가 있는 수평 스크롤 진행 표시줄.
  6. 연락처 커튼: 푸터를 클릭하면 CTA가 전체 화면으로 확장됩니다. clip-path: circle() 또는 scaleY를 뒤집어서.

6.3 reduce-motion 게이트

// src/lib/smooth.ts
export const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

export const motion = {
  get reveal() { return prefersReducedMotion ? { y: 0, opacity: 1 } : { y: 48, opacity: 0 }; },
  get duration() { return prefersReducedMotion ? 0 : 0.8; },
  get scrollDuration() { return prefersReducedMotion ? 0 : 1.2; },
  // etc
};

7. 페이지 구성 가이드

7.1 홈

(뒤에서 언급되는 h-xl, h-lg, h-md를 오름차순 크기로 가정)

  • 히어로: 풀블리드, 하단 고정. 또는 반 그리드. 무거운 디스플레이 + 작은 lede. 배경은 깔끔한 WebGL 또는 텍스처. CTA가 "작업 보기" 또는 빠른 스크롤.
  • 플래그십: 큰 카드 그리드. 각각: 이미지/데모, 이름, 태그라인, 스택 태그, CTA. 2-3개의 플래그십은 한 줄, 4개는 2x2.
  • 작업 인덱스: 테이블 느낌. 번호, 프로젝트 이름, 한 줄 요약, 스택, 연도, 링크. 종류별 필터 (버튼, 활성화 시 강조).
  • 경로: 수평 타임라인 또는 표. 각 행: 시기(연도/날짜), 무슨 일, 세부 정보.
  • 연락처: 큰 CTA 헤드라인 + 이메일 양식 + 소셜.

7.2 케이스 스터디 (CaseShell에서 제공)

  1. 히어로: 이름, 태그라인, 역할, 스택, 링크. 케이스의 강조 색상이 있는 배경. --page-accent는 여기에서 설정됩니다. 각 프로젝트는 고유한 색상을 가집니다.
  2. 요약: 문제, 구축된 것, 영향. 한두 문단 + 2-3개의 지표.
  3. 대화형 데모: 놀이터, 시뮬레이터, 라이브 목업, 호버 가능한 아키텍처 다이어그램. 포트폴리오의 쇼스토퍼. 코드 없이 작동해야 함.
  4. 의사 결정: 3-4개의 주요 선택. 각각: "문제"와 "해결책". 스택, 아키텍처, 트레이드오프에 대해 솔직해야 함.
  5. 결과: 긍정적인 경우 출시된 것, 배운 것, 지표. 숫자가 없는 경우, "더 나은 아키텍처" 대신 구체적인 기술적 교훈.
  6. 다음 프로젝트 / 연락처: 손으로 하는 핸드오프 + CTA.

7.3 404

같은 목소리와 모션. 코믹 또는 미니멀. "이 페이지는 존재하지 않습니다." + 검색 또는 홈으로 돌아가기.

PICO-8 풍선

 _____________________
< 이 페이지는 존재하지 않습니다 >
 ---------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

8. 성능 및 접근성

8.1 성능

  • preconnect + dns-prefetch 모든 타사 출처.
  • WebP/AVIF 이미지, <picture> 또는 loading="lazy".
  • GSAP gsap.quickTo 또는 네이티브 requestAnimationFrame 루프; 히어로 외부에 will-change를 피하세요.
  • Lenis: 랩탑에서 절대 30fps 아래로 떨어지지 않음.
  • Lighthouse: 모바일에서 95+ 성능, 100 접근성.
  • <link rel="preload"> 디스플레이 폰트.

8.2 접근성

  • min-height: 100svh 히어로는 모바일에서 콘텐츠를 자르지 않음.
  • 라이트-다크 모드: prefers-color-scheme에 대한 미디어 쿼리; 모든 테마는 완벽한 대비를 가짐. 다크 모드는 개념과 함께 작동해야 하는 경우에만 사용(예: 어두운 천문대). 밝은 배경이 기본.
  • 모든 스크롤 트리거는 키보드 포커스/ActiveElement를 존중합니다. ScrollTrigger는 포커스된 요소를 가리지 않음.
  • 전환: 모든 스크롤 트리거 이전에 계산된 respect-reduced-motion.
  • 키보드: 모든 것에 Tab 키; 건너뛰기 링크; aria-expanded 메뉴.
  • 모든 양식 입력에는 관련된 <label>이 있습니다.
  • <noscript>: 전체 포트폴리오 텍스트 요약 + 연락처 이메일 + 이력서 링크.

9. 검증 체크리스트

기준방법
오류 없음npx tsc --noEmit, npm run build가 성공
반응형390px 및 1440px에서 각 페이지. 내용이 360px 이하로 누락되지 않음
대비WCAG AA (4.5:1 텍스트, 3:1 큰 텍스트). DevTools 접근성 검사기
키보드Tab, Shift+Tab, Enter, Escape을 통한 전체 흐름. 포커스 링을 볼 수 있음
축소 모션window.matchMedia('(prefers-reduced-motion: reduce)')에서 모션 없음, 애니메이션 없음, 흐림 없음
오프라인 테스트3G 조절, WebGL 꺼짐, JS 꺼짐 (noscript 테스트)
소셜 카드og:image가 페이스북/트위터/슬랙에서 작동; summary_large_image
연락처 양식전송, 오류, 속도 제한, SMTP 누락
이력서/resume.pdf가 다운로드
배포Vercel/Netlify에서 성공. 사용자 정의 도메인이 설정된 경우 HTTPS가 리디렉션됨
SEO각 페이지의 고유 메타 설명; 페이지 제목에 "포트폴리오" 반복 없음 (대신 플래그십 이름)
curl 테스트```shell
curl https://yoursite.com/some-page
curl -I https://yoursite.com/some-page

관련 스킬