백엔드 개발자를 위한 프론트엔드 실전 판단

이 문서는 프론트엔드 개발 중 자주 만나는 의사결정 질문을 모은 실전 사전이다. 각 주제 파일의 상세 섹션은 원리와 예시를 더 다루고, 이 문서는 “그래서 지금 무엇을 선택해야 하는가”에 집중한다.

짧은 답

  • 기본값은 HttpOnly, Secure, SameSite가 설정된 Cookie를 우선 검토한다.
  • localStorage는 구현은 쉽지만 XSS에 노출되면 토큰 탈취로 이어지므로 “편해서 선택”하기에는 위험하다.

판단 기준

  • 민감 데이터, 결제, 관리자 기능이 있으면 refresh token은 JavaScript로 읽을 수 없는 저장소에 둔다.
  • 단순 개인 프로젝트에서 위험도가 낮고 구현 속도가 중요하면 access token만 localStorage에 두는 선택도 가능하지만, 민감 기능이 생기는 순간 다시 설계해야 한다.
  • Cookie를 쓰면 CSRF와 CORS credentials 설정까지 함께 설계해야 한다.
  • 저장소 선택은 XSS 방어를 대체하지 않는다. HttpOnly Cookie를 써도 공격 스크립트가 같은 origin에서 인증된 요청을 보낼 수 있으므로 사용자 입력 렌더링, CSP, dependency 관리를 함께 본다.

백엔드와 맞춰야 할 것

  • Set-CookieHttpOnly, Secure, SameSite, Domain, Path, 만료 정책
  • CORS의 Access-Control-Allow-Credentials와 허용 origin
  • logout 시 refresh token 서버 무효화 방식

개인 프로젝트 기준

  • 로그인만 필요한 CRUD 서비스라도 사용자 개인정보가 있다면 Cookie 기반 세션 또는 Cookie 기반 refresh token을 우선 검토한다.
  • 배포 도메인이 프론트와 API로 나뉘면 SameSite와 CORS 설정을 초기에 같이 맞춘다.

위험 신호

  • access token과 refresh token을 둘 다 localStorage에 저장한다.
  • 사용자 입력 HTML 렌더링 방어 없이 토큰을 JavaScript 접근 가능 저장소에 둔다.
  • Cookie를 쓰면서 SameSite, CSRF token, Origin 검증 중 어떤 방어를 쓸지 정하지 않았다.

access token과 refresh token을 프론트에서 어떻게 다룰까?

짧은 답

  • access token은 짧게 살리고, refresh token은 더 안전한 저장소와 서버 무효화 정책으로 관리한다.

판단 기준

  • access token은 API 호출 인증용이고, refresh token은 access token 재발급 권한이다.
  • refresh token 탈취 피해가 더 크므로 저장소와 rotation 정책을 더 엄격히 본다.
  • access token을 메모리에만 두면 XSS 탈취면에서는 낫지만, 새로고침 시 복구 흐름이 필요하다.

백엔드와 맞춰야 할 것

  • access token 만료 시간과 refresh token 만료 시간
  • refresh token rotation 여부
  • 재발급 실패 시 응답 코드와 메시지

개인 프로젝트 기준

  • Cookie 기반 refresh token과 메모리 기반 access token 조합이 균형이 좋다.
  • 새로고침 후 access token 복구를 위해 /auth/me 또는 /auth/refresh 흐름을 준비한다.

위험 신호

  • access token 만료 시간이 너무 길다.
  • refresh token 재사용 탐지나 logout 무효화가 없다.
  • 프론트가 refresh token 값을 직접 읽어 권한 판단에 사용한다.

401이 났을 때 자동 재발급은 어디서 처리해야 할까?

짧은 답

  • API client 계층에서 한 번만 처리하고, 동시에 여러 요청이 refresh를 중복 호출하지 않게 막는다.

판단 기준

  • 컴포넌트마다 401 처리를 복사하지 않는다.
  • refresh 중에는 대기열을 두거나 단일 refresh promise를 공유한다.
  • refresh endpoint 자체는 자동 refresh 대상에서 제외해 무한 반복을 막는다.

백엔드와 맞춰야 할 것

  • access token 만료는 401, 권한 부족은 403처럼 구분한다.
  • refresh 실패 응답은 프론트가 즉시 logout 처리할 수 있게 일관적으로 준다.

