프론트엔드 면접대비 시험지 PDF 다운로드

프론트엔드 면접대비
1/ 1 페이지A4 출력 미리보기
드래그하거나 버튼으로 페이지 이동
💡 최적 출력을 위한 프린트 설정
용지크기: A4 • 여백: 기본 • 배경그래픽: 체크 • 머릿말/바닥글: 사용안함
일부 브라우저(카카오톡 인앱브라우저 등)에서는 출력이 제대로 되지 않을 수 있어요 — Chrome 브라우저 사용을 권장합니다.
문제 1

Redux나 다른 상태 관리 라이브러리 대신 Zustand를 선택했나요

정답 및 해설

- 가벼운 번들사이즈

- 커스텀 훅 방식으로 React 패턴과 일치

- 보일러플레이트 최소화: 액션, 리듀서 없이 직관적인 API

- persist 미들웨어: 장바구니 데이터 영속화가 간단함

문제 2

액션, 리듀서에 대해 설명해보세요.

정답 및 해설

액션(Action)

상태 변경을 설명하는 명령서 객체

"무엇이 일어났는지"를 설명하는 type과 필요한 데이터(payload) 포함


const incrementAction = { type: 'INCREMENT' }

const addTodoAction = {

type: 'ADD_TODO',

payload: { id: 1, text: '할일 추가' }

}



리듀서(Reducer)

현재 상태와 액션을 받아서 새로운 상태를 반환하는 순수 함수

"상태를 어떻게 변경할지"의 로직을 담당


const counterReducer = (state = { count: 0 }, action) => {

switch (action.type) {

case 'INCREMENT':

return { count: state.count + 1 }

case 'DECREMENT':

return { count: state.count - 1 }

default:

return state

}

}


플로우

컴포넌트에서 액션 디스패치 리듀서가 현재 상태 + 액션으로 새 상태 계산 스토어 업데이트 후 구독 중인 컴포넌트들 리렌더링

특징:

예측 가능: 같은 입력에 항상 같은 출력

불변성: 기존 상태를 변경하지 않고 새 객체 반환

디버깅 용이: 모든 상태 변경이 액션으로 기록됨

문제 3

SWR vs React-Query

정답 및 해설

캐싱 기능이 있어 동일한 요청 시 네트워크 요청을 줄이고 성능 최적화를 지원한다


SWR:

가벼움: 4KB로 React Query보다 훨씬 작아서 초기 로딩 성능에 유리했습니다.

개발 속도: 복잡한 설정 없이 바로 사용 가능해서 프로토타이핑이 빨랐습니다


React Query: 데이터 캐싱 및 상태 관리를 세밀하게 제어해야 하거나 복잡한 애플리케이션에서 서버 상태를 효율적으로 관리해야 할 때 적합하다.


1. 계층적 캐시 무효화

queryClient.invalidateQueries({queryKey:['posts']})


2. 조건부 캐시 관리

queryClient.invalidateQueries({predicate:(query)=> query.queryKey[0]==='posts'&& query.queryKey[2]?.status ==='draft'})


3. 낙관적 업데이트

서버 응답 전에 UI 먼저 업데이트하고, 실패 시 롤백

SWR은 기본 지원하지 않아 수동 구현 필요


4. 메모리 기반 가비지 컬렉션

사용하지 않는 캐시를 자동으로 정리

쿼리별로 다른 캐시 유지 시간 설정 가능

문제 4

서버컴포넌트와 클라이언트컴포넌트를 비교해서 설명해보세요.

정답 및 해설

먼저 서버 컴포넌트는 말 그대로 서버에서 실행되는 컴포넌트입니다. 서버에서 렌더링이 끝나고 HTML이 완성된 상태로 클라이언트에 전달되죠. 그래서 번들 사이즈가 작아지고 초기 로딩 속도가 빨라지는 장점이 있어요. 또한 데이터베이스나 파일시스템 같은 백엔드 리소스에 직접 접근할 수 있습니다.

반면에 클라이언트 컴포넌트는 우리가 기존에 사용하던 React 컴포넌트와 같다고 보시면 됩니다. 브라우저에서 실행되고, useState나 useEffect 같은 훅들을 사용할 수 있어요. 사용자와의 상호작용도 처리할 수 있죠.

가장 큰 차이점은 서버 컴포넌트는 상태 관리나 이벤트 핸들링을 할 수 없다는 점입니다. 그래서 실제 프로젝트에서는 두 컴포넌트를 적절히 조합해서 사용하게 되는데요, 정적인 데이터 표시는 서버 컴포넌트로, 동적인 상호작용이 필요한 부분은 클라이언트 컴포넌트로 나누어 구현합니다.

문제 5

서버에서 만들어서 html로 전달한다고 했는데, 어떤형태로 전달되는건지 말해주세요

정답 및 해설

HTML이라고 표현했는데 정확히는 HTML이 아니에요.

서버 컴포넌트는 RSC Payload라는 특별한 형태로 전달됩니다. 이건 JSON과 비슷한 직렬화된 데이터 형태인데요, React가 이해할 수 있는 컴포넌트 트리 정보를 담고 있어요

문제 6

스트리밍 컴포넌트에 대해 알고 있나요

정답 및 해설

스트리밍을 사용하면 컴포넌트가 준비되는 대로 부분적으로 클라이언트에 전송할 수 있습니다.

Next.js에서는 Suspense 경계와 함께 사용

이렇게 하면 SlowComponent가 로딩되는 동안 Loading 컴포넌트를 보여주고, 준비되면 실제 컴포넌트로 교체됩니다.

장점은 사용자가 더 빨리 콘텐츠를 볼 수 있다는 거예요. TTFB(Time to First Byte)는 빨라지고, 전체적인 사용자 경험이 개선되죠. 특히 느린 데이터 페칭이 있는 컴포넌트가 전체 페이지를 블로킹하지 않게 됩니다.


병렬 + 논블로킹 + 점진적 전송

블로킹하지 않고 독립적으로 처리한다"

문제 7

스트리밍 컴포넌트를 사용하면 초기 번들사이즈를 줄일 수 있나요?

정답 및 해설

스트리밍은 서버에서 클라이언트로 HTML을 전송하는 방식에 관한 것이고, 번들 사이즈는 JavaScript 파일의 크기에 관한 문제거든요.

문제 8

칸반 보드를 구현하실때 웹소켓을 구현하셨는데요,

SSE나 WebRTC 등을 고려해보셨나요??

웹소켓을 선택한 이유가 뭘까요

정답 및 해설

SSE(Server-Sent Events)를 고려했지만:

- SSE는 서버에서 클라이언트로만 단방향 통신이에요

- 칸반 보드는 사용자가 카드를 드래그하거나 수정할 때 실시간으로 서버에 데이터를 보내야 하거든요

- 그러면 결국 SSE + AJAX 조합을 써야 하는데, 이게 오히려 복잡해져요


웹소켓을 선택한 이유:

양방향 통신

사용자 액션을 서버로 즉시 전송하고, 다른 사용자들에게 실시간 브로드캐스트 낮은 레이턴시

HTTP 오버헤드 없이 바로 메시지 교환 상태 유지

연결이 유지되어서 사용자가 온라인/오프라인 상태 관리도 쉬워요 구현 단순성

Socket.io 같은 라이브러리로 쉽게 구현 가능

칸반 보드처럼 실시간 협업이 핵심인 서비스에는 웹소켓이 가장 적합한 선택이었어요.

문제 9

그렇다면, 웹소켓에서 권한관련 처리는 어떻게 진행하셨나요

정답 및 해설

연결 단계에서 토큰을 메세지로 보내서 권한을 체크했다

문제 10

토근 갱신처리는 어떤 시점에 이루어졌나요

정답 및 해설

서버측에서 토큰만료시간이 다가올때쯤 emit('token-refresh-required')을 보내고

프론트에서 socket.on('refresh-token',(newToken)=>{const user =verifyJWT(newToken);if(user){ socket.user={...socket.user,token: newToken };}});

으로 재검증을 요청하는 식으로 했습니다.

문제 11

프론트에서 사용하는 소켓 메소드에 대해 설명해보세요

정답 및 해설

이벤트 발신 (emit)

이벤트 수신 (on)


칸반 보드에서는 주로 emit으로 카드 이동을 서버에 알리고, on으로 다른 사용자의 변경사항을 받아서 UI를 업데이트했어요.

문제 12

소켓으로 어떤식으로 구현하였나

정답 및 해설

낙관적 업데이트였어요. 사용자가 카드를 드래그하면 서버 응답을 기다리지 않고 일단 UI를 바로 업데이트해서 부드러운 사용자 경험을 제공하는 거죠. 그리고 만약 서버에서 거부되면 롤백하는 방식으로 처리했습니다.

문제 13

소켓구현에서 어려웠던점

정답 및 해설

여러 명이 동시에 같은 컬럼을 수정할 때 인덱스 충돌

서버에서 최종 상태를 관리하고 클라이언트는 그에 맞춰 조정하는 방식으로 해결했습니다.



드래그 중 충돌 방지

드래그 상태 기반 업데이트 필터링

현재 사용자가 카드를 드래그하고 있는 동안에는 해당 카드에 대한 다른 사용자의 업데이트를 임시로 무시하고, 현재 사용자의 액션이 끝났을 때 데이터를 업데이트 하는 방식으로 동시성 문제를 보완했습니다.


현재 사용자의 액션을 최우선으로 보장하면서도 데이터 일관성은 유지할 수 있었

문제 14

모노레포와 멀티레포의 차이와 장단점에 대해 설명해주세요

정답 및 해설

모노레포 (Monorepo): 하나의 저장소에 여러 프로젝트나 패키지를 관리하는 방식이에요. 예를 들어 웹앱, 모바일앱, 공통 라이브러리를 모두 하나의 Git 저장소에서 관리하는 거죠.


멀티레포 (Multirepo): 각 프로젝트마다 별도의 저장소를 만들어서 독립적으로 관리하는 전통적인 방식입니다.


모노레포 장점:

코드 공유가 쉬워요. 공통 컴포넌트나 유틸을 바로 import 할 수 있거든요

의존성 관리가 일관성 있게 가능하고

