React 면접 질문
React 면접은 컴포넌트 모델, 훅, 렌더링 동작 및 성능에 대한 이해도를 평가합니다. 개념 질문과 간단한 라이브 코딩 과제가 혼합되어 나옵니다.
React 면접에서 다루는 내용
훅과 상태
useState, useEffect, useMemo/useCallback, 커스텀 훅 및 훅 규칙.
렌더링 및 재조정
React가 다시 렌더링하는 방법, 키, 가상 DOM 및 불필요한 렌더링 방지.
상태 관리
로컬 상태 vs 끌어올린 상태, 컨텍스트, Redux, Zustand 또는 React Query를 사용할 시기.
성능
메모이제이션, 코드 분할, 지연 로딩 및 느린 컴포넌트 프로파일링.
샘플 React 면접 질문
- React 훅은 어떤 문제를 해결하며, 훅의 규칙은 무엇인가요?좋은 답변이 다루는 것
- 클래스 컴포넌트의 생명주기 메서드 중복 문제 해결
- 로직 재사용을 위한 HOC/render props 대안
- 훅의 규칙: 최상위에서만 호출, React 함수에서만 호출
- 훅 호출 순서 불변성의 중요성
- ESLint 플러그인의 역할
샘플 답변 보기
React 훅은 클래스 컴포넌트에서 생명주기 메서드가 관련 없는 로직을 혼합하는 문제와, HOC나 render props 패턴이 컴포넌트 트리를 복잡하게 만드는 문제를 해결합니다. 훅을 사용하면 상태 관련 로직을 함수 단위로 분리하여 재사용할 수 있습니다. 훅의 규칙은 두 가지입니다. 첫째, 훅을 반복문, 조건문, 중첩 함수 내에서 호출하지 말고 항상 컴포넌트의 최상위 레벨에서 호출해야 합니다. 이는 훅이 호출된 순서에 의존하기 때문입니다. 둘째, 훅은 반드시 React 함수 컴포넌트 또는 커스텀 훅 내에서만 호출해야 합니다. 일반 자바스크립트 함수에서 호출하면 안 됩니다. 이 규칙을 강제하기 위해 ESLint 플러그인 eslint-plugin-react-hooks를 사용하는 것이 좋습니다. 규칙을 위반하면 상태가 잘못 연결되거나 버그가 발생할 수 있습니다.
- useMemo와 useCallback의 차이점과 각각을 언제 사용하는 것이 좋은지 설명하세요.좋은 답변이 다루는 것
- useMemo: 계산 결과 메모이제이션 (값)
- useCallback: 함수 자체 메모이제이션 (참조 동일성)
- 의존성 배열 비교 방식 (Object.is)
- useMemo는 값 비싼 계산 최적화에 사용
- useCallback은 자식 컴포넌트에 콜백 전달 시 불필요한 렌더링 방지
샘플 답변 보기
useMemo와 useCallback 모두 불필요한 재계산이나 렌더링을 방지하기 위해 메모이제이션을 사용합니다. 차이점은 useMemo는 계산된 값을 캐싱하는 반면, useCallback은 함수 자체를 캐싱합니다. 즉, useMemo는 값의 변화가 없으면 이전 값을 반환하고, useCallback은 함수의 참조를 동일하게 유지합니다. 내부적으로는 useCallback(fn, deps)이 useMemo(() => fn, deps)와 동일합니다. useMemo는 복잡한 계산이나 대규모 배열 필터링 등의 결과를 캐싱할 때 유용합니다. 예를 들어, 피보나치 수열 계산이나 리스트 정렬 결과에 사용합니다. useCallback은 자식 컴포넌트에 함수를 props로 전달할 때, 그 함수가 불필요하게 재생성되는 것을 방지하여 자식의 리렌더링을 막습니다. 단, 두 훅 모두 의존성 배열을 정확히 명시해야 하며, 남용하면 오히려 메모리 낭비와 성능 저하를 일으킬 수 있습니다. 실제로 대부분의 경우 useMemo나 useCallback 없이도 충분하며, 프로파일링 후 필요한 곳에만 적용하는 것이 좋습니다.
- 컴포넌트가 다시 렌더링되는 원인과 불필요한 렌더링을 방지하는 방법은 무엇인가요?좋은 답변이 다루는 것
- 렌더링 원인: state 변경, props 변경, 부모 리렌더링, forceUpdate, context 변경
- React.memo를 통한 props 비교
- useMemo와 useCallback으로 참조 동일성 유지
- key prop을 통한 리스트 재조정 최소화
- 상태 끌어올리기와 컴포넌트 분할
샘플 답변 보기
컴포넌트가 다시 렌더링되는 주요 원인은 다섯 가지입니다. 첫째, 자신의 state가 setState나 useState의 setter로 변경될 때. 둘째, 부모로부터 받는 props가 변경될 때. 셋째, 부모 컴포넌트가 리렌더링되면 자식도 기본적으로 리렌더링됩니다. 넷째, forceUpdate() 호출 시. 다섯째, Context의 value가 변경되면 해당 Context를 구독하는 모든 컴포넌트가 리렌더링됩니다. 불필요한 렌더링을 방지하는 방법으로는 React.memo를 사용하여 props의 얕은 비교를 통해 리렌더링 여부를 결정할 수 있습니다. 또한 useMemo와 useCallback을 활용하여 값이나 함수의 참조를 안정화시키면 자식 컴포넌트의 불필요한 리렌더링을 막을 수 있습니다. 리스트를 렌더링할 때는 key prop에 고유하고 안정적인 값을 지정하여 React가 DOM을 효율적으로 업데이트하도록 합니다. 또 다른 방법은 상태를 가능한 낮은 위치로 내리고(상태 끌어올리기), 변경되지 않는 부분을 별도의 컴포넌트로 분리하여 리렌더링 범위를 최소화하는 것입니다. 하지만 과도한 최적화는 오히려 코드 복잡성을 증가시키므로, 실제 성능 문제가 발생했을 때 추적하여 해결하는 것이 바람직합니다.
- 리스트에서 key prop은 어떻게 작동하며, 왜 중요한가요?좋은 답변이 다루는 것
- key prop: React가 각 요소를 식별하는 고유 ID
- 리스트 재조정에서 효율적인 DOM 업데이트
- key가 없을 때 인덱스를 사용하면 발생하는 문제
- key는 형제 간 고유해야 하며 안정적이어야 함
- key 변경 시 컴포넌트 언마운트/리마운트
샘플 답변 보기
key prop은 React가 리스트 내의 각 요소를 고유하게 식별할 수 있도록 하는 특수 속성입니다. 리스트가 업데이트될 때, React는 key 값을 사용하여 이전 가상 DOM과 새로운 가상 DOM을 비교합니다. key가 있으면 React는 어떤 아이템이 추가, 제거, 재정렬되었는지 정확히 알 수 있어, 필요한 DOM 요소만 추가/제거/이동하여 효율적으로 업데이트합니다. key가 없으면 React는 기본적으로 인덱스를 사용하는데, 이는 아이템의 순서가 바뀌거나 중간에 아이템이 추가/제거될 때 문제가 발생합니다. 인덱스를 key로 사용하면 모든 아이템이 변경된 것으로 간주되어 성능이 저하될 뿐만 아니라, 입력 필드와 같은 상태가 있는 컴포넌트에서 상태가 꼬일 수 있습니다. 예를 들어, 리스트의 첫 번째 아이템이 제거되면 두 번째 아이템이 key 0을 갖게 되어 기존의 첫 번째 아이템의 상태를 그대로 물려받게 됩니다. 따라서 key는 가능한 데이터의 고유 ID(예: 데이터베이스 ID)를 사용해야 합니다. key가 변경되면 React는 해당 컴포넌트를 완전히 언마운트하고 새로 마운트하므로, key는 안정적이고 예측 가능해야 합니다.
- 커스텀 훅으로 디바운스된 검색 입력을 구현하세요.좋은 답변이 다루는 것
- 디바운스의 개념: 입력이 멈춘 후 일정 시간 지연 후 실행
- 타이머 관리와 클린업
- 검색어 상태와 디바운스된 값 분리
- AbortController로 중복 요청 취소
샘플 답변 보기
커스텀 훅 useDebounce는 사용자가 입력을 완료할 때까지 기다렸다가 실제 검색을 수행하도록 디바운스 기능을 제공합니다. 이 훅은 value와 delay를 인자로 받아, delay 밀리초 동안 값의 변경이 없으면 최종 값을 반환합니다. 구현 방식은 useEffect 내에서 setTimeout을 사용하여 delay 시간 후에 디바운스된 값을 업데이트하고, 클린업 함수에서 타이머를 제거하는 것입니다. 이렇게 하면 value가 자주 변경되어도 마지막 변경만 반영됩니다. 시간 복잡도는 O(1)이며, 각 호출마다 타이머를 설정하므로 메모리 사용량은 상수입니다. 주의할 점은 디바운스된 값이 변경될 때 실제 API 요청을 보내도록 useEffect를 추가로 사용해야 하며, 이전 요청이 완료되지 않은 경우 AbortController를 사용하여 취소하는 것이 좋습니다. 또한, delay 값을 너무 작게 설정하면 불필요한 요청이 많아지고, 너무 크게 설정하면 사용자 경험이 저하될 수 있습니다.
참고 코드typescript import { useState, useEffect, useRef } from 'react'; /** * 디바운스된 값을 반환하는 커스텀 훅 * @param value 디바운스할 값 * @param delay 지연 시간 (밀리초) * @returns 디바운스된 값 */ function useDebounce<T>(value: T, delay: number): T { const [debouncedValue, setDebouncedValue] = useState<T>(value); useEffect(() => { // delay 시간 후에 value를 debouncedValue로 설정 const timer = setTimeout(() => { setDebouncedValue(value); }, delay); // 컴포넌트가 언마운트되거나 value/delay가 변경되면 타이머 클리어 return () => { clearTimeout(timer); }; }, [value, delay]); return debouncedValue; } export default useDebounce; // 사용 예시: // function SearchComponent() { // const [searchTerm, setSearchTerm] = useState(''); // const debouncedSearchTerm = useDebounce(searchTerm, 500); // // useEffect(() => { // // debouncedSearchTerm이 변경될 때 API 호출 // if (debouncedSearchTerm) { // fetchSearchResults(debouncedSearchTerm); // } // }, [debouncedSearchTerm]); // // return ( // <input // value={searchTerm} // onChange={(e) => setSearchTerm(e.target.value)} // placeholder="검색어 입력..." // /> // ); // } - Context를 사용하는 경우와 Redux 또는 React Query 같은 상태 라이브러리를 사용하는 경우는 언제인가요?좋은 답변이 다루는 것
- Context: 단순한 전역 상태, 소규모 앱, 테마/인증 등
- React Query: 서버 상태 관리, 캐싱, 동기화
- Redux: 복잡한 클라이언트 상태, 미들웨어 필요, 대규모 팀
- Context의 단점: 렌더링 최적화 어려움, 큰 트리에서 성능 저하
- 선택 기준: 상태의 특성, 데이터 흐름, 팀 규모
샘플 답변 보기
Context API는 주로 테마, 로케일, 인증 정보처럼 여러 컴포넌트에서 전역적으로 사용되지만 자주 변경되지 않는 값을 전달할 때 적합합니다. 사용법이 간단하고 외부 라이브러리가 필요 없어 소규모 앱에 좋습니다. 그러나 Context 값이 변경되면 구독하는 모든 컴포넌트가 리렌더링되므로, 큰 트리에서 빈번한 업데이트가 있으면 성능 문제가 발생할 수 있습니다. React Query는 서버 상태(API 호출 결과)를 관리하는 데 특화되어 있습니다. 데이터 캐싱, 자동 재요청, 낙관적 업데이트 등을 제공하며, 비동기 데이터 흐름을 단순화합니다. 클라이언트 상태와 서버 상태를 분리하여 관리하는 것이 모범 사례입니다. Redux는 복잡한 클라이언트 상태 로직이 있고, 미들웨어(예: saga, thunk)를 통해 비동기 흐름을 제어해야 하며, 여러 팀이 함께 작업하는 대규모 프로젝트에 적합합니다. 단, 보일러플레이트가 많고 학습 곡선이 있습니다. 결론적으로, 상태가 서버에서 오는지 클라이언트에서 오는지, 상태 변경 빈도와 범위, 팀의 숙련도를 고려하여 선택해야 합니다. 최근에는 Redux 대신 Zustand나 Jotai 같은 가벼운 상태 관리 라이브러리도 많이 사용됩니다.
준비 방법
- 렌더링에 대해 소리 내어 추론할 수 있어야 합니다 — 면접관은 API 암기보다 사고 모델을 더 중요시합니다.
- 작은 라이브 코딩 과제(카운터, 디바운스 입력, 가져오기 및 목록 표시)를 자동으로 할 수 있을 때까지 연습하세요.
- 하나를 기본으로 사용하기보다 각 상태 도구의 장단점을 알아두세요.
- 최적화를 논할 때 성능 도구(React DevTools Profiler)를 언급하세요.
자주 묻는 질문
React 면접 질문은 주로 이론인가요, 코딩인가요?
둘 다입니다. 훅과 렌더링에 관한 개념 질문과 함께 작은 컴포넌트를 만드는 짧은 라이브 코딩 과제가 나옵니다.
React 면접을 위해 Redux를 알아야 하나요?
장단점과 상태 라이브러리가 도움이 되는 시점을 알아두세요. 하지만 많은 팀이 이제 Context + React Query를 선호합니다. 하나의 라이브러리를 암기하는 것보다 이유를 이해하는 것이 더 중요합니다.
어느 정도의 TypeScript 수준이 요구되나요?
대부분의 React 직무는 props, state, hooks에 대한 타입 지정에 익숙할 것을 기대합니다. 고급 제네릭은 시니어/인프라 역할이 아니면 거의 요구되지 않습니다.
React 면접을 어떻게 연습할 수 있나요?
시간 제한이 있는 라이브 코딩 과제를 수행하고 자신의 추론을 소리 내어 설명하세요. Offersly는 이력서에서 React 중심 질문을 생성하고 답변을 채점합니다.
즉각적인 AI 피드백으로 React 질문 연습하기
이력서를 업로드하고 맞춤형 모의 면접을 받아 무엇을 개선해야 할지 정확히 확인하세요 — 무료로 시작하세요.