D-—정치 노잼인 거 아는데D-—그래도 1분만D-—내 동네 후보 누군지는 알고 찍자D-—정당 보고만 찍지 말기D-—팩트만 깔끔하게D-—이거 보고도 안 가면 어쩔 수 없고D-—정치 노잼인 거 아는데D-—그래도 1분만D-—내 동네 후보 누군지는 알고 찍자D-—정당 보고만 찍지 말기D-—팩트만 깔끔하게D-—이거 보고도 안 가면 어쩔 수 없고
노잼선거
← 메인
학습 가이드

공부하기

노잼선거 코드를 본인이 직접 설명할 수 있도록 정리한 학습 가이드. 백엔드(SpringBoot 등) 개발자가 풀스택으로 넘어가는 다리.

※ 위쪽: 10개 학습 영역 (코드 위치 + 공부 자료 + 체크 질문). 아래쪽: 면접 예상 질문 25개.

추천 학습 순서
  1. 먼저 필수 항목 4개 (Next.js · React · Vercel · 인증)
  2. 그다음 중요 항목 4개 (TS · Tailwind · Upstash · SEO)
  3. 마지막 보너스 2개 (데이터 처리 · UX 패턴)
  4. 각 항목 끝 체크 질문에 본인이 답할 수 있으면 다음으로
#1

Next.js 14 App Router

필수

왜 필요? 노잼선거의 라우팅·렌더링 모드·메타데이터 전부 App Router 기반. Server Component vs Client Component 차이를 모르면 코드 절반 못 읽는다.

노잼선거 어디에
  • app/page.tsx메인 페이지 — 서버 컴포넌트
  • app/[region]/page.tsx동적 라우팅 ([region])
  • app/api/votes/route.tsAPI Route — Edge runtime
  • components/RaceTabs.tsx"use client" 클라이언트 컴포넌트
  • components/DDayBadge.tsx클라이언트 컴포넌트 — 매분 갱신
이해 체크 질문
  • 왜 페이지에 `export const dynamic = "force-dynamic"` 을 썼나? (힌트: 마스킹 토글)
  • `generateMetadata`와 정적 `metadata` 객체 차이?
  • `use client`를 안 쓰면 무엇이 안 되나?
  • `cookies()` 함수를 클라이언트 컴포넌트에서 쓰면? (안 됨)
#2

React 기초 (Hooks)

필수

왜 필요? 백엔드 SpringBoot만 했다면 React useState/useEffect가 낯설다. 노잼선거 클라이언트 컴포넌트 거의 다 hooks 기반.

노잼선거 어디에
  • components/VoteWidget.tsxuseState · useEffect · fetch
  • components/Countdown.tsxsetInterval로 매초 갱신
  • components/RaceTabs.tsxURL hash·query 보는 useEffect
  • components/BoardClient.tsx페이징 + 폼 상태
이해 체크 질문
  • `useState`의 setter를 호출하면 컴포넌트가 어떻게 다시 렌더되나?
  • `useEffect`의 두 번째 인자(deps 배열) 의미?
  • Hydration mismatch는 왜 발생? 노잼선거에서 어떻게 해결?
  • 함수 컴포넌트에서 `this` 못 쓰는 이유?
#3

TypeScript

중요

왜 필요? Java/Spring과 비슷한 정적 타입이지만 구조적 타이핑·유니온 타입·제네릭이 더 유연. 노잼선거 전체가 TS.

노잼선거 어디에
  • data/types.tsCandidate · Race · Region 인터페이스
  • lib/mask.tsGeneric `maskEntry<T>` 함수
  • lib/districtRank.tsUnion 타입 `'wealth' | 'crim'`
이해 체크 질문
  • `interface`와 `type` 차이? 언제 어떤 거 쓰나?
  • `Candidate['partyKey']`처럼 타입에서 값 꺼내는 문법 의미?
  • `as unknown as Foo` 캐스팅을 왜 쓰나? 안전한가?
  • 제네릭 함수 `function f<T>(x: T): T` 의 T는 어떻게 추론되나?
#4

Tailwind CSS

중요

왜 필요? 노잼선거 전체 디자인이 Tailwind 유틸리티 클래스. 다크 배경·네온 그린 톤도 클래스 조합.

노잼선거 어디에
  • tailwind.config.ts색상 토큰 (paper, ink, neon) 정의
  • app/globals.css글로벌 + CSS 변수
  • components/Top5Teaser.tsx반응형 클래스 (sm:, md:)
  • components/RaceTabs.tsxsticky · backdrop-blur 등
이해 체크 질문
  • `sm:` `md:` 접두사 의미? 어떤 breakpoint?
  • `tracking-tightest` 같은 커스텀 클래스는 어디 정의?
  • Dark mode를 Tailwind에서 어떻게 지원? 노잼선거는?
  • `@apply` 디렉티브 언제 쓰면 안 좋나?
#5

Vercel 인프라

필수