전체 프로젝트를 한 번에 리팩토링할 수 있어요

배포 파이프라인을 통합해서 관리할 수 있고요

모노레포 단점:

저장소 크기가 커져서 클론 시간이 오래 걸리고

빌드 시간이 길어질 수 있어요

권한 관리가 복잡해지죠

멀티레포 장점:

각 팀이 독립적으로 작업할 수 있고

저장소가 가벼워서 빠르고

기술 스택을 자유롭게 선택할 수 있어요

멀티레포 단점:

공통 코드 공유가 복잡하고

의존성 버전 관리가 어려워요

실제로는 팀 규모와 프로젝트 성격에 따라 선택하게 되는 것 같아요.

문제 15

모노레포를 구현하셨다고 하셨는데,

터보레포를 선택하신 이유가 있을까요?

정답 및 해설

- 가장 큰 이유는 캐싱과 병렬 처리였습니다. 변경되지 않은 패키지는 다시 빌드하지 않고 캐시를 사용해서 빌드 시간이 엄청 단축됐거든요. 특히 여러 프로젝트가 있을 때 이 효과가 확실했어요.


- turbo.json 파일 하나로 파이프라인을 정의할 수 있어서 러닝 커브가 낮았습니다.


-Vercel에서 만들어서 Next.js와의 호환성도 뛰어났다.

문제 16

pnpm 을 사용한 이유가 있을까요

정답 및 해설

 모노레포 지원이 훌륭했어요. 기능이 직관적이고, 터보레포와의 조합도 완벽했습니다.


pnpm의 디스크 효율성과 빠른 설치 속도


디스크 효율성: 모노레포에서는 여러 패키지가 같은 라이브러리를 사용하는 경우가 많아요. 예를 들어 web-app, mobile-app, admin-app이 모두 React를 사용한다면:

npm/yarn: React가 3번 설치됨 (각 패키지마다)

pnpm: React가 1번만 저장되고 하드링크로 공유


 pnpm은 패키지를 중앙 저장소에 한 번만 저장하고, 각 프로젝트에서는 하드링크로 참조하는 방식으로 디스크 공간을 절약

하드링크는 하나의 파일을 여러 경로에서 참조할 수 있게 해주는 파일시스템 기능


1. 의존성 호이스팅: 공통으로 사용하는 라이브러리는 루트에서 한 번만 설치하고 공유해요.

2. 내부 패키지 참조: web-app에서 ui-components를 바로 import할 수 있어요. 별도로 npm에 배포하지 않아도 되죠.

3. 통합 명령어:

문제 17

 웹소켓이 무엇이고 HTTP와 어떤 차이가 있나요?

정답 및 해설

A: 웹소켓은 클라이언트와 서버 간에 지속적인 양방향 통신을 가능하게 하는 프로토콜입니다. HTTP는 요청-응답 기반의 단방향 통신이지만, 웹소켓은 한 번 연결되면 지속적으로 양방향으로 데이터를 주고받을 수 있습니다. HTTP는 매번 요청 시 헤더 오버헤드가 크지만, 웹소켓은 초기 핸드셰이크 후에는 오버헤드가 적어 효율적입니다.

문제 18

웹소켓 연결 과정을 설명해주세요.

정답 및 해설

웹소켓 연결은 HTTP 업그레이드 핸드셰이크로 시작됩니다. 클라이언트가 HTTP GET 요청에 Upgrade 헤더를 포함해서 보내면, 서버가 101 Switching Protocols로 응답하며 프로토콜이 HTTP에서 웹소켓으로 전환됩니다. 이후 지속적인 양방향 통신이 가능해집니다.

문제 19

 웹소켓 성능 최적화 방법은?

정답 및 해설

메시지 배치 처리로 여러 메시지를 한 번에 보내고, 연결 풀링으로 여러 연결을 관리하며, 압축을 사용해서 데이터 크기를 줄입니다. 또한 불필요한 메시지 전송을 피하고, 적절한 하트비트 간격을 설정해서 연결을 유지합니다.

문제 20

Socket.IO와 네이티브 웹소켓의 차이는?

정답 및 해설

: 네이티브 웹소켓은 브라우저 내장 API로 가볍지만 기본 기능만 제공합니다. Socket.IO는 자동 재연결, 하트비트, 폴백 메커니즘, 룸 기능 등을 제공하지만 추가 라이브러리가 필요해서 번들 크기가 커집니다. 프로젝트 요구사항에 따라 선택해야 합니다.

문제 21

웹소켓 연결 문제를 어떻게 디버깅하나요?

정답 및 해설

브라우저 개발자 도구의 Network 탭에서 웹소켓 연결 상태를 확인하고, Console에서 에러 메시지를 점검합니다. 연결 상태 변화를 로깅하고, 헬스체크(ping/pong)을 구현해서 연결 품질을 모니터링합니다. 서버 로그와 클라이언트 로그를 함께 분석해서 문제점을 파악합니다.

문제 22

웹소켓 연결이 자주 끊어지는 문제는 어떻게 해결하나요?

정답 및 해설

A: 네트워크 환경, 프록시 설정, 방화벽 정책을 점검하고, 하트비트 간격을 조정합니다. 모바일에서는 백그라운드 상태나 네트워크 전환 시 연결이 끊어질 수 있으므로 적절한 재연결 로직이 필요합니다. keep-alive 설정을 조정하거나 더 짧은 타임아웃을 설정할 수도 있습니다.

문제 23

HTTP의 오버헤드

정답 및 해설

HTTP 요청 시마다 발생하는 추가 비용:

헤더 정보: 매 요청마다 User-Agent, Accept, Cookie, Content-Type 등의 헤더가 포함됨 (보통 500바이트~2KB)

연결 설정: TCP 3-way handshake + TLS handshake (HTTPS의 경우)

연결 해제: 요청 완료 후 연결을 닫는 과정

상태 정보: HTTP는 stateless라서 매번 인증 정보 등을 다시 보내야 함

예시: "안녕"이라는 4바이트 메시지를 보내도, HTTP 헤더까지 포함하면 실제로는 1KB 이상이 전송됨

웹소켓의 낮은 오버헤드

초기 연결 후 발생하는 비용:

프레임 헤더: 메시지마다 단 2-14바이트의 작은 헤더만 추가됨

연결 유지: 한 번 연결되면 계속 사용, 매번 새로 연결할 필요 없음

상태 유지: 연결이 지속되므로 인증 정보 등을 매번 보낼 필요 없음

예시: "안녕" 메시지를 보낼 때 실제로 6-18바이트 정도만 전송됨 (메시지 4바이트 + 헤더 2-14바이트)

실제 차이

HTTP: 작은 메시지도 매번 큰 헤더와 함께 전송 → 비효율적

웹소켓: 작은 헤더만 추가되므로 순수한 데이터 비율이 높음 → 효율적

특히 실시간으로 작은 메시지를 자주 주고받는 상황에서 이 차이가 크게 납니다. 채팅처럼 짧은 메시지를 많이 보내는 경우 웹소켓이 HTTP보다 대역폭을 훨씬 적게 사용하게 됩니다.

문제 24

React가 무엇이고 왜 사용하나요

정답 및 해설

React는 Facebook에서 개발한 사용자 인터페이스를 구축하기 위한 JavaScript 라이브러리입니다. 컴포넌트 기반 아키텍처로 재사용 가능한 UI 요소를 만들 수 있고, Virtual DOM을 통해 효율적인 렌더링을 제공합니다. 단방향 데이터 플로우로 예측 가능한 상태 관리가 가능하며, 큰 개발자 커뮤니티와 풍부한 생태계를 제공합니다.

문제 25

Virtual DOM이 무엇이고 어떻게 동작하나요?

정답 및 해설

 Virtual DOM은 실제 DOM의 가벼운 JavaScript 표현입니다. React는 상태가 변경될 때마다 새로운 Virtual DOM 트리를 생성하고, 이전 트리와 비교(diffing)하여 변경된 부분만 실제 DOM에 반영(reconciliation)합니다. 이를 통해 DOM 조작을 최소화하여 성능을 향상시킵니다. 실제 DOM 조작은 비용이 크지만 JavaScript 객체 비교는 빠르기 때문에 효율적입니다.

문제 26

커스텀 Hook을 만드는 이유와 장점은?

정답 및 해설

커스텀 Hook은 stateful 로직을 여러 컴포넌트에서 재사용하기 위해 만듭니다. 관련된 상태와 로직을 하나로 묶어서 관리할 수 있고, 컴포넌트를 더 깔끔하게 만들 수 있습니다. 테스트하기 쉽고 로직의 관심사를 분리할 수 있어서 유지보수가 용이합니다. 예를 들어 API 호출, 폼 상태 관리, 로컬 스토리지 관리 등을 커스텀 Hook으로 추상화할 수 있습니다.

문제 27

제어 컴포넌트와 비제어 컴포넌트의 차이는?

정답 및 해설

어 컴포넌트는 React 상태로 폼 데이터를 관리하며, 모든 입력 변경이 상태를 통해 처리됩니다. 실시간 검증이나 조건부 렌더링이 쉽고 예측 가능합니다. 비제어 컴포넌트는 DOM 자체에서 폼 데이터를 관리하며, ref를 사용해서 값에 접근합니다. 간단한 폼이나 기존 HTML 폼 라이브러리와 통합할 때 유용하지만, React의 선언적 특성과 맞지 않을 수 있습니다.

문제 28

 컴포넌트를 언제 분리해야 하나요

정답 및 해설

단일 책임 원칙에 따라 하나의 컴포넌트가 하나의 역할만 하도록 분리합니다.

stateful한 컴포넌트의 경우 따로 분리하며, 부모컴포넌트까지 상태변화에 따른 리렌더링이 발생하지 않도록합니다.

문제 29

컴파운드 컴포넌트란 무엇인가요

정답 및 해설

여러 개의 컴포넌트가 함께 작동하여 하나의 완전한 기능을 제공하는 디자인 패턴입니다. 부모와 자식 컴포넌트가 암시적으로 상태를 공유하며, HTML의 <select><option> 관계와 유사합니다.

문제 30

컴파운드 컴포넌트의 장점

정답 및 해설

