TIL - 프론트엔드 기술면접 대비 정리본

·2025년 7월 22일

📖 TIL

목록 보기
85/90

취업준비생 개발자를 위한 실전 기술면접 질문 & 답변 총정리
React, JavaScript, 최적화, 비동기까지 한 번에!


📋 목차


🎯 1차 기술면접

⚛️ React의 상태 관리: useState vs useReducer

🤔 면접관 질문: "React의 상태 관리 방법 중 useState와 useReducer의 차이점은 무엇인가요?"

💡 핵심 답변:

  • useState: 간단한 상태관리 (숫자, 문자열, 체크박스 등)
  • useReducer: 복잡한 상태 변화 처리 (액션 → 변화 과정)
// useState: 간단한 상태
const [count, setCount] = useState(0);

// useReducer: 복잡한 상태 흐름
const [state, dispatch] = useReducer(reducer, initialState);

💼 실무 경험 포인트:

"저는 단순한 input은 useState로, API 요청이나 상태 흐름이 있는 UI는 useReducer로 관리합니다. 예를 들어 API 호출 시 loading, data, error를 묶어서 처리할 때 useReducer가 훨씬 직관적이에요!"


🔒 JavaScript 클로저(Closure)

🤔 면접관 질문: "JavaScript에서 클로저란 무엇인가요? 어떤 상황에서 유용한가요?"

💡 핵심 답변:
클로저는 함수가 선언될 때의 환경(스코프)을 기억하는 함수예요.

📌 활용 상황:

  • 함수형 프로그래밍에서 자주 사용
  • 캡슐화: 내부 상태를 숨기고, 함수로만 조작하게 만드는 구조
  • setTimeout 같은 비동기 코드에서 유용
// 클로저 예시: 캡슐화
function createCounter() {
  let count = 0; // 외부에서 접근 불가
  return function() {
    return ++count; // 클로저로 count 기억
  };
}

⚡ 웹 페이지 렌더링 최적화 전략

🤔 면접관 질문: "웹 페이지 렌더링 최적화를 위해 어떤 전략을 써본 경험이 있으신가요?"

💡 핵심 답변:

🖼️ 이미지 최적화

  • Next.js의 next/image 활용
  • 자동 WebP 변환, lazy loading 기본 적용
  • 뷰포트 밖 이미지는 안 불러와서 LCP 개선

📦 코드 스플리팅

import dynamic from 'next/dynamic';

const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  ssr: false, // 클라이언트에서만 로드
  loading: () => <div>로딩중...</div>
});

🎯 기타 최적화 기법

  • SSG/SSR 적절한 활용
  • Critical CSS 추출
  • Lazy Loading + IntersectionObserver

📊 성과 포인트:

"구글 분석에 의하면 페이지 로딩이 1초에서 3초로 느려질 경우 이탈률이 32% 증가해요. 그래서 항상 LCP를 3초 이하로 유지하는 걸 목표로 최적화 작업을 합니다!"


🌐 CORS 문제와 해결방법

🤔 면접관 질문: "CORS란 무엇이고, CORS 문제가 발생하면 어떻게 해결하나요?"

💡 핵심 답변:
CORS는 Cross-Origin Resource Sharing으로, 브라우저가 다른 도메인에서 데이터를 가져오는 걸 기본적으로 막는 보안 정책이에요.

🔧 해결 방법:
1. 서버 측에서 허용 (Access-Control-Allow-Origin)
2. 프록시 서버 만들기 (Glitch, Next API Routes)

// Next.js API Routes로 CORS 우회
export default async function handler(req, res) {
  const response = await fetch('외부API주소');
  const data = await response.json();
  res.json(data);
}

🎯 TypeScript 사용 경험

🤔 면접관 질문: "TypeScript를 실제로 사용해본 경험이 있으신가요? 장점과 단점은?"

✅ 장점:

  • 타입 안정성: 런타임 전에 에러 잡아줌
  • 자동완성/인텔리센스: 개발 생산성 향상
  • 디버깅 쉬움: 어떤 값이 어떤 타입인지 명확

❌ 단점:

  • 초기 러닝커브 (환경 설정, 타입 정의)
  • 외부 라이브러리에 타입 없으면 직접 정의해야 함

🎯 핵심 한줄 요약:

"JS보다 엄격하지만, 안전하고 유지보수가 쉬운 언어예요!"


🔥 2차 심화 기술면접