왜 필요? 노잼선거 호스팅 전체가 Vercel. Edge Runtime, Hobby 한도, 환경변수, OG 이미지 동적 생성까지.

노잼선거 어디에
  • app/api/votes/route.ts`export const runtime = "edge"`
  • app/opengraph-image.tsx동적 OG 이미지 (next/og)
  • .env.local환경변수 (ADMIN_PASSWORD, KV_*)
이해 체크 질문
  • Edge Runtime과 Node.js Runtime 차이? 언제 어떤 거?
  • Vercel Hobby 무료 한도는? 노잼선거 사용량 대비 여유?
  • 환경변수가 빌드 시점에 박히는 것과 런타임에 읽히는 것 차이?
  • OG 이미지 캐시 무효화는 어떻게? (`revalidate = 3600`)
#6

Upstash Redis (Vercel KV)

중요

왜 필요? 투표 카운터·게시판·rate limit 모두 Upstash. REST API 기반 서버리스 Redis는 일반 Redis와 패턴이 다름.

노잼선거 어디에
  • lib/votes.tsRedis 클라이언트 초기화
  • lib/board.tsZADD · ZRANGE · INCR · EXPIRE
  • app/api/votes/route.tsGET / POST 핸들러
이해 체크 질문
  • Sorted Set (ZADD/ZRANGE) 왜 게시판에 썼나?
  • INCR + EXPIRE 조합으로 rate limit 어떻게 동작?
  • REST 기반 Redis가 일반 Redis와 다른 점?
  • 왜 Vercel KV가 무료 50MB에서 게시판 1만 글까지 OK?
#7

인증·보안

필수

왜 필요? 관리자 토글의 쿠키 기반 인증, rate limiting, 비번 해시·timing safe 비교, XSS 방지(escape) 등 보안 기초.

노잼선거 어디에
  • lib/auth.tsisAdmin() · cookieAttrs() · checkPassword()
  • app/api/admin/login/route.ts비번 검증 + 쿠키 설정 + rate limit
  • components/PostContent.tsx본문 HTML escape (XSS 방지)
  • lib/board.tscheckRateLimit()
이해 체크 질문
  • 쿠키의 `httpOnly` `secure` `sameSite` 각각 무엇을 막나?
  • 왜 ADMIN_PASSWORD와 ADMIN_TOKEN을 분리? (단순화 가능?)
  • Rate limit을 IP 기반으로 하는 것의 한계?
  • XSS 방지를 위해 사용자 입력을 어떻게 처리?
#8

SEO

중요

왜 필요? 노잼선거가 5일 만에 구글·네이버 검색 1위 한 핵심. 메타데이터·sitemap·OG 이미지·robots.txt·canonical URL.

노잼선거 어디에
  • app/layout.tsx글로벌 metadata (title template, OG, twitter)
  • app/recap/page.tsx페이지별 metadata + canonical
  • app/opengraph-image.tsx동적 OG 이미지
  • app/sitemap.ts동적 sitemap.xml 생성
이해 체크 질문
  • `alternates.canonical` 왜 중요?
  • OG 이미지 1200×630 권장 이유?
  • Sitemap.xml과 robots.txt가 SEO에 미치는 영향?
  • Vercel의 OG 이미지가 캐시되는 메커니즘?
#9

데이터 처리·정렬·필터링

보너스

왜 필요? 6,714명 후보 데이터를 메모리에서 정렬·집계. JavaScript Array methods 숙련도가 통계 페이지 전체 결정.

노잼선거 어디에
  • lib/overallStats.ts재산·전과·나이 Top N 함수들
  • lib/districtRank.ts구·시·군별 집계 + 랭킹
  • lib/uncontested.ts단독후보 추출 (Map + Set)
  • lib/searchCandidates.ts한글 자음(초성) 매칭 검색
이해 체크 질문
  • `map` / `filter` / `reduce` 각각 언제?
  • 한글 초성 추출 어떻게? (`0xAC00`, `588`의 의미)
  • Sort 함수의 비교 함수 작성 시 주의점?
  • Map과 Object 중 언제 무엇을 쓰나?
#10

UX·UI 패턴

보너스

왜 필요? URL hash·query 라우팅, 카드 자동 스크롤, sticky 탭, 다크모드 셀렉트 가독성 등. 작지만 사용자 경험 결정하는 디테일.

노잼선거 어디에
  • components/RaceTabs.tsx?cand= 쿼리 자동 스크롤
  • lib/candidateHref.tsbuildCandidateHref 공통 헬퍼
  • components/Marquee.tsx무한 스크롤 마키
  • components/RegionCard.tsx모달 패턴 (모바일 대응)
이해 체크 질문
  • URL `#hash` 와 `?query` 의 차이? 언제 어떤 거?
  • Sticky positioning의 `top-0`이 동작 안 할 때 원인은?
  • 다크모드에서 native `<select>` 옵션이 흰 배경 나오는 이유? 어떻게 해결?
  • Hydration 직전 깜빡임을 어떻게 줄이나?