개인 프로젝트 기준

  • fetch wrapper 또는 axios interceptor에 refresh 흐름을 둔다.
  • TanStack Query를 쓴다면 query retry와 refresh retry가 서로 무한 반복하지 않게 제한한다.

위험 신호

  • 401이 난 요청 수만큼 refresh 요청이 동시에 날아간다.
  • refresh endpoint까지 interceptor가 다시 refresh를 시도한다.
  • refresh 실패 후 query cache와 사용자 상태를 정리하지 않아 화면만 로그인 상태처럼 남는다.

서버 에러 메시지를 그대로 화면에 보여줘도 될까?

짧은 답

  • 사용자에게 보여줄 메시지와 개발자 디버깅 메시지는 분리한다.

판단 기준

  • validation error는 field 단위로 보여주는 것이 좋다.
  • 내부 예외 메시지, SQL, stack trace, 인프라 정보는 화면에 노출하지 않는다.
  • 같은 실패라도 사용자가 고칠 수 있는 오류와 잠시 후 다시 시도해야 하는 오류는 UI 메시지가 달라야 한다.

백엔드와 맞춰야 할 것

  • code, message, fieldErrors, traceId 같은 에러 응답 구조
  • 사용자 표시용 메시지와 로깅용 상세 정보 분리

개인 프로젝트 기준

  • 사용자에게는 짧은 메시지, 콘솔 또는 Sentry에는 traceId와 context를 남긴다.

위험 신호

  • error.message를 무조건 toast로 보여준다.
  • 서버 내부 예외 문장이 그대로 브라우저에 노출된다.
  • field error를 global toast로만 보여줘 사용자가 어느 값을 고쳐야 하는지 모른다.

form validation은 프론트와 백엔드 중 어디까지 해야 할까?

짧은 답

  • 프론트는 빠른 피드백과 UX를 담당하고, 백엔드는 최종 권위를 가진다.

판단 기준

  • required, length, format 같은 즉시 검사는 프론트에서 한다.
  • 중복 이메일, 권한, 재고, 금액 검증은 서버 검증이 최종이다.
  • 같은 규칙을 양쪽에 둘 때는 문서, schema, 테스트 중 하나로 drift를 줄여야 한다.

백엔드와 맞춰야 할 것

  • validation error 응답의 field path 규칙
  • 서버와 프론트가 공유할 수 있는 enum, 최소/최대 길이, format 정책

개인 프로젝트 기준

  • React Hook Form과 Zod로 client validation을 만들고, 서버 field error를 같은 UI에 매핑한다.

위험 신호

  • 프론트 검증이 있으니 서버 검증을 생략한다.
  • 서버 field name과 프론트 field name이 달라 에러를 매핑하지 못한다.

버튼 클릭 후 중복 요청은 어떻게 막을까?

짧은 답

  • submit pending 상태로 버튼을 비활성화하고, 서버는 멱등성까지 고려한다.

판단 기준

  • 사용자는 더블 클릭, 네트워크 지연, 뒤로가기, 재시도로 중복 요청을 만들 수 있다.
  • 프론트 방어는 UX 개선이고, 백엔드 멱등성은 데이터 안전 장치다.
  • 버튼 disable은 같은 화면의 중복 클릭을 줄일 뿐, 새로고침이나 네트워크 재전송까지 막지는 못한다.

백엔드와 맞춰야 할 것

  • 주문, 결제, 가입처럼 중복 생성이 치명적인 API의 idempotency key
  • 같은 요청 재시도 시 응답 정책

개인 프로젝트 기준

  • mutation pending 동안 버튼을 disable하고 loading label을 보여준다.
  • 결제나 주문은 백엔드에서 중복 요청을 막는다.

위험 신호

  • 버튼만 disable하고 네트워크 재시도나 새로고침 중복을 고려하지 않는다.
  • 생성 API가 중복 호출되어도 백엔드가 무조건 새 row를 만든다.

API 응답 DTO를 화면 모델로 그대로 써도 될까?

짧은 답

  • 작은 프로젝트에서는 가능하지만, 화면 상태가 섞이기 시작하면 view model로 변환한다.

판단 기준

  • 서버 DTO는 저장과 전송의 모델이고, 화면 모델은 표시와 상호작용의 모델이다.
  • 날짜 포맷, 선택 상태, disabled 이유, 계산된 label이 들어가면 변환 계층이 유리하다.
  • DTO를 그대로 쓰더라도 변환이 필요한 지점을 흩뿌리지 말고 API 경계나 hook 근처에 모은다.

