Vue.js 미드레벨 종합 기술면접
새 면접Q. Vue 3에서 watchEffect와 watch의 차이점을 설명하고, 각각 어떤 상황에서 사용하는 것이 적절한지 설명해주세요. 또한 watchEffect가 의존성을 자동으로 추적하는 방식과 이로 인해 발생할 수 있는 문제점을 설명해주세요.
watchEffect는 즉시 실행되며 자동으로 의존성을 추적하지만, watch는 명시적으로 소스를 지정합니다.
watchEffect는 함수 내부에서 사용된 반응형 데이터를 자동으로 추적하며 즉시 실행되는 반면, watch는 명시적으로 감시할 대상을 지정하고 lazy하게 동작합니다. watchEffect는 side effect 로직이 단순하고 여러 반응형 데이터에 의존할 때 유용하며, watch는 이전 값과 새 값을 비교하거나 특정 데이터만 감시할 때 적합합니다. watchEffect의 자동 의존성 추적은 조건문 내부의 반응형 데이터가 있을 때 의도치 않은 재실행을 유발할 수 있으며, 이 경우 watch를 사용하거나 명시적으로 의존성을 제어해야 합니다. 또한 watchEffect는 cleanup 함수를 반환하여 이전 effect를 정리할 수 있어 비동기 작업 취소에 유용합니다.
- • watchEffect는 즉시 실행 및 자동 의존성 추적
- • watch는 명시적 소스 지정 및 이전/새 값 비교 가능
- • 조건문 내 반응형 데이터 사용 시 주의 필요
- • cleanup 함수를 통한 side effect 정리
사용자 설정이 변경될 때마다 자동으로 로컬스토리지에 저장하거나, 여러 필터 조건이 변경될 때 자동으로 데이터를 다시 불러오는 경우에 사용됩니다.
watchEffect 내부에서 비동기 API 호출을 할 때, 컴포넌트가 unmount되거나 의존성이 변경되어 재실행될 때 이전 요청을 취소하는 로직을 어떻게 구현하시겠습니까?
Q. Vue 애플리케이션에서 사용자 인증 토큰을 저장할 때 LocalStorage, SessionStorage, Cookie, Memory 중 어디에 저장하는 것이 적절한지 각각의 보안 측면과 사용성 측면에서 비교 분석하고, XSS와 CSRF 공격에 대한 취약성을 설명해주세요.
각 저장소의 JavaScript 접근 가능성, 만료 정책, HTTP 요청 포함 여부를 고려하세요.
LocalStorage와 SessionStorage는 JavaScript로 접근 가능하여 XSS 공격에 취약하지만 CSRF에는 안전합니다. Cookie는 HttpOnly 플래그를 사용하면 XSS를 방어할 수 있지만 자동으로 HTTP 요청에 포함되어 CSRF에 취약하므로 SameSite 속성 설정이 필요합니다. Memory 저장은 XSS와 CSRF 모두에 가장 안전하지만 새로고침 시 데이터가 사라져 사용성이 떨어집니다. 일반적으로 Access Token은 Memory 또는 HttpOnly Cookie에, Refresh Token은 HttpOnly, Secure, SameSite=Strict Cookie에 저장하는 것이 권장됩니다. 또한 민감한 토큰은 저장 전 암호화하고, CSP 헤더를 설정하여 XSS 공격 벡터를 최소화해야 합니다.
- • LocalStorage/SessionStorage는 XSS에 취약
- • HttpOnly Cookie는 XSS 방어 가능하나 CSRF 대책 필요
- • Memory 저장이 가장 안전하나 사용성 저하
- • 토큰 타입별 저장소 분리 전략
금융 서비스나 개인정보를 다루는 애플리케이션에서 사용자 인증 토큰의 안전한 저장 및 관리가 필수적입니다.
SPA에서 HttpOnly Cookie에 토큰을 저장할 때, JavaScript에서 토큰 만료 여부를 어떻게 확인하고 Refresh 로직을 구현할 수 있습니까?
Q. Vue 애플리케이션에서 실시간 채팅 기능을 구현할 때, 메시지를 시간순으로 정렬하면서 특정 사용자의 메시지만 빠르게 필터링하고, 읽지 않은 메시지 개수를 O(1)에 조회할 수 있는 자료구조를 설계해주세요. 메시지 추가, 사용자별 필터링, 읽음 처리의 시간 복잡도를 각각 분석하고, Vue의 반응성 시스템과 함께 사용할 때 주의할 점을 설명해주세요.
시간순 정렬을 위한 배열과 사용자별 인덱싱을 위한 Map, 읽지 않은 메시지 카운트를 별도로 관리하는 복합 구조를 고려하세요.
메시지 배열(시간순 정렬 유지), 사용자 ID를 키로 하는 Map(메시지 ID 배열 저장), 읽지 않은 메시지 카운트 객체를 조합하여 구현합니다. 메시지 추가는 배열 push와 Map 업데이트로 O(1), 사용자별 필터링은 Map에서 메시지 ID 목록을 가져와 O(k) (k는 해당 사용자 메시지 수), 읽지 않은 메시지 개수 조회는 카운트 객체에서 O(1)에 가능합니다. Vue의 반응성 시스템에서는 대량 메시지 추가 시 개별 push 대신 배치 업데이트를 사용하고, shallowRef나 shallowReactive로 깊은 감시를 방지하며, 메시지 객체는 Object.freeze로 불변화하여 성능을 최적화해야 합니다. 또한 메시지가 계속 증가하므로 일정 개수 이상 시 오래된 메시지를 제거하는 LRU 정책을 함께 구현해야 합니다.
- • 배열 + Map + 카운트 객체 복합 구조
- • 각 연산의 시간 복잡도 최적화
- • shallowRef/shallowReactive로 반응성 제어
- • 대량 데이터 처리 시 배치 업데이트 및 LRU 정책
슬랙이나 카카오톡 같은 실시간 메시징 애플리케이션에서 대량의 메시지를 효율적으로 관리하고 빠르게 검색할 수 있어야 합니다.
메시지가 100만 개 이상으로 증가했을 때 Virtual Scrolling과 함께 사용하면서 메모리 사용량을 제어하는 전략을 설명해주세요.
Q. Vue 3 애플리케이션에서 대시보드 페이지에 10개 이상의 차트 컴포넌트가 있고, 각 차트가 독립적으로 API를 호출하여 데이터를 로드합니다. 페이지 초기 로딩 시 네트워크 요청이 동시에 발생하여 브라우저의 HTTP 동시 연결 제한에 걸리고 일부 차트 로딩이 지연되는 문제가 발생했습니다. 이 문제를 해결하기 위한 여러 접근 방법과 각각의 장단점을 설명해주세요.
요청 큐잉, 우선순위 기반 로딩, 배치 요청, lazy loading 등 다양한 전략을 고려하세요.
첫째, 요청 큐를 구현하여 동시 요청 수를 제한하고 순차적으로 처리할 수 있지만 전체 로딩 시간이 증가합니다. 둘째, 뷰포트에 보이는 차트만 먼저 로드하고 나머지는 IntersectionObserver로 lazy loading하여 초기 로딩을 최적화할 수 있습니다. 셋째, 백엔드에 배치 API를 구현하여 여러 차트 데이터를 한 번의 요청으로 받아올 수 있지만 백엔드 수정이 필요합니다. 넷째, HTTP/2의 멀티플렉싱을 활용하여 동시 연결 제한 문제를 근본적으로 해결할 수 있습니다. 실무에서는 IntersectionObserver 기반 lazy loading과 우선순위 큐를 조합하여 중요한 차트는 즉시 로드하고 나머지는 지연 로드하는 하이브리드 방식이 효과적입니다. 또한 차트 데이터를 캐싱하고 stale-while-revalidate 패턴으로 이전 데이터를 먼저 보여주며 백그라운드에서 갱신하는 방법도 고려해야 합니다.
- • IntersectionObserver 기반 lazy loading
- • 요청 큐잉 및 우선순위 관리
- • 배치 API 및 HTTP/2 멀티플렉싱
- • 캐싱 및 stale-while-revalidate 패턴
관리자 대시보드나 분석 툴에서 여러 위젯이 동시에 데이터를 로드할 때 발생하는 성능 병목을 해결해야 합니다.
IntersectionObserver를 사용한 lazy loading을 Composable로 추상화할 때, 여러 차트 컴포넌트에서 재사용 가능하도록 어떻게 설계하시겠습니까?
Q. Vue 애플리케이션의 장바구니 기능에서 사용자가 쿠폰을 적용하고 결제를 진행할 때, 쿠폰 사용 처리와 재고 차감, 주문 생성이 하나의 트랜잭션으로 처리되어야 합니다. 데이터베이스의 ACID 속성이 무엇인지 설명하고, 이 시나리오에서 각 속성이 왜 중요한지, 그리고 트랜잭션 중간에 네트워크 오류가 발생했을 때 어떻게 처리되는지 설명해주세요.
Atomicity, Consistency, Isolation, Durability 각각의 역할과 트랜잭션 롤백 메커니즘을 고려하세요.
ACID는 Atomicity(원자성), Consistency(일관성), Isolation(격리성), Durability(지속성)를 의미합니다. Atomicity는 쿠폰 사용, 재고 차감, 주문 생성이 모두 성공하거나 모두 실패하도록 보장하여 부분 실패를 방지합니다. Consistency는 재고가 음수가 되거나 이미 사용된 쿠폰이 재사용되는 등 비즈니스 규칙 위반을 방지합니다. Isolation은 동시에 같은 쿠폰을 사용하려는 여러 사용자 간 충돌을 방지하며, Durability는 결제 완료 후 서버 장애가 발생해도 주문 데이터가 유실되지 않도록 보장합니다. 네트워크 오류 발생 시 데이터베이스는 자동으로 트랜잭션을 롤백하여 모든 변경사항을 취소하며, 애플리케이션 레벨에서는 사용자에게 재시도 옵션을 제공하고 멱등성 키를 사용하여 중복 결제를 방지해야 합니다.
- • ACID 속성의 정의와 역할
- • Atomicity로 부분 실패 방지
- • Isolation으로 동시성 제어
- • 롤백 메커니즘 및 멱등성 보장
전자상거래 결제 프로세스에서 재고 관리, 포인트 차감, 주문 생성 등 여러 작업이 원자적으로 처리되어야 데이터 정합성을 보장할 수 있습니다.
분산 시스템 환경에서 여러 마이크로서비스에 걸친 트랜잭션을 처리할 때 ACID를 보장하기 어려운 이유와 Saga 패턴 같은 대안을 설명해주세요.
Q. Vue SPA 애플리케이션에서 사용자가 작성 중인 긴 폼 데이터를 브라우저가 갑자기 종료되거나 탭이 닫혀도 복구할 수 있도록 자동 저장 기능을 구현해야 합니다. 저장 시점 결정 전략, 저장소 선택, 데이터 직렬화, 충돌 해결, 보안 고려사항을 포함하여 전체 시스템을 설계해주세요.
debounce, localStorage/IndexedDB 선택, 버전 관리, 암호화, 만료 정책을 고려하세요.
저장 시점은 사용자 입력 후 debounce(500ms~1초)를 적용하여 과도한 저장을 방지하고, beforeunload 이벤트에서도 저장합니다. 저장소는 단순 폼은 localStorage, 파일 첨부나 대용량 데이터는 IndexedDB를 사용하며, 5MB 제한을 고려합니다. 데이터는 JSON 직렬화하되 민감 정보는 Web Crypto API로 암호화하고, 타임스탬프와 버전 번호를 함께 저장합니다. 복구 시 저장된 데이터와 현재 폼 데이터의 타임스탬프를 비교하여 사용자에게 선택권을 주며, 7일 이상 된 데이터는 자동 삭제합니다. Vue에서는 Composable로 추상화하여 watch로 폼 상태 변경을 감지하고, onBeforeUnmount에서 cleanup하며, Pinia 스토어에 저장된 데이터를 관리하여 여러 컴포넌트에서 공유할 수 있도록 합니다. 또한 여러 탭에서 동시 편집 시 BroadcastChannel API로 동기화하고 충돌을 방지합니다.
- • debounce 및 beforeunload 이벤트 활용
- • localStorage/IndexedDB 선택 기준
- • 암호화 및 버전 관리
- • Composable 패턴 및 BroadcastChannel 동기화
구글 문서나 노션처럼 사용자가 긴 문서를 작성할 때 데이터 손실을 방지하고 언제든 이전 작업을 복구할 수 있어야 합니다.
사용자가 여러 디바이스에서 동일한 폼을 작성할 때 클라우드 동기화를 추가한다면 어떤 충돌 해결 전략을 사용하시겠습니까?
Q. Vue 프로젝트에서 성능 최적화 작업을 진행하던 중, 기존 코드의 구조적 문제로 인해 예상보다 훨씬 많은 시간이 소요될 것으로 판단되었습니다. 이미 일정을 약속한 상태였고 다른 팀원들도 이 작업에 의존하고 있었는데, 일정을 지키기 어렵다는 것을 언제, 어떻게 공유하셨는지, 그리고 문제를 해결하기 위해 어떤 대안을 제시하고 실행하셨는지 STAR 방식으로 말씀해주세요.
조기 커뮤니케이션, 우선순위 조정, 단계적 접근, 팀 협업을 통한 해결 과정을 구조화하여 설명하세요.
이 질문은 경험 기반 답변이 필요하므로 STAR 형식으로 구성하세요. Situation: 프로젝트 배경과 성능 최적화가 필요했던 이유, 약속한 일정과 의존 관계를 설명합니다. Task: 작업 중 발견한 구조적 문제의 구체적 내용과 예상 지연 규모를 명확히 합니다. Action: 문제를 발견한 즉시 팀 리더와 이해관계자에게 투명하게 공유하고, 핵심 성능 이슈만 먼저 해결하는 단계적 접근을 제안했으며, 리팩토링이 필요한 부분은 별도 태스크로 분리하여 우선순위를 조정한 과정을 설명합니다. 필요시 다른 팀원의 코드 리뷰나 페어 프로그래밍을 요청하여 병목을 해소한 경험도 포함합니다. Result: 최종적으로 핵심 성능 개선은 일정 내 완료하고, 추가 리팩토링은 다음 스프린트로 이관하여 팀 전체 일정에 미치는 영향을 최소화한 결과와 이를 통해 배운 점(조기 리스크 공유의 중요성, 작업 분할 전략 등)을 정리합니다.
- • 조기에 투명하게 리스크 공유
- • 우선순위 기반 단계적 접근
- • 팀 협업 및 작업 분할
- • 결과 및 학습한 교훈
실무에서는 예상치 못한 기술 부채나 복잡도로 인해 일정이 지연될 수 있으며, 이를 조기에 투명하게 공유하고 대안을 제시하는 능력이 중요합니다.
만약 이해관계자가 일정 연장을 받아들이지 않고 원래 일정을 고수하라고 요구했다면 어떻게 대응하셨을까요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!