관심사의 분리로 각 컴포넌트가 명확한 역할 담당

필요한 부분만 조합하여 사용 가능한 유연성

직관적이고 선언적인 API

높은 재사용성과 확장성

문제 31

컴파운드 컴포넌트의 단점

정답 및 해설

구조가 고정적이어서 유연성 제한

Context 사용 시 성능 오버헤드 발생 가능

깊은 중첩에서 prop drilling 문제

초기 구현 복잡도가 높음

잘못된 구조로 사용 시 오류 발생 위험

문제 32

언제 컴파운드 컴포넌트를 사용하나요?

정답 및 해설

A: Modal, Tabs, Dropdown, Accordion 같은 복잡한 UI 패턴, UI 라이브러리나 디자인 시스템 구축, 다양한 조합이 필요한 재사용 컴포넌트를 만들 때 사용합니다.

문제 33

대규모 아키텍처 개선에서

Pages Router를 App Router로 전면 마이그레이션 하셨다고 하셨는데, 마이그레이션 하신 이유가 있을까요?

정답 및 해설

첫 번째로 성능 개선이었습니다. App Router는 서버 컴포넌트를 기본으로 지원해서 초기 번들 사이즈를 크게 줄일 수 있었고, 스트리밍 렌더링으로 사용자가 더 빠르게 콘텐츠를 볼 수 있게 됐어요.

두 번째는 개발자 경험 향상이었습니다. 기존 Pages Router에서는 getServerSideProps나 getStaticProps로 데이터 패칭이 분리되어 있었는데, App Router에서는 컴포넌트 레벨에서 직접 fetch할 수 있어서 코드가 훨씬 직관적이고 유지보수하기 좋아졌어요.

마지막으로 미래 지향적인 선택이었습니다. Next.js 13부터 App Router가 stable해지면서 앞으로 새로운 기능들이 App Router 중심으로 개발될 것 같았고, 실제로 Server Actions 같은 기능들을 활용할 수 있게 됐거든요.

문제 34

마이그레이션은 어떤식으로 진행되었나요

정답 및 해설

네, 총 3개월 정도 걸렸어요. 점진적으로 진행했습니다.


1단계 (1개월) - 먼저 하이브리드 구조로 시작했어요. 기존 Pages Router는 그대로 두고 새로운 기능들만 App Router로 개발하면서 팀이 익숙해지도록 했죠. 이때 라우팅 컨벤션이나 서버 컴포넌트 사용법을 학습했고요.


2단계 (1.5개월) - 페이지별 우선순위를 매겨서 마이그레이션했어요. 트래픽이 낮고 의존성이 적은 페이지부터 시작해서, 점진적으로 메인 페이지들로 확장했습니다. 이때 가장 중요했던 건 기존 API 호환성 유지였어요.


3단계 (0.5개월) - 마지막에 레거시 코드 정리하고 Pages Router 관련 설정들을 제거했습니다.

문제 35

마이그레이션 하면서 어려웠던 부분은 없었나요?

정답 및 해설

nextjs의 api가 많이 바껴서 이를 학습하고, 오류없이 적용하는데 어려움이 있었습니다.


getServersideProps, getStaticProps 등의 api 가 서버컴포넌트의 fetch로 변환되고,

주로 사용하던 useRouter등의 api가 많이 바뀌었다

문제 36

"성능 최적화: React Server Components 도입, 렌더링 성능 및 데이터 페치 효율성 향상"

이라고 적혀있는데요,

조금도 자세히 설명해주시겠어요

정답 및 해설

서버에서 HTML을 미리 생성해서 보내니까 번들사이즈가 작아서 렌더링 성능이 개선되었어요 , First Contentful Paint가 약 40% 빨라졌어요


데이터 패칭 부분에서

Request-level 캐싱이 자동으로 돼요. 같은 요청 내에서 동일한 fetch가 여러 번 호출되면 한 번만 실행되거든요

Router CacheData Cache가 계층적으로 동작해서 사용자가 페이지 간 이동할 때 훨씬 빨라졌어요.


인터렉션 관련 코드를 hydration 해주는 작업이 필요

문제 37

"테스트 환경 구축: Jest 단위 테스트 및 Cypress E2E 테스트 환경 구축, 배포 안정성 확보" 에 대해 질문하겠습니다.

테스트 코드는 어떤 기준으로 작성하셨나요

정답 및 해설

Jest 단위 테스트는:

계산로직 과같은 핵심 비즈니스 로직을 우선으로 했습니다.

재사용 가능한 유틸 함수들 - 날짜 포맷팅, 유효성 검증 함수 등

컴포넌트 테스트는 사용자 인터랙션이 많은 것들만 선별적으로 했어요. 버튼 클릭, 폼 제출 같은 것들


Cypress E2E 테스트는:

핵심 사용자 플로우 중심이었어요. 회원가입 → 로그인 → 상품 주문 → 결제 이런 해피 패스

크리티컬한 기능들 - 결제 프로세스, 권한 관리 같은 장애 시 비즈니스 임팩트가 큰 부분들

작성 우선순위는:

버그가 자주 발생했던 부분 리팩토링할 예정인 코드 새로운 기능 개발할 때 필수로 작성

너무 많이 작성하면 유지보수 비용이 커지니까, 비즈니스 임팩트와 변경 빈도를 고려해서 선별적으로 작성했습니다.

문제 38

e2e테스트를 진행할때 데이터는 어떤 데이터를 활용하셨나요

정답 및 해설

시드 데이터베이스를 구축해서 테스트 실행 전에 항상 동일한 상태로 리셋되도록 했고요

문제 39

"디자인 시스템 구축 : 디자인 시스템 표준화를 통한 디자이너 협업 프로세스 최적화

스토리북을 활용한 컴포넌트 문서화 및 시각적 테스트 환경 구축 크로마틱을 활용해 PR별 시각적 변경사항 자동 감지 및 리뷰 프로세스 개선"

부분에 대해 질문하겠습니다.

디자인 시스템 구축에서 어려웠던 점은 어떤게 있었을까요

정답 및 해설

가장 큰 문제는 초기 합의 과정이었어요. 디자이너와 개발자 간에 "재사용 가능한 컴포넌트"의 기준이 달랐거든요. 디자이너는 픽셀 퍼펙트를 원했고, 개발자는 유연성을 중시했죠. 예를 들어 버튼 하나만 해도 사이즈, 색상, 상태별로 수십 가지 조합이 나오니까 어디까지 시스템화할지 결정하기가 어려웠어요.


두 번째는 기존 코드와의 충돌이었습니다. 이미 각 페이지마다 비슷하지만 조금씩 다른 컴포넌트들이 있었는데, 이걸 통합하는 과정에서 기존 디자인을 해치지 않으면서도 일관성을 맞추기가 까다로웠죠.

문제 40

"커스텀 비디오 플레이어 개발로 강의 시청 환경 개선 및 학습 효율성 증대"

어떤 기능을 구현하셨나요

정답 및 해설

배속 조절 - 0.5x부터 2x까지, 학습자가 본인 속도에 맞춰 조절할 수 있도록 했고요

자동 이어보기 - 이전에 시청 중단한 지점부터 자동으로 재생되고

HLS 스트리밍 지원해서 끊김 없는 재생 구현했고

진도율 추적 API와 연동해서 학습 진행 상황을 실시간으로 서버에 저장했어요

문제 41

hls스트리밍이 뭔가요? 어떻게 구현하셧나요

정답 및 해설

네, **HLS(HTTP Live Streaming)**는 Apple에서 개발한 스트리밍 프로토콜이에요.

HLS가 뭔지 먼저 설명드리면, 영상을 여러 개의 작은 세그먼트(보통 2-10초)로 나누고, 다양한 화질별로 준비해서 사용자의 네트워크 상황에 맞춰 적응적으로 스트리밍하는 방식이에요. YouTube나 Netflix에서도 이런 방식을 사용하죠.

왜 HLS를 선택했냐면:

기존 MP4 다운로드 방식은 파일 크기가 커서 로딩이 오래 걸렸고

네트워크가 느린 사용자는 버퍼링이 자주 발생했거든요

HLS는 실시간으로 화질을 조절해서 끊김 없이 재생할 수 있어요


서버 측에서는 FFmpeg로 원본 영상을 여러 해상도로 인코딩하고 m3u8 플레이리스트 파일을 생성했어요.

결과적으로 로딩 시간 60% 단축, 버퍼링 발생률 80% 감소 효과를 얻었습니다

문제 42

"컨텐츠 기반 PDF 생성 시스템 및 A4 페이징 최적화 알고리즘 구현"

A4페이징 최적화 알고리즘에 대해 설명해주세요

정답 및 해설



문제 상황부터 설명드리면, 동적 콘텐츠를 PDF로 변환할 때 텍스트나 이미지가 페이지 경계에서 잘리는 문제가 계속 발생했어요. 특히 표나 차트 같은 요소들이 페이지 중간에서 끊어져서 가독성이 많이 떨어졌거든요.


PDF 생성 전에 임시 컨테이너를 만들어서 측정하는 방식이었어요.

폰트 크기, line-height, margin/padding 등이 모두 반영된 실제 렌더링 크기가 필요했어요


알고리즘 핵심 로직은:

콘텐츠 요소별 높이 측정

- 각 섹션(제목, 텍스트 블록, 표, 이미지)의 실제 렌더링 높이를 미리 계산했어요

페이지 여백 계산


- 현재 페이지에서 사용 가능한 남은 공간을 실시간으로 체크하고 분할 가능성 판단


- 테이블이나 차트 같은

atomic 요소 는 절대 분할하지 않도록 했어요


- 이미지가 클경우에는. 비율을 유지하면서 최대 한페이지가 넘어가지않게 스케일 다운을 했습니다.

문제 43

"드래그 기반 하이라이팅 시스템 개발 텍스트 선택 영역의 DOM 좌표 추출 및 저장 로직 구현 위치 기반 데이터 매핑으로 페이지 새로고침 시에도 하이라이트 유지"

정답 및 해설

. DOM 좌표 추출이 가장 까다로웠어요:

Range.getBoundingClientRect()로 선택 영역의 위치를 구하고