백엔드와 맞춰야 할 것

  • API 응답 필드의 nullable, enum, 날짜 형식
  • 화면에 필요한 값이 서버에서 내려와야 하는지 프론트에서 계산해야 하는지

개인 프로젝트 기준

  • API 함수에서는 DTO 타입을 쓰고, 컴포넌트 직전에서 view model로 좁힌다.

위험 신호

  • API 응답 객체에 isSelected, isEditing 같은 UI 상태를 직접 섞는다.
  • nullable 필드를 화면 곳곳에서 매번 방어한다.

서버 상태를 useState에 넣는 것과 TanStack Query를 쓰는 것은 뭐가 다를까?

짧은 답

  • useState는 단순 값 보관이고, TanStack Query는 서버 상태의 cache, stale, refetch, invalidation을 관리한다.

판단 기준

  • 같은 데이터를 여러 화면에서 읽고 갱신한다면 query cache가 필요해진다.
  • loading, error, retry, staleTime, background refetch가 반복되면 라이브러리 도입 가치가 크다.
  • 서버 상태는 “가져온 시점”의 복사본이므로 stale 여부와 다시 가져올 조건을 설계해야 한다.

백엔드와 맞춰야 할 것

  • cache 가능성, 목록 갱신 조건, pagination cursor, ETag 또는 Last-Modified 사용 여부

개인 프로젝트 기준

  • 인증 사용자, 목록, 상세, 검색 결과는 TanStack Query로 관리한다.
  • 모달 open 여부, 입력 중인 값은 React state로 둔다.

위험 신호

  • 서버 데이터를 여러 컴포넌트의 useState에 복사해 서로 달라진다.
  • mutation 후 어느 query를 다시 가져와야 하는지 정해져 있지 않다.

전역 상태는 언제 필요한가?

짧은 답

  • 여러 화면이 공유하면서 서버 cache로 해결되지 않는 클라이언트 상태에 필요하다.

판단 기준

  • 인증 사용자 자체는 서버 상태일 수 있고, 테마나 sidebar open 여부는 클라이언트 상태다.
  • props drilling이 불편하다는 이유만으로 전역 상태를 만들면 변경 경로가 흐려진다.
  • 전역 상태가 필요한지보다 먼저 source of truth가 서버인지 브라우저인지 확인한다.

백엔드와 맞춰야 할 것

  • 사용자 권한, feature flag, 환경 설정처럼 전역처럼 쓰이는 값의 source of truth

개인 프로젝트 기준

  • 처음에는 local state와 Context로 시작하고, 복잡해지면 Zustand 같은 가벼운 store를 검토한다.

위험 신호

  • API 응답 전체를 전역 store에 복사한다.
  • 한 화면에서만 쓰는 값을 전역 상태에 넣는다.

URL query param에 상태를 넣어도 되는가?

짧은 답

  • 공유, 새로고침 복원, 뒤로가기 의미가 있는 상태는 URL에 두는 것이 좋다.

판단 기준

  • 검색어, filter, sort, page는 URL에 잘 맞는다.
  • 모달 내부 임시 입력값, 비밀번호, access token은 URL에 두면 안 된다.
  • URL에 넣은 값은 브라우저 history, 서버 로그, 분석 도구, 공유 링크에 남을 수 있다.

백엔드와 맞춰야 할 것

  • query parameter 이름, 기본값, 다중 값 표현, sort 문법

개인 프로젝트 기준

  • 목록 화면의 검색 조건은 URL query param으로 두고, form 입력 중 임시 값은 local state로 둔다.

위험 신호

  • 뒤로가기를 눌렀는데 검색 조건이 복원되지 않는다.
  • 민감 정보가 URL, 로그, referrer에 남는다.

짧은 답

  • 화면 local UI 상태는 가까운 곳에 두고, 앱 전역 알림은 공통 provider를 둔다.

판단 기준

  • 특정 카드의 confirm modal은 해당 화면 근처가 좋다.
  • toast는 여러 API 흐름에서 쓰므로 공통 인터페이스가 좋다.
  • loading은 직접 boolean을 복사하기보다 query, mutation, form submit 상태에서 파생하는 편이 안전하다.

백엔드와 맞춰야 할 것

  • API 실패 시 사용자가 복구 가능한 메시지와 재시도 가능 여부