실전

면접 예상 질문 25개

면접관 입장에서 이 프로젝트로 물어볼 만한 질문들. 답변을 미리 적어두고 시뮬레이션해보세요. ⭐는 자주 받는 핵심 질문.

A. 자기소개 · 프로젝트 개요
  1. ⭐ 노잼선거를 한 문장으로 설명해주세요. (엘리베이터 피치 — "1분만 보면 알 수 있게 만든 시민 선거 사이트")
  2. ⭐ 왜 이 프로젝트를 시작했어요? (개인 동기 + 시민 가치 둘 다)
  3. 혼자 만든 거예요? 팀이 몇 명?
  4. ⭐ 5일 만에 만든 거 맞나요? 어떻게 가능했어요? (AI 활용 솔직히 인정 + 의사결정은 본인)
B. 기술 스택 결정
  1. ⭐ 왜 Next.js 14 App Router를 선택했나요? Pages Router랑 차이는?
  2. 왜 Vercel? AWS·GCP 같은 다른 옵션은 고려 안 했나요?
  3. ⭐ 왜 6,714명 데이터를 정적 JSON으로 했나요? PostgreSQL·MySQL 안 쓰고?
  4. Upstash Redis와 일반 Redis 차이는? 왜 서버리스 KV?
  5. Tailwind CSS 선택 이유? styled-components·CSS Modules 비교했어요?
C. 아키텍처 결정
  1. ⭐ Server Component와 Client Component를 어떤 기준으로 나눴어요?
  2. 전체 데이터 흐름을 설명해주세요. 사용자 클릭부터 응답까지.
  3. ⭐ 관리자 인증 시스템 설계를 설명해주세요. (쿠키 + 환경변수 + rate limit)
  4. 마스킹 시스템의 트레이드오프는? 왜 클라이언트 마스킹이 아니라 서버 마스킹?
  5. Rate limiting 어떻게 구현했나요? Upstash 사용한 이유?
D. 문제 해결 (사건들)
  1. ⭐ 트래픽 폭증 시 어떻게 대응했나요? (Vercel Edge + ISR + 모니터링)
  2. ⭐ 어뷰징 사건이 있었다고 하던데 어떻게 발견·대응했나요? 막을 수 있었나요?
  3. D-day 카운트다운이 안 바뀌는 버그가 있었다고요? 원인은? 어떻게 해결?
  4. ⭐ 선관위 데이터가 사라진 후 개인정보 보호 어떻게 처리했나요?
  5. SSR Hydration mismatch 경험 있나요? 어떻게 디버깅?
E. 운영 · 마케팅 · 사용자
  1. ⭐ 어떻게 트래픽을 모았나요? 광고 없이 3,705명?
  2. 사용자 피드백을 어떻게 수집·반영했나요?
  3. SEO를 어떻게 신경 썼나요? 5일 만에 검색 1위가 가능?
F. AI 활용 · 시니어급 질문
  1. ⭐ AI(Claude Code 등)를 어디까지 활용했나요? 코드를 본인이 짠 게 아니라면 본인 프로젝트라고 할 수 있나요? (가장 첨예한 질문. 솔직 + 의사결정 강조)
  2. 이 프로젝트의 기술 부채는? 다시 만든다면 무엇을 바꿀 건가요?
  3. 스케일링 한계는 어디? 10만 명 동시 접속이면?
답변 작성 팁
  • STAR 구조: Situation → Task → Action → Result. 사건들 질문(D-day 버그·어뷰징 등)은 이 구조가 잘 맞음.
  • 트레이드오프 명시: "왜 X 선택?" → "Y와 비교했을 때 Z 이유로 X. 다만 W는 단점."
  • 숫자 인용: "트래픽 3,705명", "5일", "6,714명", "₩2,300/월" — 구체 숫자가 신뢰감.
  • AI 활용 솔직히: "프론트 코드는 Claude Code 도움을 많이 받았지만, 아키텍처·데이터 모델·보안 결정·운영은 제가 직접 했습니다." 이게 정답.
  • 모르는 거 인정: 모르면 "그 부분은 학습이 더 필요합니다, 다만 이렇게 추정합니다..." 솔직히. 면접관이 더 좋아함.
최종 점검

체크 질문 40개에 본인이 답할 수 있다면 — 노잼선거를 "본인 프로젝트"로 당당히 말할 수 있는 수준이에요. 모든 코드를 본인이 짠 게 아니라도, 모든 결정과 구조를 본인이 설명할 수 있다는 게 중요해요.

공부하다가 막히면 노잼선거 코드 직접 열어서 보거나, 해당 파일을 ChatGPT/Claude에 붙여넣고 "이거 왜 이렇게 짰어?" 물어보세요. AI 시대의 학습 방식.

공부하기 전에 회고나 구성도 다시 보고 싶으면

한 줄 평가

이 사이트 어땠어요?