startContainer, startOffset, endContainer, endOffset으로 정확한 텍스트 위치를 저장했어요

문제는 DOM 구조가 바뀌면 이 좌표들이 무효가 된다는 거였죠

복원할 때는 저장된 좌표 정보로 다시 Range 객체를 만들어서 동일한 오버레이를 생성하는 방식이었습니다.

이 방식이 비파괴적이라서 안전했어요!

문제 44

자기소개

정답 및 해설

안녕하세요! 3년차 프론트엔드 개발자 심은광입니다.

React와 Next.js 생태계에서 다양한 프로젝트 진행해 왔습니다.


백엔드기술에도 관심이 있어, 사이드 프로젝트를 진행하면서 백엔드쪽 공부도 하고 있어, 백엔드에 개발자와도 원활한 소통이 가능합니다 !


많은 이용자에게 좋은 경험을 제공해주는 개발을 하고 싶습니다.

문제 45

 프로젝트의 전체 아키텍처에 대해 설명해주세요.

정답 및 해설

레이어드 아키텍처를 채택했습니다.

pages/: 라우팅별 페이지 컴포넌트 (MenuPage, DetailPage, CartPage)

components/: 페이지별 도메인 컴포넌트들을 분리

apis/: 데이터 페칭 로직과 타입 정의 분리

stores/: 전역 상태 관리 (장바구니)

utils/: 비즈니스 로직 유틸리티 함수들

각 레이어가 명확한 책임을 갖도록 설계하여 유지보수성을 높였습니다.


레이어드 아키텍처: 각각 계층이 서로 독립적으로 구성되어 있어서 한 계층의 변경이 다른 계층에 영향을 주지 않게 설계할 수 있다.

문제 46

컴포넌트 구조를 어떻게 설계하셨나요

정답 및 해설

페이지별로 컴포넌트를 그룹화하고, 각 페이지 내에서도 기능별로 세분화했습니다.


관련 로직을 응집도 높게 관리하고, 재사용성을 고려했습니다.

문제 47

상태 관리 라이브러리로 Zustand를 선택한 이유는

정답 및 해설

단순함: Redux 대비 보일러플레이트 코드가 적음


번들 크기: 경량 라이브러리 (2.5kb)

persist 미들웨어: 장바구니 데이터 영속화가 간단함

문제 48

전역 상태와 로컬 상태를 어떻게 구분하셨나요?

정답 및 해설

전역: 장바구니 상태 (여러 페이지에서 공유 필요)

로컬: 폼 상태, UI 상태 (해당 컴포넌트에서만 사용)

각 DetailPage의 폼 상태는 react-hook-form으로 로컬 관리

문제 49

SWR을 선택한 이유와 어떻게 활용하셨나요?

정답 및 해설

캐싱 & 재검증: 동일 API 중복 호출 방지

에러 처리: 선언적 에러 핸들링

로딩 상태: 자동 로딩 상태 관리

문제 50

코드 재사용성을 위해 어떤 패턴을 사용하셨나요

정답 및 해설

커스텀 훅: 비즈니스 로직 추상화

유틸리티 함수: 계산 로직 분리 (utils/item.ts)

복잡한 함수 분리를 통한, 코드 가독성 향상

문제 51

유지보수성을 위해 어떤 부분에 신경 쓰셨나요

정답 및 해설

단일 책임 원칙: 각 함수/컴포넌트가 하나의 역할만 담당

명확한 네이밍: 함수/변수명으로 의도 명확히 표현

문제 52

useOptionSelection 훅을 어떤 설계 원칙으로 만드셨나요

정답 및 해설

1. 단일 책임 원칙: 옵션 선택 로직만 담당

2. 재사용성: 다양한 옵션 타입(grid, list, select)에서 공통 사용

3. 확장성: Config 패턴으로 다양한 설정 지원

4. 사이드 이펙트 최소화: 상태 변경을 콜백으로 외부에 위임

문제 53

Union Type을 활용한 CatalogOption 설계에 대해 설명해주세요.


export type CatalogOption = CatalogOptionGrid | CatalogOptionList | CatalogOptionSelect;

정답 및 해설

판별 유니온: type 필드로 각 타입을 구분

타입 가드: 런타임에서 안전한 타입 좁히기 가능

확장성: 새로운 옵션 타입 추가 시 기존 코드 영향 최소화

문제 54

메모이제이션을 어디에 적용하셨고, 그 기준은?

정답 및 해설

1. 스키마 생성: useMemo로 옵션 변경 시만 재생성

2. 기준: 계산 비용이 높고, 의존성이 자주 변하지 않는 경우

문제 55

에러 경계(Error Boundary)를 구현하지 않은 이유는

정답 및 해설

현재는 선언적 에러 핸들링으로 충분하다고 판단했습니다.


SWR: API 에러 처리

React Hook Form: 폼 검증 에러

Toast: 사용자 피드백


실제 운영환경에서는 예상치 못한 에러를 위한 Error Boundary가 필요할 것입니다.

문제 56

네트워크 에러나 서버 장애 시 사용자 경험을 어떻게 개선할 수 있을까요?

정답 및 해설

Retry 로직: SWR의 자동 재시도 기능

Offline 지원: Service Worker로 캐시된 데이터 제공

Skeleton UI: 로딩 상태의 시각적 개선

문제 57

이 프로젝트를 대규모 서비스로 확장한다면

정답 및 해설

마이크로 프론트엔드: 도메인별 팀 분리

상태 관리 분리: 도메인별 스토어 분할

컴포넌트 라이브러리: 디자인 시스템 구축

모니터링: 성능 메트릭 수집 및 분석

문제 58

이 코드에서 개선할 점이 있다면

정답 및 해설

Error Boundary: 예상치 못한 에러 처리

Loading State: Skeleton UI로 사용자 경험 개선

Testing: 핵심 로직에 대한 단위 테스트

문제 59

이 프로젝트에서 가장 고민했던 부분은 무엇인가요?

정답 및 해설

바구니 상태 관리가 가장 큰 고민이었습니다.

- 같은 상품이지만 옵션이 다르면 별도 아이템으로 관리

- 동일한 상품+옵션이면 수량만 증가

- 새로고침해도 장바구니 유지

- 실시간 가격 계산

- 이를 위해 Zustand + persist 조합과 옵션 비교 로직을 핵심으로 설계했습니다.

문제 60

만약 이 프로젝트를 다시 한다면 다르게 할 부분이 있나요

정답 및 해설

1. 테스트 코드: 비즈니스 로직부터 TDD로 접근

2. 에러 바운더리: 예상치 못한 에러 대비

문제 61

 폴더 구조를 이렇게 설계한 이유는

정답 및 해설

도메인 기반 구조를 선택했습니다:

응집도 높임: 관련 코드가 한 곳에 모임

유지보수성: 기능 추가/수정 시 찾기 쉬움

문제 62

폼 라이브러리로 React Hook Form을 선택한 이유는

정답 및 해설

복잡한 옵션 검증 때문이었습니다:

옵션별로 다른 검증 규칙 (필수/선택, 최소/최대 개수)

실시간 검증 피드백

성능 (리렌더링 최소화)

Formik 대비 uncontrolled 방식으로 성능이 더 좋고, Zod와의 조합도 완벽했습니다.

문제 63

사용자 경험을 위해 특별히 신경 쓴 부분은?

정답 및 해설

장바구니 영속화:

실수로 새로고침해도 안전

즉각적 피드백: 에러 발생 시 Toast + 해당 위치로 스크롤

문제 64

성능 최적화는 어떤 부분에 집중하셨나요?

정답 및 해설

실제 병목이 될 만한 부분에 집중했습니다


스키마 생성: useMemo로 옵션 변경시만 재생성

API 호출: SWR 캐싱으로 중복 요청 방지

문제 65

개발하면서 가장 어려웠던 문제와 해결 과정은

정답 및 해설

복잡한 옵션 검증 로직이 가장 힘들었습니다.


Grid 옵션: 반드시 1개 선택

List 옵션: 최소/최대 개수 제한

Select 옵션: 0~1개 선택

각각 다른 에러 메시지와 UI 피드백


처음에는 각 컴포넌트에서 개별 검증 → 중복 코드 발생

Zod superRefine으로 통합 검증 로직 구현

에러 메시지에 optionId포함해서 스크롤 위치 특정

커스텀 훅으로 옵션 선택 로직 추상화

문제 66

예상치 못한 버그나 이슈가 있었나요

정답 및 해설

장바구니 새로고침 시 총합이 안 맞는 문제가 있었습니다.

원인: Zustand persist에서 데이터 복원 시 계산된 값들이 초기화되지 않음

해결: onRehydrateStorage 콜백에서 총합 재계산

이 경험으로 상태 복원 로직의 중요성을 깨달았습니다.

문제 67

이 코드를 팀원이 이해하기 쉽게 만든 부분

정답 및 해설

명확한 네이밍: calculateItemPrice

mergeCartItem 등 의도가 드러나는 함수명

타입 정의: 모든 데이터 구조를 인터페이스로 명시

폴더 구조: 기능별로 파일이 어디에 있는지 예측 가능

순수 함수: 사이드 이펙트 없는 유틸리티 함수들

문제 68

이 프로젝트가 실제 서비스가 된다면 어떤 부분을 먼저 개선하겠습니까?

정답 및 해설

모니터링: 에러 추적, 성능 메트릭 수집

접근성: 스크린 리더 지원

문제 69

사용자가 10배로 늘어난다면 어떤 부분이 문제가 될까요

정답 및 해설

번들 크기: 코드 스플리팅으로 초기 로딩 개선

에러 추적: 대규모 에러 모니터링 시스템

문제 70

이 프로젝트를 통해 가장 많이 배운 것은?

정답 및 해설

"추상화의 적정선"입니다.

너무 추상화하면 복잡해짐

너무 구체적이면 재사용성 떨어짐

실제 요구사항에 맞는 적절한 추상화를 찾는 게 핵심

특히 useOptionSelection 훅에서 이런 고민을 많이 했습니다.

문제 71

토스 개발 문화에 맞춰 어떤 부분을 더 발전시키고 싶나요?

정답 및 해설