개인 프로젝트 기준

  • loading은 query/mutation 상태에서 파생하고, toast는 공통 hook으로 감싼다.

위험 신호

  • 모든 modal open 상태를 전역 store에 넣는다.
  • loading boolean이 여러 곳에 복사되어 서로 맞지 않는다.

optimistic update는 언제 위험한가?

짧은 답

  • 실패 가능성이 낮고 rollback이 쉬운 상호작용에만 조심해서 쓴다.

판단 기준

  • 좋아요, 북마크처럼 되돌리기 쉬운 작업은 적합하다.
  • 결제, 권한 변경, 재고 차감처럼 실패 비용이 큰 작업은 보수적으로 처리한다.
  • 낙관적 UI를 쓰려면 실패 시 이전 cache로 되돌릴 수 있는 스냅샷이 있어야 한다.

백엔드와 맞춰야 할 것

  • mutation 실패 코드, 충돌 처리, 최신 상태 재조회 기준

개인 프로젝트 기준

  • optimistic update 후 실패하면 이전 cache로 rollback하고 toast를 보여준다.

위험 신호

  • 서버 실패 후 화면이 성공 상태로 남는다.
  • 권한이나 금액 같은 민감 상태를 optimistic하게 확정한다.

pagination, infinite scroll, search filter는 API와 어떻게 맞춰야 할까?

짧은 답

  • 프론트 UI 방식과 API의 page/cursor/filter/sort 계약을 함께 설계해야 한다.

판단 기준

  • 단순 관리자 목록은 page 기반이 편하다.
  • 실시간성이 있거나 feed 형태면 cursor 기반이 안정적이다.
  • 검색과 정렬 조건이 바뀌면 기존 page나 cursor를 초기화해야 중복과 누락을 줄일 수 있다.

백엔드와 맞춰야 할 것

  • page index가 0인지 1인지
  • totalCount, hasNext, nextCursor, sort 안정성
  • 검색어 debounce와 서버 부하 정책

개인 프로젝트 기준

  • 일반 목록은 page, feed는 cursor를 선택한다.
  • filter와 sort는 URL query param과 API query parameter를 맞춘다.

위험 신호

  • 프론트는 infinite scroll인데 API는 total page만 준다.
  • 같은 sort 조건인데 다음 페이지에서 중복이나 누락이 생긴다.

CORS 문제는 프론트 문제인가 백엔드 문제인가?

짧은 답

  • 브라우저 보안 정책 때문에 프론트에서 보이지만, 허용 정책은 백엔드가 응답 헤더로 결정한다.

판단 기준

  • Postman에서는 되는데 브라우저에서 안 되면 CORS나 Cookie credentials를 의심한다.
  • CORS는 서버 간 통신 문제가 아니라 브라우저가 enforcing하는 정책이다.
  • preflight는 실제 요청 전 브라우저가 서버의 허용 정책을 확인하는 별도 요청이다.

백엔드와 맞춰야 할 것

  • 허용 origin, method, header, credentials, preflight 응답
  • 인증이 필요한 API라도 preflight OPTIONS 요청은 브라우저의 허용 정책 확인용이므로, 인증 미들웨어에서 막히지 않게 처리한다.

개인 프로젝트 기준

  • 개발 환경과 운영 환경 origin을 분리해서 설정한다.

위험 신호

  • 운영에서 Access-Control-Allow-Origin: *와 credentials를 같이 쓰려 한다.
  • preflight 실패를 프론트 fetch 코드만 바꿔 해결하려 한다.

SameSite, Secure, HttpOnly 쿠키 설정을 프론트는 어떻게 이해해야 할까?

짧은 답

  • HttpOnly는 JavaScript 접근을 막고, Secure는 HTTPS 전송을 요구하며, SameSite는 cross-site 전송 여부를 제어한다.

판단 기준

  • refresh token cookie는 HttpOnly가 강력한 기본값이다.
  • cross-site 배포 구조에서는 SameSite=None; Secure가 필요할 수 있다.
  • 로컬 개발과 운영 HTTPS 환경의 Cookie 동작이 다를 수 있으므로 환경별 표를 만들어 둔다.
  • same-origin과 same-site는 다르다. app.example.comapi.example.com은 origin은 다르지만 site는 같을 수 있어, CORS와 SameSite를 각각 따로 판단해야 한다.

백엔드와 맞춰야 할 것

  • 프론트 도메인, API 도메인, HTTPS 여부, CORS credentials