🚀 React 성능 최적화: memo, useMemo, useCallback

🤔 면접관 질문: "React.memo, useMemo, useCallback의 차이점은 무엇인가요?"

💡 핵심 답변:

용도사용 시점
React.memo컴포넌트 메모이제이션props가 안 바뀌는 컴포넌트
useMemo값 메모이제이션계산 비용이 큰 연산 결과
useCallback함수 메모이제이션자식에 넘기는 함수 최적화

⚠️ 주의사항:

"오히려 렌더링보다 캐싱 비용이 더 크면 성능 저하 가능하니까, 꼭 필요한 상황에서만 사용해야 해요!"


🎪 DOM 이벤트: 버블링 vs 캡처링

🤔 면접관 질문: "이벤트 버블링과 캡처링이란 무엇인가요?"

💡 핵심 답변:
DOM 이벤트는 캡처링(부모→자식) → 타겟 이벤트 → 버블링(자식→부모) 순서로 전파돼요.

// 이벤트 전파 막기
function handleClick(e) {
  e.stopPropagation(); // 상위로 이벤트 전파 차단
}

// 캡처링 단계에서 이벤트 감지
element.addEventListener('click', handler, { capture: true });

💼 실무 예시:

"모달 안의 버튼 클릭 시, 배경까지 클릭 이벤트가 전파되는 걸 막을 때 stopPropagation() 사용해요!"


🌐 REST API vs GraphQL

🤔 면접관 질문: "REST API와 GraphQL의 차이는 무엇인가요?"

💡 핵심 답변:

🔗 REST API

  • 리소스를 URL로 표현
  • HTTP 메서드(GET, POST, PUT, DELETE)로 조작
  • 여러 API 호출 필요할 수 있음

⚡ GraphQL

  • 클라이언트가 원하는 데이터만 요청
  • 하나의 엔드포인트로 모든 데이터 처리
  • Over-fetching, Under-fetching 문제 해결

💼 선택 기준:

"데이터 구조가 복잡하고 N+1 문제가 많다면 GraphQL, 간단한 CRUD라면 REST가 적합해요!"


⏰ 비동기 처리: callback → promise → async/await

🤔 면접관 질문: "callback, promise, async/await의 차이를 설명해주세요."

💡 진화 과정:

1️⃣ Callback (콜백 지옥 😱)

getData(function(a) {
  getMoreData(a, function(b) {
    getMoreData(b, function(c) {
      // 콜백 지옥...
    });
  });
});

2️⃣ Promise (체이닝 🔗)

getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .catch(error => console.error(error));

3️⃣ Async/Await (동기식 코드처럼! ✨)

async function fetchData() {
  try {
    const a = await getData();
    const b = await getMoreData(a);
    return await getMoreData(b);
  } catch (error) {
    console.error(error);
  }
}

🧩 컴포넌트 재사용성 높이는 방법

🤔 면접관 질문: "컴포넌트 재사용성을 높이기 위한 방법에는 어떤 것이 있나요?"

💡 핵심 전략:

🔬 아토믹 디자인 패턴

  • 원자(Atom): <Input />, <Button />
  • 분자(Molecule): <FormGroup />, <SearchBox />
  • 유기체(Organism): <Header />, <ProductList />
  • 페이지(Page): 최종 조합

🎯 SOLID 원칙 적용

  • SRP: 단일 책임 원칙
  • DIP: 의존성 역전 (추상화된 인터페이스에 의존)
// 재사용 가능한 컴포넌트 예시
function Button({ variant = 'primary', size = 'md', children, ...props }) {
  return (
    <button 
      className={`btn btn--${variant} btn--${size}`} 
      {...props}
    >
      {children}
    </button>
  );
}

🔧 추가 기법:

  • Custom Hook으로 로직 분리
  • Composition Pattern 활용
  • Props 인터페이스 명확히 설계

💡 면접 팁

🎯 답변할 때 이것만 기억하자!

  1. 경험 + 이론 조합하기
  2. 구체적인 예시 들기
  3. 장단점 균형있게 설명
  4. 실무에서 왜 선택했는지 근거 제시

🚀 추가 학습 키워드

  • 성능: Web Vitals, LCP, FCP, CLS
  • 상태관리: Redux Toolkit, Zustand, Jotai
  • 테스팅: Jest, React Testing Library
  • 빌드도구: Webpack, Vite, SWC
profile
주니어 프론트엔드 성장기 기록기록

0개의 댓글