사용자 중심 사고: 개발자가 아닌 사용자 관점에서 UX 고민

데이터 기반 의사결정: A/B 테스트, 메트릭 기반 개선

빠른 실험과 검증: MVP로 빠르게 검증 후 개선

팀 협업: 코드 리뷰, 지식 공유 문화

문제 1

Redux나 다른 상태 관리 라이브러리 대신 Zustand를 선택했나요

정답 및 해설

- 가벼운 번들사이즈

- 커스텀 훅 방식으로 React 패턴과 일치

- 보일러플레이트 최소화: 액션, 리듀서 없이 직관적인 API

- persist 미들웨어: 장바구니 데이터 영속화가 간단함

문제 2

액션, 리듀서에 대해 설명해보세요.

정답 및 해설

액션(Action)

상태 변경을 설명하는 명령서 객체

"무엇이 일어났는지"를 설명하는 type과 필요한 데이터(payload) 포함


const incrementAction = { type: 'INCREMENT' }

const addTodoAction = {

type: 'ADD_TODO',

payload: { id: 1, text: '할일 추가' }

}



리듀서(Reducer)

현재 상태와 액션을 받아서 새로운 상태를 반환하는 순수 함수

"상태를 어떻게 변경할지"의 로직을 담당


const counterReducer = (state = { count: 0 }, action) => {

switch (action.type) {

case 'INCREMENT':

return { count: state.count + 1 }

case 'DECREMENT':

return { count: state.count - 1 }

default:

return state

}

}


플로우

컴포넌트에서 액션 디스패치 리듀서가 현재 상태 + 액션으로 새 상태 계산 스토어 업데이트 후 구독 중인 컴포넌트들 리렌더링

특징:

예측 가능: 같은 입력에 항상 같은 출력

불변성: 기존 상태를 변경하지 않고 새 객체 반환

디버깅 용이: 모든 상태 변경이 액션으로 기록됨

문제 3

SWR vs React-Query

정답 및 해설

캐싱 기능이 있어 동일한 요청 시 네트워크 요청을 줄이고 성능 최적화를 지원한다


SWR:

가벼움: 4KB로 React Query보다 훨씬 작아서 초기 로딩 성능에 유리했습니다.

개발 속도: 복잡한 설정 없이 바로 사용 가능해서 프로토타이핑이 빨랐습니다


React Query: 데이터 캐싱 및 상태 관리를 세밀하게 제어해야 하거나 복잡한 애플리케이션에서 서버 상태를 효율적으로 관리해야 할 때 적합하다.


1. 계층적 캐시 무효화

queryClient.invalidateQueries({queryKey:['posts']})


2. 조건부 캐시 관리

queryClient.invalidateQueries({predicate:(query)=> query.queryKey[0]==='posts'&& query.queryKey[2]?.status ==='draft'})


3. 낙관적 업데이트

서버 응답 전에 UI 먼저 업데이트하고, 실패 시 롤백

SWR은 기본 지원하지 않아 수동 구현 필요


4. 메모리 기반 가비지 컬렉션

사용하지 않는 캐시를 자동으로 정리

쿼리별로 다른 캐시 유지 시간 설정 가능

문제 4

서버컴포넌트와 클라이언트컴포넌트를 비교해서 설명해보세요.

정답 및 해설

먼저 서버 컴포넌트는 말 그대로 서버에서 실행되는 컴포넌트입니다. 서버에서 렌더링이 끝나고 HTML이 완성된 상태로 클라이언트에 전달되죠. 그래서 번들 사이즈가 작아지고 초기 로딩 속도가 빨라지는 장점이 있어요. 또한 데이터베이스나 파일시스템 같은 백엔드 리소스에 직접 접근할 수 있습니다.

반면에 클라이언트 컴포넌트는 우리가 기존에 사용하던 React 컴포넌트와 같다고 보시면 됩니다. 브라우저에서 실행되고, useState나 useEffect 같은 훅들을 사용할 수 있어요. 사용자와의 상호작용도 처리할 수 있죠.

가장 큰 차이점은 서버 컴포넌트는 상태 관리나 이벤트 핸들링을 할 수 없다는 점입니다. 그래서 실제 프로젝트에서는 두 컴포넌트를 적절히 조합해서 사용하게 되는데요, 정적인 데이터 표시는 서버 컴포넌트로, 동적인 상호작용이 필요한 부분은 클라이언트 컴포넌트로 나누어 구현합니다.

문제 5

서버에서 만들어서 html로 전달한다고 했는데, 어떤형태로 전달되는건지 말해주세요

정답 및 해설

HTML이라고 표현했는데 정확히는 HTML이 아니에요.

서버 컴포넌트는 RSC Payload라는 특별한 형태로 전달됩니다. 이건 JSON과 비슷한 직렬화된 데이터 형태인데요, React가 이해할 수 있는 컴포넌트 트리 정보를 담고 있어요

문제 6

스트리밍 컴포넌트에 대해 알고 있나요

정답 및 해설

스트리밍을 사용하면 컴포넌트가 준비되는 대로 부분적으로 클라이언트에 전송할 수 있습니다.

Next.js에서는 Suspense 경계와 함께 사용

이렇게 하면 SlowComponent가 로딩되는 동안 Loading 컴포넌트를 보여주고, 준비되면 실제 컴포넌트로 교체됩니다.

장점은 사용자가 더 빨리 콘텐츠를 볼 수 있다는 거예요. TTFB(Time to First Byte)는 빨라지고, 전체적인 사용자 경험이 개선되죠. 특히 느린 데이터 페칭이 있는 컴포넌트가 전체 페이지를 블로킹하지 않게 됩니다.


병렬 + 논블로킹 + 점진적 전송

블로킹하지 않고 독립적으로 처리한다"

문제 7

스트리밍 컴포넌트를 사용하면 초기 번들사이즈를 줄일 수 있나요?

정답 및 해설

스트리밍은 서버에서 클라이언트로 HTML을 전송하는 방식에 관한 것이고, 번들 사이즈는 JavaScript 파일의 크기에 관한 문제거든요.

문제 8

칸반 보드를 구현하실때 웹소켓을 구현하셨는데요,

SSE나 WebRTC 등을 고려해보셨나요??

웹소켓을 선택한 이유가 뭘까요

정답 및 해설

SSE(Server-Sent Events)를 고려했지만:

- SSE는 서버에서 클라이언트로만 단방향 통신이에요

- 칸반 보드는 사용자가 카드를 드래그하거나 수정할 때 실시간으로 서버에 데이터를 보내야 하거든요

- 그러면 결국 SSE + AJAX 조합을 써야 하는데, 이게 오히려 복잡해져요


웹소켓을 선택한 이유:

양방향 통신

사용자 액션을 서버로 즉시 전송하고, 다른 사용자들에게 실시간 브로드캐스트 낮은 레이턴시

HTTP 오버헤드 없이 바로 메시지 교환 상태 유지

연결이 유지되어서 사용자가 온라인/오프라인 상태 관리도 쉬워요 구현 단순성

Socket.io 같은 라이브러리로 쉽게 구현 가능

칸반 보드처럼 실시간 협업이 핵심인 서비스에는 웹소켓이 가장 적합한 선택이었어요.

문제 9

그렇다면, 웹소켓에서 권한관련 처리는 어떻게 진행하셨나요

정답 및 해설

연결 단계에서 토큰을 메세지로 보내서 권한을 체크했다

문제 10

토근 갱신처리는 어떤 시점에 이루어졌나요

정답 및 해설

서버측에서 토큰만료시간이 다가올때쯤 emit('token-refresh-required')을 보내고

프론트에서 socket.on('refresh-token',(newToken)=>{const user =verifyJWT(newToken);if(user){ socket.user={...socket.user,token: newToken };}});

으로 재검증을 요청하는 식으로 했습니다.

문제 11

프론트에서 사용하는 소켓 메소드에 대해 설명해보세요

정답 및 해설

이벤트 발신 (emit)

이벤트 수신 (on)


칸반 보드에서는 주로 emit으로 카드 이동을 서버에 알리고, on으로 다른 사용자의 변경사항을 받아서 UI를 업데이트했어요.

문제 12

소켓으로 어떤식으로 구현하였나

정답 및 해설

낙관적 업데이트였어요. 사용자가 카드를 드래그하면 서버 응답을 기다리지 않고 일단 UI를 바로 업데이트해서 부드러운 사용자 경험을 제공하는 거죠. 그리고 만약 서버에서 거부되면 롤백하는 방식으로 처리했습니다.

문제 13

소켓구현에서 어려웠던점

정답 및 해설

여러 명이 동시에 같은 컬럼을 수정할 때 인덱스 충돌

서버에서 최종 상태를 관리하고 클라이언트는 그에 맞춰 조정하는 방식으로 해결했습니다.



드래그 중 충돌 방지

드래그 상태 기반 업데이트 필터링

현재 사용자가 카드를 드래그하고 있는 동안에는 해당 카드에 대한 다른 사용자의 업데이트를 임시로 무시하고, 현재 사용자의 액션이 끝났을 때 데이터를 업데이트 하는 방식으로 동시성 문제를 보완했습니다.


현재 사용자의 액션을 최우선으로 보장하면서도 데이터 일관성은 유지할 수 있었

문제 14

모노레포와 멀티레포의 차이와 장단점에 대해 설명해주세요

정답 및 해설

모노레포 (Monorepo): 하나의 저장소에 여러 프로젝트나 패키지를 관리하는 방식이에요. 예를 들어 웹앱, 모바일앱, 공통 라이브러리를 모두 하나의 Git 저장소에서 관리하는 거죠.


멀티레포 (Multirepo): 각 프로젝트마다 별도의 저장소를 만들어서 독립적으로 관리하는 전통적인 방식입니다.


모노레포 장점:

코드 공유가 쉬워요. 공통 컴포넌트나 유틸을 바로 import 할 수 있거든요

의존성 관리가 일관성 있게 가능하고

전체 프로젝트를 한 번에 리팩토링할 수 있어요

배포 파이프라인을 통합해서 관리할 수 있고요

모노레포 단점:

저장소 크기가 커져서 클론 시간이 오래 걸리고

빌드 시간이 길어질 수 있어요