개인 프로젝트 기준

  • 로컬 개발은 proxy 또는 same-site 개발 도메인으로 Cookie 문제를 단순화한다.

위험 신호

  • HTTPS가 아닌 운영 환경에서 Secure 쿠키를 기대한다.
  • HttpOnly 쿠키를 프론트 JavaScript에서 읽으려 한다.

SSR/CSR/SSG는 프로젝트 선택에 어떤 영향을 주는가?

짧은 답

  • SEO, 초기 로딩, 인증, 배포 복잡도에 영향을 준다.

판단 기준

  • 로그인 후 내부 서비스는 CSR SPA로 충분한 경우가 많다.
  • 공개 마케팅 페이지, 블로그, SEO가 중요하면 SSG 또는 SSR을 검토한다.
  • 사용자별 데이터를 SSR이나 CDN cache와 결합할 때는 cache key와 인증 경계를 특히 조심한다.

백엔드와 맞춰야 할 것

  • SSR 서버가 API를 호출할 때 인증 Cookie 전달 방식
  • cache 정책과 사용자별 데이터 분리

개인 프로젝트 기준

  • 관리형 CRUD, 포트폴리오성 앱은 Vite SPA로 시작한다.
  • 공개 콘텐츠와 SEO가 중요하면 Next.js를 검토한다.

위험 신호

  • SEO가 중요하지 않은 내부 앱에 SSR 복잡도를 먼저 도입한다.
  • 사용자별 데이터를 CDN cache로 잘못 공유한다.

Next.js가 필요한 프로젝트와 Vite SPA로 충분한 프로젝트는 어떻게 구분할까?

짧은 답

  • SSR/SSG, 파일 기반 라우팅, 이미지 최적화, 풀스택 라우트가 필요하면 Next.js를 검토하고, 빠른 SPA면 Vite가 단순하다.

판단 기준

  • 백엔드가 이미 있고 로그인 후 앱이면 Vite가 가볍다.
  • 공개 페이지와 앱이 섞이고 SEO가 중요하면 Next.js가 편하다.
  • Next.js를 선택하면 서버/클라이언트 컴포넌트 경계, runtime env, cache 정책까지 학습 범위에 들어온다.

백엔드와 맞춰야 할 것

  • API 서버와 프론트 서버의 배포 단위
  • 인증 Cookie를 어느 서버가 읽는지

개인 프로젝트 기준

  • 처음 React 학습과 빠른 CRUD는 Vite로 시작한다.
  • 블로그, 상품 상세, OG image, SSR 인증이 필요해지면 Next.js로 넓힌다.

위험 신호

  • Next.js를 쓰면서 서버/클라이언트 컴포넌트 경계를 이해하지 못한다.
  • Vite SPA로 SEO가 핵심인 공개 콘텐츠 서비스를 만든다.

UI 라이브러리를 쓰는 게 좋은가, 직접 만드는 게 좋은가?

짧은 답

  • 접근성 있는 기본 컴포넌트는 라이브러리를 쓰고, 제품 고유 표현은 직접 조합하는 편이 현실적이다.

판단 기준

  • Date picker, combobox, dialog, dropdown은 직접 만들수록 접근성 비용이 크다.
  • Button, Card, Badge 같은 단순 컴포넌트는 직접 만드는 것도 좋다.
  • 접근성이 어려운 컴포넌트는 headless library를 쓰고, 제품 고유 스타일은 wrapper에서 통제하는 방식이 실용적이다.

백엔드와 맞춰야 할 것

  • table pagination, filter, export 같은 데이터 UI 요구사항

개인 프로젝트 기준

  • Radix UI, shadcn/ui, MUI 같은 선택지를 비교하고, 디자인 일관성을 먼저 정한다.

위험 신호

  • 라이브러리 스타일을 억지로 덮어쓰느라 CSS가 더 복잡해진다.
  • 접근성이 필요한 컴포넌트를 클릭 이벤트만으로 직접 만든다.

Tailwind는 언제 생산적이고 언제 지저분해지는가?

짧은 답

  • 작고 일관된 디자인 토큰을 빠르게 적용할 때 생산적이고, 공통 패턴을 추출하지 않으면 markup이 지저분해진다.

판단 기준

  • spacing, color, typography 규칙이 명확하면 Tailwind가 빠르다.
  • 복잡한 상태와 variant가 많으면 component abstraction이 필요하다.
  • className이 길어지는 것 자체보다 같은 패턴이 여러 파일에 복사되는지가 유지보수 신호다.

