웹 개발 기초집LESSON 30
반응형 개인 포트폴리오 완성하기
난이도입문
예상 시간25분
선수지식이전 강의
30강. 반응형 개인 포트폴리오 완성하기
이번 강의의 결과물은 소개, 기술 목록, 필터 가능한 프로젝트, 연락 링크를 갖추고 모바일에서도 사용할 수 있는 반응형 개인 포트폴리오입니다.
1. 이번 강의에서 해결할 문제
지금까지 HTML, CSS, JavaScript, Git, HTTP를 각각 연습했지만 실제 프로젝트에서는 이 기술들이 함께 동작합니다. 새 문법을 더 배우는 대신 기존 개념을 하나의 작은 제품으로 연결하고, 다른 사람에게 보여 줄 수 있는 완료 기준을 세웁니다.
학습 목표
- 지금까지 HTML, CSS, JavaScript, Git, HTTP를 각각 연습했지만 실제 프로젝트에서는 이 기술들이 함께 동작합니다. 새 문법을 더 배우는 대신 기존 개념을 하나의 작은 제품으로 연결하고, 다른 사람에게 보여 줄 수 있는 완료 기준을 세웁니다.
- 핵심 개념을 코드 예시와 짧은 실습에 적용하고 결과를 설명합니다.
2. 핵심 개념
최종 프로젝트에서는 기술보다 먼저 각 파일의 책임을 정합니다.
HTML 콘텐츠 구조와 접근 가능한 이름
CSS 시각 표현과 반응형 레이아웃
JSON 프로젝트 데이터
JavaScript 데이터 요청, DOM 생성, 필터 상태와 이벤트
Git 변경 이력과 배포할 버전
HTTP 로컬 실행과 배포 파일 전달
완성된 예제는 projects/personal-portfolio에 있습니다. 구조는 다음과 같습니다.
projects/personal-portfolio/
├─ index.html
├─ README.md
├─ css/
│ └─ styles.css
├─ data/
│ └─ projects.json
└─ js/
├─ main.js
├─ data/
│ └─ load-projects.js
└─ ui/
└─ render-projects.js
3. 코드 예시
파일명: index.html
시맨틱 구역과 필터 컨트롤을 배치합니다.
<main id="main-content">
<section class="hero" aria-labelledby="hero-title">
<h1 id="hero-title">게임의 상호작용과 웹의 경험을 만듭니다.</h1>
</section>
<section id="projects" aria-labelledby="projects-title">
<h2 id="projects-title">프로젝트</h2>
<div class="filter-list" aria-label="프로젝트 분류">
<button type="button" data-filter="all" aria-pressed="true">전체</button>
<button type="button" data-filter="game" aria-pressed="false">게임</button>
<button type="button" data-filter="web" aria-pressed="false">웹</button>
</div>
<p id="project-status" role="status">프로젝트를 불러오는 중입니다.</p>
<div id="project-list"></div>
</section>
</main>
파일명: css/styles.css
넓은 화면에서는 두 열, 좁은 화면에서는 한 열로 바꿉니다.
.project-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1rem;
}
:focus-visible {
outline: 3px solid var(--color-accent);
outline-offset: 4px;
}
@media (max-width: 42rem) {
.project-grid {
grid-template-columns: 1fr;
}
}
파일명: js/main.js
JSON 데이터를 불러온 뒤 현재 필터에 맞는 카드만 렌더링합니다.
import { loadProjects } from "./data/load-projects.js";
import { renderProjects } from "./ui/render-projects.js";
const state = { projects: [], filter: "all" };
function getVisibleProjects() {
if (state.filter === "all") return state.projects;
return state.projects.filter((project) => project.category === state.filter);
}
state.projects = await loadProjects();
renderProjects(getVisibleProjects(), document.querySelector("#project-list"));
실행 위치: D:\WebProject\StartBook\dev-foundations\projects\personal-portfolio
python -m http.server 5500
브라우저에서 http://localhost:5500을 엽니다.
4. 코드가 동작하는 이유
- 시맨틱 HTML이 소개, 프로젝트, 연락 영역의 의미와 탐색 기준을 만듭니다.
- CSS Grid와 미디어 쿼리가 같은 콘텐츠를 화면 너비에 맞게 재배치합니다.
- 모듈 진입점인
main.js가 데이터 요청과 UI 모듈을 연결합니다. load-projects.js는 HTTP 응답 확인과 JSON 변환만 담당합니다.render-projects.js는 받은 데이터를 안전하게textContent로 DOM에 표시합니다.- 필터 버튼은 상태를 바꾸고 같은 렌더링 함수를 다시 호출합니다.
aria-pressed,role="status",:focus-visible이 키보드와 보조 기술 사용자를 위한 상태 정보를 제공합니다.
파일 책임이 나뉘어 있으므로 프로젝트 정보를 바꿀 때 JSON을, 화면 구조를 바꿀 때 HTML을, 카드 생성을 바꿀 때 UI 모듈을 찾을 수 있습니다.
5. 자주 하는 실수
- 예제 이름과 설명을 자신의 정보로 바꾸지 않고 배포함
- 큰 화면만 확인하고 카드가 좁은 화면 밖으로 넘치는지 놓침
- 필터의 시각 상태만 바꾸고
aria-pressed를 갱신하지 않음 - JSON 요청 실패 시 빈 화면만 표시함
- 데이터 문자열을 불필요하게
innerHTML에 넣음 - 프로젝트마다 역할, 사용 기술, 해결한 문제를 설명하지 않음
- 로컬에서 수정한 뒤 커밋과 push를 빠뜨려 배포본이 바뀌지 않음
6. 짧은 실습 과제
projects/personal-portfolio예제를 로컬 서버로 실행합니다.index.html의 소개와 GitHub 링크를 자신의 정보로 수정합니다.data/projects.json의 네 항목을 실제 또는 계획 중인 프로젝트로 교체합니다.:root의 색상 변수 세 개를 바꿔 자신만의 분위기를 만듭니다.- 전체, 게임, 웹 필터를 마우스와 키보드로 각각 확인합니다.
- 브라우저 폭을 줄여 카드가 한 열이 되는지 확인합니다.
- Network와 Console 탭에 실패가 없는지 확인합니다.
- 변경을 기능별 커밋으로 나누고 29강 방식으로 배포합니다.
완료 기준:
- 320px 정도의 좁은 화면과 데스크톱에서 가로 스크롤이 생기지 않음
- 제목 계층과 시맨틱 영역이 자연스러움
- Tab 키로 모든 링크와 버튼을 조작할 수 있음
- 프로젝트 필터와 상태 안내가 정확히 갱신됨
- JSON을 불러오지 못해도 오류 안내가 표시됨
- 공개 URL에서 CSS, JavaScript, JSON 요청이 모두 성공함
- README에 실행 방법과 프로젝트 목적이 적혀 있음
7. 이해 점검 질문 3개
- 최종 프로젝트에서 HTML, CSS, JSON, JavaScript는 각각 어떤 책임을 가지나요?
- 필터 버튼의 시각적 선택 상태와 접근성 상태를 함께 유지하려면 무엇을 갱신해야 하나요?
- 로컬에서는 동작하지만 배포 후 JSON만
404라면 어떤 경로와 Git 상태를 확인해야 하나요?
핵심 요약
- 이번 강의의 핵심 개념을 코드의 구조와 실행 결과에 연결했습니다.
- 코드 예시를 직접 바꾸는 짧은 실습으로 핵심 동작을 확인했습니다.
- 이해 점검 질문에 답하며 다음 강의에 필요한 기준을 정리했습니다.
MINI QUIZ
0 / 2반응형 개인 포트폴리오 완성하기 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
LESSON STATUS
30강. 반응형 개인 포트폴리오 완성하기 미완료 상태학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.