권한 관리가 복잡해지죠

멀티레포 장점:

각 팀이 독립적으로 작업할 수 있고

저장소가 가벼워서 빠르고

기술 스택을 자유롭게 선택할 수 있어요

멀티레포 단점:

공통 코드 공유가 복잡하고

의존성 버전 관리가 어려워요

실제로는 팀 규모와 프로젝트 성격에 따라 선택하게 되는 것 같아요.

문제 15

모노레포를 구현하셨다고 하셨는데,

터보레포를 선택하신 이유가 있을까요?

정답 및 해설

- 가장 큰 이유는 캐싱과 병렬 처리였습니다. 변경되지 않은 패키지는 다시 빌드하지 않고 캐시를 사용해서 빌드 시간이 엄청 단축됐거든요. 특히 여러 프로젝트가 있을 때 이 효과가 확실했어요.


- turbo.json 파일 하나로 파이프라인을 정의할 수 있어서 러닝 커브가 낮았습니다.


-Vercel에서 만들어서 Next.js와의 호환성도 뛰어났다.

문제 16

pnpm 을 사용한 이유가 있을까요

정답 및 해설

 모노레포 지원이 훌륭했어요. 기능이 직관적이고, 터보레포와의 조합도 완벽했습니다.


pnpm의 디스크 효율성과 빠른 설치 속도


디스크 효율성: 모노레포에서는 여러 패키지가 같은 라이브러리를 사용하는 경우가 많아요. 예를 들어 web-app, mobile-app, admin-app이 모두 React를 사용한다면:

npm/yarn: React가 3번 설치됨 (각 패키지마다)

pnpm: React가 1번만 저장되고 하드링크로 공유


 pnpm은 패키지를 중앙 저장소에 한 번만 저장하고, 각 프로젝트에서는 하드링크로 참조하는 방식으로 디스크 공간을 절약

하드링크는 하나의 파일을 여러 경로에서 참조할 수 있게 해주는 파일시스템 기능


1. 의존성 호이스팅: 공통으로 사용하는 라이브러리는 루트에서 한 번만 설치하고 공유해요.

2. 내부 패키지 참조: web-app에서 ui-components를 바로 import할 수 있어요. 별도로 npm에 배포하지 않아도 되죠.

3. 통합 명령어:

문제 17

 웹소켓이 무엇이고 HTTP와 어떤 차이가 있나요?

정답 및 해설

A: 웹소켓은 클라이언트와 서버 간에 지속적인 양방향 통신을 가능하게 하는 프로토콜입니다. HTTP는 요청-응답 기반의 단방향 통신이지만, 웹소켓은 한 번 연결되면 지속적으로 양방향으로 데이터를 주고받을 수 있습니다. HTTP는 매번 요청 시 헤더 오버헤드가 크지만, 웹소켓은 초기 핸드셰이크 후에는 오버헤드가 적어 효율적입니다.

문제 18

웹소켓 연결 과정을 설명해주세요.

정답 및 해설

웹소켓 연결은 HTTP 업그레이드 핸드셰이크로 시작됩니다. 클라이언트가 HTTP GET 요청에 Upgrade 헤더를 포함해서 보내면, 서버가 101 Switching Protocols로 응답하며 프로토콜이 HTTP에서 웹소켓으로 전환됩니다. 이후 지속적인 양방향 통신이 가능해집니다.

문제 19

 웹소켓 성능 최적화 방법은?

정답 및 해설

메시지 배치 처리로 여러 메시지를 한 번에 보내고, 연결 풀링으로 여러 연결을 관리하며, 압축을 사용해서 데이터 크기를 줄입니다. 또한 불필요한 메시지 전송을 피하고, 적절한 하트비트 간격을 설정해서 연결을 유지합니다.

문제 20

Socket.IO와 네이티브 웹소켓의 차이는?

정답 및 해설

: 네이티브 웹소켓은 브라우저 내장 API로 가볍지만 기본 기능만 제공합니다. Socket.IO는 자동 재연결, 하트비트, 폴백 메커니즘, 룸 기능 등을 제공하지만 추가 라이브러리가 필요해서 번들 크기가 커집니다. 프로젝트 요구사항에 따라 선택해야 합니다.

문제 21

웹소켓 연결 문제를 어떻게 디버깅하나요?

정답 및 해설

브라우저 개발자 도구의 Network 탭에서 웹소켓 연결 상태를 확인하고, Console에서 에러 메시지를 점검합니다. 연결 상태 변화를 로깅하고, 헬스체크(ping/pong)을 구현해서 연결 품질을 모니터링합니다. 서버 로그와 클라이언트 로그를 함께 분석해서 문제점을 파악합니다.

문제 22

웹소켓 연결이 자주 끊어지는 문제는 어떻게 해결하나요?

정답 및 해설

A: 네트워크 환경, 프록시 설정, 방화벽 정책을 점검하고, 하트비트 간격을 조정합니다. 모바일에서는 백그라운드 상태나 네트워크 전환 시 연결이 끊어질 수 있으므로 적절한 재연결 로직이 필요합니다. keep-alive 설정을 조정하거나 더 짧은 타임아웃을 설정할 수도 있습니다.

문제 23

HTTP의 오버헤드

정답 및 해설

HTTP 요청 시마다 발생하는 추가 비용:

헤더 정보: 매 요청마다 User-Agent, Accept, Cookie, Content-Type 등의 헤더가 포함됨 (보통 500바이트~2KB)

연결 설정: TCP 3-way handshake + TLS handshake (HTTPS의 경우)

연결 해제: 요청 완료 후 연결을 닫는 과정

상태 정보: HTTP는 stateless라서 매번 인증 정보 등을 다시 보내야 함

예시: "안녕"이라는 4바이트 메시지를 보내도, HTTP 헤더까지 포함하면 실제로는 1KB 이상이 전송됨

웹소켓의 낮은 오버헤드

초기 연결 후 발생하는 비용:

프레임 헤더: 메시지마다 단 2-14바이트의 작은 헤더만 추가됨

연결 유지: 한 번 연결되면 계속 사용, 매번 새로 연결할 필요 없음

상태 유지: 연결이 지속되므로 인증 정보 등을 매번 보낼 필요 없음

예시: "안녕" 메시지를 보낼 때 실제로 6-18바이트 정도만 전송됨 (메시지 4바이트 + 헤더 2-14바이트)

실제 차이

HTTP: 작은 메시지도 매번 큰 헤더와 함께 전송 → 비효율적

웹소켓: 작은 헤더만 추가되므로 순수한 데이터 비율이 높음 → 효율적

특히 실시간으로 작은 메시지를 자주 주고받는 상황에서 이 차이가 크게 납니다. 채팅처럼 짧은 메시지를 많이 보내는 경우 웹소켓이 HTTP보다 대역폭을 훨씬 적게 사용하게 됩니다.

문제 24

React가 무엇이고 왜 사용하나요

정답 및 해설

React는 Facebook에서 개발한 사용자 인터페이스를 구축하기 위한 JavaScript 라이브러리입니다. 컴포넌트 기반 아키텍처로 재사용 가능한 UI 요소를 만들 수 있고, Virtual DOM을 통해 효율적인 렌더링을 제공합니다. 단방향 데이터 플로우로 예측 가능한 상태 관리가 가능하며, 큰 개발자 커뮤니티와 풍부한 생태계를 제공합니다.

문제 25

Virtual DOM이 무엇이고 어떻게 동작하나요?

정답 및 해설

 Virtual DOM은 실제 DOM의 가벼운 JavaScript 표현입니다. React는 상태가 변경될 때마다 새로운 Virtual DOM 트리를 생성하고, 이전 트리와 비교(diffing)하여 변경된 부분만 실제 DOM에 반영(reconciliation)합니다. 이를 통해 DOM 조작을 최소화하여 성능을 향상시킵니다. 실제 DOM 조작은 비용이 크지만 JavaScript 객체 비교는 빠르기 때문에 효율적입니다.

문제 26

커스텀 Hook을 만드는 이유와 장점은?

정답 및 해설

커스텀 Hook은 stateful 로직을 여러 컴포넌트에서 재사용하기 위해 만듭니다. 관련된 상태와 로직을 하나로 묶어서 관리할 수 있고, 컴포넌트를 더 깔끔하게 만들 수 있습니다. 테스트하기 쉽고 로직의 관심사를 분리할 수 있어서 유지보수가 용이합니다. 예를 들어 API 호출, 폼 상태 관리, 로컬 스토리지 관리 등을 커스텀 Hook으로 추상화할 수 있습니다.

문제 27

제어 컴포넌트와 비제어 컴포넌트의 차이는?

정답 및 해설

어 컴포넌트는 React 상태로 폼 데이터를 관리하며, 모든 입력 변경이 상태를 통해 처리됩니다. 실시간 검증이나 조건부 렌더링이 쉽고 예측 가능합니다. 비제어 컴포넌트는 DOM 자체에서 폼 데이터를 관리하며, ref를 사용해서 값에 접근합니다. 간단한 폼이나 기존 HTML 폼 라이브러리와 통합할 때 유용하지만, React의 선언적 특성과 맞지 않을 수 있습니다.

문제 28

 컴포넌트를 언제 분리해야 하나요

정답 및 해설

단일 책임 원칙에 따라 하나의 컴포넌트가 하나의 역할만 하도록 분리합니다.

stateful한 컴포넌트의 경우 따로 분리하며, 부모컴포넌트까지 상태변화에 따른 리렌더링이 발생하지 않도록합니다.

문제 29

컴파운드 컴포넌트란 무엇인가요

정답 및 해설

여러 개의 컴포넌트가 함께 작동하여 하나의 완전한 기능을 제공하는 디자인 패턴입니다. 부모와 자식 컴포넌트가 암시적으로 상태를 공유하며, HTML의 <select><option> 관계와 유사합니다.

문제 30

컴파운드 컴포넌트의 장점

정답 및 해설

관심사의 분리로 각 컴포넌트가 명확한 역할 담당

필요한 부분만 조합하여 사용 가능한 유연성

직관적이고 선언적인 API

높은 재사용성과 확장성

문제 31

컴파운드 컴포넌트의 단점

정답 및 해설