백엔드와 맞춰야 할 것

  • 직접 맞출 것은 적지만, data table, 상태 badge, error UI 같은 서버 상태 표현은 API와 맞춘다.

개인 프로젝트 기준

  • Tailwind로 시작하되 반복되는 button/input/card/table은 컴포넌트로 묶는다.

위험 신호

  • 모든 화면에 긴 className을 복사해 수정 지점이 늘어난다.
  • 디자인 토큰 없이 임의 색상과 spacing이 계속 추가된다.

반응형은 CSS 문제인가 제품 요구사항 문제인가?

짧은 답

  • CSS 구현 문제이기 전에 어떤 정보와 행동을 작은 화면에서 우선할지 정하는 제품 요구사항이다.

판단 기준

  • 모바일에서 column으로 쌓는 것만으로는 충분하지 않다.
  • table, filter, navigation은 모바일 UX를 별도로 설계해야 한다.
  • 반응형은 “화면에 들어가게 하기”가 아니라 작은 화면에서도 핵심 행동을 완료하게 만드는 일이다.

백엔드와 맞춰야 할 것

  • 모바일 목록에서 필요한 최소 필드
  • 이미지 크기, 썸네일, page size

개인 프로젝트 기준

  • 핵심 경로는 360px 폭에서 먼저 확인한다.

위험 신호

  • desktop table을 모바일에서 가로 스크롤만으로 해결한다.
  • 터치 target이 너무 작고 focus 상태가 없다.

접근성은 어디까지 챙겨야 하는가?

짧은 답

  • semantic HTML, keyboard navigation, focus, label, color contrast는 기본 품질로 본다.

판단 기준

  • 버튼처럼 동작하면 button을 쓴다.
  • form input에는 label과 error 연결을 둔다.
  • 접근성 좋은 DOM은 Testing Library의 role, label 기반 테스트도 자연스럽게 만든다.

백엔드와 맞춰야 할 것

  • 에러 메시지와 상태 코드가 사용자가 이해할 수 있는 UI로 바뀔 수 있어야 한다.

개인 프로젝트 기준

  • Lighthouse만 믿지 말고 키보드만으로 핵심 흐름을 한 번 수행한다.

위험 신호

  • div에 onClick만 달아 버튼처럼 쓴다.
  • modal을 닫은 뒤 focus가 어디로 가는지 모른다.

프론트 성능 문제는 보통 어디서 생기는가?

짧은 답

  • 큰 bundle, 불필요한 re-render, 큰 이미지, 느린 API, 과도한 동기 작업에서 자주 생긴다.

판단 기준

  • 성능 문제는 프론트 코드만의 문제가 아니라 API 응답 크기와 cache 정책도 함께 본다.
  • 측정 없이 memoization부터 넣지 않는다.
  • 느린 화면은 Network, Performance, React DevTools 중 어디에서 병목이 보이는지 먼저 나눈다.

백엔드와 맞춰야 할 것

  • 필요한 필드만 내려주는 API, pagination, image size, cache header

개인 프로젝트 기준

  • Lighthouse, DevTools Performance, Network panel로 먼저 측정한다.

위험 신호

  • 목록 1페이지에 수천 row를 한 번에 내려준다.
  • 원본 이미지를 그대로 카드 썸네일로 쓴다.

이미지 최적화, code splitting, lazy loading은 언제 필요한가?

짧은 답

  • 초기 로딩에 필요하지 않은 큰 자원은 지연하고, 화면에 보이는 이미지는 크기와 포맷을 최적화한다.

판단 기준

  • route 단위 code splitting은 큰 앱에서 효과가 크다.
  • hero image나 목록 썸네일은 이미지 최적화의 우선순위가 높다.
  • lazy loading은 보이지 않는 자원을 늦추는 도구이지, 첫 화면 핵심 콘텐츠를 늦추는 면죄부가 아니다.

백엔드와 맞춰야 할 것

  • 이미지 원본, 썸네일, CDN, cache header, width/height metadata

개인 프로젝트 기준

  • route lazy loading과 이미지 width/height 지정부터 적용한다.

위험 신호

  • 3MB 이미지를 모바일 목록에서 여러 장 로드한다.
  • lazy loading 때문에 중요한 첫 화면 콘텐츠가 늦게 보인다.