구조가 고정적이어서 유연성 제한

Context 사용 시 성능 오버헤드 발생 가능

깊은 중첩에서 prop drilling 문제

초기 구현 복잡도가 높음

잘못된 구조로 사용 시 오류 발생 위험

문제 32

언제 컴파운드 컴포넌트를 사용하나요?

정답 및 해설

A: Modal, Tabs, Dropdown, Accordion 같은 복잡한 UI 패턴, UI 라이브러리나 디자인 시스템 구축, 다양한 조합이 필요한 재사용 컴포넌트를 만들 때 사용합니다.

문제 33

대규모 아키텍처 개선에서

Pages Router를 App Router로 전면 마이그레이션 하셨다고 하셨는데, 마이그레이션 하신 이유가 있을까요?

정답 및 해설

첫 번째로 성능 개선이었습니다. App Router는 서버 컴포넌트를 기본으로 지원해서 초기 번들 사이즈를 크게 줄일 수 있었고, 스트리밍 렌더링으로 사용자가 더 빠르게 콘텐츠를 볼 수 있게 됐어요.

두 번째는 개발자 경험 향상이었습니다. 기존 Pages Router에서는 getServerSideProps나 getStaticProps로 데이터 패칭이 분리되어 있었는데, App Router에서는 컴포넌트 레벨에서 직접 fetch할 수 있어서 코드가 훨씬 직관적이고 유지보수하기 좋아졌어요.

마지막으로 미래 지향적인 선택이었습니다. Next.js 13부터 App Router가 stable해지면서 앞으로 새로운 기능들이 App Router 중심으로 개발될 것 같았고, 실제로 Server Actions 같은 기능들을 활용할 수 있게 됐거든요.

문제 34

마이그레이션은 어떤식으로 진행되었나요

정답 및 해설

네, 총 3개월 정도 걸렸어요. 점진적으로 진행했습니다.


1단계 (1개월) - 먼저 하이브리드 구조로 시작했어요. 기존 Pages Router는 그대로 두고 새로운 기능들만 App Router로 개발하면서 팀이 익숙해지도록 했죠. 이때 라우팅 컨벤션이나 서버 컴포넌트 사용법을 학습했고요.


2단계 (1.5개월) - 페이지별 우선순위를 매겨서 마이그레이션했어요. 트래픽이 낮고 의존성이 적은 페이지부터 시작해서, 점진적으로 메인 페이지들로 확장했습니다. 이때 가장 중요했던 건 기존 API 호환성 유지였어요.


3단계 (0.5개월) - 마지막에 레거시 코드 정리하고 Pages Router 관련 설정들을 제거했습니다.

문제 35

마이그레이션 하면서 어려웠던 부분은 없었나요?

정답 및 해설

nextjs의 api가 많이 바껴서 이를 학습하고, 오류없이 적용하는데 어려움이 있었습니다.


getServersideProps, getStaticProps 등의 api 가 서버컴포넌트의 fetch로 변환되고,

주로 사용하던 useRouter등의 api가 많이 바뀌었다

문제 36

"성능 최적화: React Server Components 도입, 렌더링 성능 및 데이터 페치 효율성 향상"

이라고 적혀있는데요,

조금도 자세히 설명해주시겠어요

정답 및 해설

서버에서 HTML을 미리 생성해서 보내니까 번들사이즈가 작아서 렌더링 성능이 개선되었어요 , First Contentful Paint가 약 40% 빨라졌어요


데이터 패칭 부분에서

Request-level 캐싱이 자동으로 돼요. 같은 요청 내에서 동일한 fetch가 여러 번 호출되면 한 번만 실행되거든요

Router CacheData Cache가 계층적으로 동작해서 사용자가 페이지 간 이동할 때 훨씬 빨라졌어요.


인터렉션 관련 코드를 hydration 해주는 작업이 필요

문제 37

"테스트 환경 구축: Jest 단위 테스트 및 Cypress E2E 테스트 환경 구축, 배포 안정성 확보" 에 대해 질문하겠습니다.

테스트 코드는 어떤 기준으로 작성하셨나요

정답 및 해설

Jest 단위 테스트는:

계산로직 과같은 핵심 비즈니스 로직을 우선으로 했습니다.

재사용 가능한 유틸 함수들 - 날짜 포맷팅, 유효성 검증 함수 등

컴포넌트 테스트는 사용자 인터랙션이 많은 것들만 선별적으로 했어요. 버튼 클릭, 폼 제출 같은 것들


Cypress E2E 테스트는:

핵심 사용자 플로우 중심이었어요. 회원가입 → 로그인 → 상품 주문 → 결제 이런 해피 패스

크리티컬한 기능들 - 결제 프로세스, 권한 관리 같은 장애 시 비즈니스 임팩트가 큰 부분들

작성 우선순위는:

버그가 자주 발생했던 부분 리팩토링할 예정인 코드 새로운 기능 개발할 때 필수로 작성

너무 많이 작성하면 유지보수 비용이 커지니까, 비즈니스 임팩트와 변경 빈도를 고려해서 선별적으로 작성했습니다.

문제 38

e2e테스트를 진행할때 데이터는 어떤 데이터를 활용하셨나요

정답 및 해설

시드 데이터베이스를 구축해서 테스트 실행 전에 항상 동일한 상태로 리셋되도록 했고요

문제 39

"디자인 시스템 구축 : 디자인 시스템 표준화를 통한 디자이너 협업 프로세스 최적화

스토리북을 활용한 컴포넌트 문서화 및 시각적 테스트 환경 구축 크로마틱을 활용해 PR별 시각적 변경사항 자동 감지 및 리뷰 프로세스 개선"

부분에 대해 질문하겠습니다.

디자인 시스템 구축에서 어려웠던 점은 어떤게 있었을까요

정답 및 해설

가장 큰 문제는 초기 합의 과정이었어요. 디자이너와 개발자 간에 "재사용 가능한 컴포넌트"의 기준이 달랐거든요. 디자이너는 픽셀 퍼펙트를 원했고, 개발자는 유연성을 중시했죠. 예를 들어 버튼 하나만 해도 사이즈, 색상, 상태별로 수십 가지 조합이 나오니까 어디까지 시스템화할지 결정하기가 어려웠어요.


두 번째는 기존 코드와의 충돌이었습니다. 이미 각 페이지마다 비슷하지만 조금씩 다른 컴포넌트들이 있었는데, 이걸 통합하는 과정에서 기존 디자인을 해치지 않으면서도 일관성을 맞추기가 까다로웠죠.

문제 40

"커스텀 비디오 플레이어 개발로 강의 시청 환경 개선 및 학습 효율성 증대"

어떤 기능을 구현하셨나요

정답 및 해설

배속 조절 - 0.5x부터 2x까지, 학습자가 본인 속도에 맞춰 조절할 수 있도록 했고요

자동 이어보기 - 이전에 시청 중단한 지점부터 자동으로 재생되고

HLS 스트리밍 지원해서 끊김 없는 재생 구현했고

진도율 추적 API와 연동해서 학습 진행 상황을 실시간으로 서버에 저장했어요

문제 41

hls스트리밍이 뭔가요? 어떻게 구현하셧나요

정답 및 해설

네, **HLS(HTTP Live Streaming)**는 Apple에서 개발한 스트리밍 프로토콜이에요.

HLS가 뭔지 먼저 설명드리면, 영상을 여러 개의 작은 세그먼트(보통 2-10초)로 나누고, 다양한 화질별로 준비해서 사용자의 네트워크 상황에 맞춰 적응적으로 스트리밍하는 방식이에요. YouTube나 Netflix에서도 이런 방식을 사용하죠.

왜 HLS를 선택했냐면:

기존 MP4 다운로드 방식은 파일 크기가 커서 로딩이 오래 걸렸고

네트워크가 느린 사용자는 버퍼링이 자주 발생했거든요

HLS는 실시간으로 화질을 조절해서 끊김 없이 재생할 수 있어요


서버 측에서는 FFmpeg로 원본 영상을 여러 해상도로 인코딩하고 m3u8 플레이리스트 파일을 생성했어요.

결과적으로 로딩 시간 60% 단축, 버퍼링 발생률 80% 감소 효과를 얻었습니다

문제 42

"컨텐츠 기반 PDF 생성 시스템 및 A4 페이징 최적화 알고리즘 구현"

A4페이징 최적화 알고리즘에 대해 설명해주세요

정답 및 해설



문제 상황부터 설명드리면, 동적 콘텐츠를 PDF로 변환할 때 텍스트나 이미지가 페이지 경계에서 잘리는 문제가 계속 발생했어요. 특히 표나 차트 같은 요소들이 페이지 중간에서 끊어져서 가독성이 많이 떨어졌거든요.


PDF 생성 전에 임시 컨테이너를 만들어서 측정하는 방식이었어요.

폰트 크기, line-height, margin/padding 등이 모두 반영된 실제 렌더링 크기가 필요했어요


알고리즘 핵심 로직은:

콘텐츠 요소별 높이 측정

- 각 섹션(제목, 텍스트 블록, 표, 이미지)의 실제 렌더링 높이를 미리 계산했어요

페이지 여백 계산


- 현재 페이지에서 사용 가능한 남은 공간을 실시간으로 체크하고 분할 가능성 판단


- 테이블이나 차트 같은

atomic 요소 는 절대 분할하지 않도록 했어요


- 이미지가 클경우에는. 비율을 유지하면서 최대 한페이지가 넘어가지않게 스케일 다운을 했습니다.

문제 43

"드래그 기반 하이라이팅 시스템 개발 텍스트 선택 영역의 DOM 좌표 추출 및 저장 로직 구현 위치 기반 데이터 매핑으로 페이지 새로고침 시에도 하이라이트 유지"

정답 및 해설

. DOM 좌표 추출이 가장 까다로웠어요:

Range.getBoundingClientRect()로 선택 영역의 위치를 구하고

startContainer, startOffset, endContainer, endOffset으로 정확한 텍스트 위치를 저장했어요

문제는 DOM 구조가 바뀌면 이 좌표들이 무효가 된다는 거였죠

복원할 때는 저장된 좌표 정보로 다시 Range 객체를 만들어서 동일한 오버레이를 생성하는 방식이었습니다.