테스트는 unit/component/e2e 중 무엇을 최소로 가져갈까?

짧은 답

  • 개인 프로젝트라도 핵심 유틸 unit test, 주요 컴포넌트 interaction test, 로그인과 CRUD e2e smoke test는 가치가 크다.

판단 기준

  • 알고리즘성 로직은 unit test, 사용자 상호작용은 component test, 실제 흐름은 e2e test가 맞다.
  • e2e는 실제 통합을 확인하는 데 강하지만 느리고 취약하므로 핵심 경로를 얇게 잡는다.

백엔드와 맞춰야 할 것

  • 테스트용 API fixture, mock server, seed data, test account

개인 프로젝트 기준

  • React Testing Library와 MSW로 컴포넌트 테스트를 만들고, Playwright로 핵심 happy path만 e2e로 둔다.

위험 신호

  • 구현 세부 DOM 구조만 테스트한다.
  • mock이 실제 API 계약과 달라 테스트가 통과해도 운영에서 깨진다.

프론트 배포에서 env 변수는 왜 빌드 타임/런타임 구분이 중요한가?

짧은 답

  • Vite 같은 정적 빌드는 env 값이 빌드 결과물에 박히므로, 배포 후 런타임 변경이 되지 않을 수 있다.

판단 기준

  • 브라우저에 전달되는 env는 secret이 아니다.
  • API base URL처럼 환경별 값은 빌드 파이프라인과 배포 단위를 함께 설계한다.
  • 정적 배포라면 “지금 서버 env”가 아니라 “그 bundle을 만들 때의 env”가 사용자에게 전달된다.

백엔드와 맞춰야 할 것

  • dev/stage/prod API URL, CORS origin, Cookie domain

개인 프로젝트 기준

  • VITE_ prefix 값은 공개 설정으로 보고, secret은 서버나 배포 플랫폼 secret에 둔다.

위험 신호

  • 브라우저 bundle 안에 API secret이나 private key가 들어간다.
  • 운영 배포 후 env만 바꾸면 프론트 설정이 바뀐다고 생각한다.

API 계약은 Swagger/OpenAPI만 있으면 충분한가?

짧은 답

  • OpenAPI는 시작점이고, 에러, nullable, enum, pagination, 예시 데이터, 변경 정책까지 합의해야 충분하다.

판단 기준

  • 프론트 개발자는 성공 응답보다 실패 응답과 경계값에서 시간을 많이 쓴다.
  • 문서와 실제 응답이 다르면 문서는 신뢰를 잃는다.
  • OpenAPI가 있어도 예시 응답, error schema, nullable 정책, mock이 실제와 다르면 협업 비용은 줄지 않는다.
  • OpenAPI로 생성한 TypeScript 타입은 컴파일 타임 도움이지, 브라우저가 받은 JSON을 자동 검증하는 런타임 방어막은 아니다.

백엔드와 맞춰야 할 것

  • success/error schema, field error, enum 확장, deprecation, mock server

개인 프로젝트 기준

  • OpenAPI를 만들고 MSW handler나 타입 생성으로 계약을 코드에 연결한다.

위험 신호

  • 문서에는 non-null인데 실제로 null이 온다.
  • 에러 코드는 있지만 사용자가 무엇을 해야 하는지 알 수 없다.

프론트 개발자가 백엔드에게 가장 답답해하는 API는 어떤 API인가?

짧은 답

  • 화면 상태를 만들기 어렵고, 실패 처리와 경계값이 불명확하며, 일관성이 없는 API다.

판단 기준

  • nullable이 불명확하고, enum이 문자열 자유 입력처럼 오며, pagination metadata가 부족하면 화면이 흔들린다.
  • 날짜와 타임존, 권한별 필드 노출, 에러 메시지 정책이 없으면 디버깅 비용이 커진다.
  • 프론트가 loading, empty, error, disabled, permission denied 상태를 만들 수 없는 API는 화면 구현 시간을 크게 늘린다.

백엔드와 맞춰야 할 것

  • 표준 응답 형식, field naming, error code, timezone, pagination, sorting, filtering

개인 프로젝트 기준

  • API를 만들 때 화면의 loading, empty, error, disabled 상태를 같이 상상한다.

위험 신호

  • 같은 종류의 API가 매번 다른 응답 wrapper를 쓴다.
  • 200 OK 안에 비즈니스 실패를 숨긴다.

참고 문서