이 방식이 비파괴적이라서 안전했어요!

문제 44

자기소개

정답 및 해설

안녕하세요! 3년차 프론트엔드 개발자 심은광입니다.

React와 Next.js 생태계에서 다양한 프로젝트 진행해 왔습니다.


백엔드기술에도 관심이 있어, 사이드 프로젝트를 진행하면서 백엔드쪽 공부도 하고 있어, 백엔드에 개발자와도 원활한 소통이 가능합니다 !


많은 이용자에게 좋은 경험을 제공해주는 개발을 하고 싶습니다.

문제 45

 프로젝트의 전체 아키텍처에 대해 설명해주세요.

정답 및 해설

레이어드 아키텍처를 채택했습니다.

pages/: 라우팅별 페이지 컴포넌트 (MenuPage, DetailPage, CartPage)

components/: 페이지별 도메인 컴포넌트들을 분리

apis/: 데이터 페칭 로직과 타입 정의 분리

stores/: 전역 상태 관리 (장바구니)

utils/: 비즈니스 로직 유틸리티 함수들

각 레이어가 명확한 책임을 갖도록 설계하여 유지보수성을 높였습니다.


레이어드 아키텍처: 각각 계층이 서로 독립적으로 구성되어 있어서 한 계층의 변경이 다른 계층에 영향을 주지 않게 설계할 수 있다.

문제 46

컴포넌트 구조를 어떻게 설계하셨나요

정답 및 해설

페이지별로 컴포넌트를 그룹화하고, 각 페이지 내에서도 기능별로 세분화했습니다.


관련 로직을 응집도 높게 관리하고, 재사용성을 고려했습니다.

문제 47

상태 관리 라이브러리로 Zustand를 선택한 이유는

정답 및 해설

단순함: Redux 대비 보일러플레이트 코드가 적음


번들 크기: 경량 라이브러리 (2.5kb)

persist 미들웨어: 장바구니 데이터 영속화가 간단함

문제 48

전역 상태와 로컬 상태를 어떻게 구분하셨나요?

정답 및 해설

전역: 장바구니 상태 (여러 페이지에서 공유 필요)

로컬: 폼 상태, UI 상태 (해당 컴포넌트에서만 사용)

각 DetailPage의 폼 상태는 react-hook-form으로 로컬 관리

문제 49

SWR을 선택한 이유와 어떻게 활용하셨나요?

정답 및 해설

캐싱 & 재검증: 동일 API 중복 호출 방지

에러 처리: 선언적 에러 핸들링

로딩 상태: 자동 로딩 상태 관리

문제 50

코드 재사용성을 위해 어떤 패턴을 사용하셨나요

정답 및 해설

커스텀 훅: 비즈니스 로직 추상화

유틸리티 함수: 계산 로직 분리 (utils/item.ts)

복잡한 함수 분리를 통한, 코드 가독성 향상

문제 51

유지보수성을 위해 어떤 부분에 신경 쓰셨나요

정답 및 해설

단일 책임 원칙: 각 함수/컴포넌트가 하나의 역할만 담당

명확한 네이밍: 함수/변수명으로 의도 명확히 표현

문제 52

useOptionSelection 훅을 어떤 설계 원칙으로 만드셨나요

정답 및 해설

1. 단일 책임 원칙: 옵션 선택 로직만 담당

2. 재사용성: 다양한 옵션 타입(grid, list, select)에서 공통 사용

3. 확장성: Config 패턴으로 다양한 설정 지원

4. 사이드 이펙트 최소화: 상태 변경을 콜백으로 외부에 위임

문제 53

Union Type을 활용한 CatalogOption 설계에 대해 설명해주세요.


export type CatalogOption = CatalogOptionGrid | CatalogOptionList | CatalogOptionSelect;

정답 및 해설

판별 유니온: type 필드로 각 타입을 구분

타입 가드: 런타임에서 안전한 타입 좁히기 가능

확장성: 새로운 옵션 타입 추가 시 기존 코드 영향 최소화

문제 54

메모이제이션을 어디에 적용하셨고, 그 기준은?

정답 및 해설

1. 스키마 생성: useMemo로 옵션 변경 시만 재생성

2. 기준: 계산 비용이 높고, 의존성이 자주 변하지 않는 경우

문제 55

에러 경계(Error Boundary)를 구현하지 않은 이유는

정답 및 해설

현재는 선언적 에러 핸들링으로 충분하다고 판단했습니다.


SWR: API 에러 처리

React Hook Form: 폼 검증 에러

Toast: 사용자 피드백


실제 운영환경에서는 예상치 못한 에러를 위한 Error Boundary가 필요할 것입니다.

문제 56

네트워크 에러나 서버 장애 시 사용자 경험을 어떻게 개선할 수 있을까요?

정답 및 해설

Retry 로직: SWR의 자동 재시도 기능

Offline 지원: Service Worker로 캐시된 데이터 제공

Skeleton UI: 로딩 상태의 시각적 개선

문제 57

이 프로젝트를 대규모 서비스로 확장한다면

정답 및 해설

마이크로 프론트엔드: 도메인별 팀 분리

상태 관리 분리: 도메인별 스토어 분할

컴포넌트 라이브러리: 디자인 시스템 구축

모니터링: 성능 메트릭 수집 및 분석

문제 58

이 코드에서 개선할 점이 있다면

정답 및 해설

Error Boundary: 예상치 못한 에러 처리

Loading State: Skeleton UI로 사용자 경험 개선

Testing: 핵심 로직에 대한 단위 테스트

문제 59

이 프로젝트에서 가장 고민했던 부분은 무엇인가요?

정답 및 해설

바구니 상태 관리가 가장 큰 고민이었습니다.

- 같은 상품이지만 옵션이 다르면 별도 아이템으로 관리

- 동일한 상품+옵션이면 수량만 증가

- 새로고침해도 장바구니 유지

- 실시간 가격 계산

- 이를 위해 Zustand + persist 조합과 옵션 비교 로직을 핵심으로 설계했습니다.

문제 60

만약 이 프로젝트를 다시 한다면 다르게 할 부분이 있나요

정답 및 해설

1. 테스트 코드: 비즈니스 로직부터 TDD로 접근

2. 에러 바운더리: 예상치 못한 에러 대비

문제 61

 폴더 구조를 이렇게 설계한 이유는

정답 및 해설

도메인 기반 구조를 선택했습니다:

응집도 높임: 관련 코드가 한 곳에 모임

유지보수성: 기능 추가/수정 시 찾기 쉬움

문제 62

폼 라이브러리로 React Hook Form을 선택한 이유는

정답 및 해설

복잡한 옵션 검증 때문이었습니다:

옵션별로 다른 검증 규칙 (필수/선택, 최소/최대 개수)

실시간 검증 피드백

성능 (리렌더링 최소화)

Formik 대비 uncontrolled 방식으로 성능이 더 좋고, Zod와의 조합도 완벽했습니다.

문제 63

사용자 경험을 위해 특별히 신경 쓴 부분은?

정답 및 해설

장바구니 영속화:

실수로 새로고침해도 안전

즉각적 피드백: 에러 발생 시 Toast + 해당 위치로 스크롤

문제 64

성능 최적화는 어떤 부분에 집중하셨나요?

정답 및 해설

실제 병목이 될 만한 부분에 집중했습니다


스키마 생성: useMemo로 옵션 변경시만 재생성

API 호출: SWR 캐싱으로 중복 요청 방지

문제 65

개발하면서 가장 어려웠던 문제와 해결 과정은

정답 및 해설

복잡한 옵션 검증 로직이 가장 힘들었습니다.


Grid 옵션: 반드시 1개 선택

List 옵션: 최소/최대 개수 제한

Select 옵션: 0~1개 선택

각각 다른 에러 메시지와 UI 피드백


처음에는 각 컴포넌트에서 개별 검증 → 중복 코드 발생

Zod superRefine으로 통합 검증 로직 구현

에러 메시지에 optionId포함해서 스크롤 위치 특정

커스텀 훅으로 옵션 선택 로직 추상화

문제 66

예상치 못한 버그나 이슈가 있었나요

정답 및 해설

장바구니 새로고침 시 총합이 안 맞는 문제가 있었습니다.

원인: Zustand persist에서 데이터 복원 시 계산된 값들이 초기화되지 않음

해결: onRehydrateStorage 콜백에서 총합 재계산

이 경험으로 상태 복원 로직의 중요성을 깨달았습니다.

문제 67

이 코드를 팀원이 이해하기 쉽게 만든 부분

정답 및 해설

명확한 네이밍: calculateItemPrice

mergeCartItem 등 의도가 드러나는 함수명

타입 정의: 모든 데이터 구조를 인터페이스로 명시

폴더 구조: 기능별로 파일이 어디에 있는지 예측 가능

순수 함수: 사이드 이펙트 없는 유틸리티 함수들

문제 68

이 프로젝트가 실제 서비스가 된다면 어떤 부분을 먼저 개선하겠습니까?

정답 및 해설

모니터링: 에러 추적, 성능 메트릭 수집

접근성: 스크린 리더 지원

문제 69

사용자가 10배로 늘어난다면 어떤 부분이 문제가 될까요

정답 및 해설

번들 크기: 코드 스플리팅으로 초기 로딩 개선

에러 추적: 대규모 에러 모니터링 시스템

문제 70

이 프로젝트를 통해 가장 많이 배운 것은?

정답 및 해설

"추상화의 적정선"입니다.

너무 추상화하면 복잡해짐

너무 구체적이면 재사용성 떨어짐

실제 요구사항에 맞는 적절한 추상화를 찾는 게 핵심

특히 useOptionSelection 훅에서 이런 고민을 많이 했습니다.

문제 71

토스 개발 문화에 맞춰 어떤 부분을 더 발전시키고 싶나요?

정답 및 해설

사용자 중심 사고: 개발자가 아닌 사용자 관점에서 UX 고민

데이터 기반 의사결정: A/B 테스트, 메트릭 기반 개선

빠른 실험과 검증: MVP로 빠르게 검증 후 개선

팀 협업: 코드 리뷰, 지식 공유 문화