JavaScript 주니어 시스템 설계 면접
새 면접Q. 사용자 인증이 필요한 게시판 서비스의 RESTful API를 설계할 때, JWT 토큰을 어떻게 관리하고 전달하는 것이 좋은지 설명해주세요. 또한 토큰 만료 시 사용자 경험을 해치지 않기 위한 방법을 제시해주세요.
JWT 토큰은 로그인 성공 시 Access Token(짧은 만료시간)과 Refresh Token(긴 만료시간)을 함께 발급합니다. Access Token은 HTTP Authorization 헤더에 Bearer 스키마로 전달하고, Refresh Token은 HttpOnly 쿠키에 저장하여 XSS 공격을 방지합니다. Access Token 만료 시 Refresh Token으로 자동 갱신하는 엔드포인트(/api/auth/refresh)를 제공하여 사용자가 재로그인 없이 서비스를 계속 이용할 수 있게 합니다. 클라이언트는 401 응답을 받으면 자동으로 토큰 갱신을 시도하는 인터셉터를 구현합니다.
- • Access Token과 Refresh Token의 이중 토큰 전략 사용
- • Access Token은 Authorization 헤더, Refresh Token은 HttpOnly 쿠키에 저장
- • 토큰 자동 갱신 메커니즘으로 사용자 경험 개선
- • HTTP 인터셉터를 통한 401 에러 처리 및 자동 재시도
만약 Refresh Token마저 만료되었을 때는 어떻게 처리해야 하며, 보안을 위해 Refresh Token에 추가로 적용할 수 있는 전략은 무엇인가요?
Q. 전자상거래 쇼핑몰에서 상품, 카테고리, 주문, 사용자 테이블을 설계한다고 가정할 때, 하나의 상품이 여러 카테고리에 속할 수 있고 하나의 주문에 여러 상품이 포함될 수 있는 관계를 어떻게 모델링해야 하는지 설명해주세요.
상품과 카테고리의 다대다(N:M) 관계를 위해 중간 테이블인 product_categories를 생성하여 product_id와 category_id를 외래키로 관리합니다. 주문과 상품의 다대다 관계를 위해서는 order_items 테이블을 생성하여 order_id, product_id와 함께 수량(quantity), 가격(price) 등 주문 시점의 정보를 저장합니다. 주문 시점의 가격을 별도로 저장하는 이유는 상품 가격이 변경되더라도 과거 주문 내역이 영향받지 않도록 하기 위함입니다. 각 테이블에는 created_at, updated_at 같은 타임스탬프 필드를 추가하여 데이터 추적을 용이하게 합니다.
- • 다대다 관계는 중간 테이블(junction table)로 해결
- • product_categories와 order_items 중간 테이블 생성
- • 주문 시점의 스냅샷 데이터(가격, 상품명 등)를 order_items에 저장
- • 타임스탬프 필드로 데이터 변경 이력 관리
상품 재고 관리를 위해 동시에 여러 사용자가 같은 상품을 주문할 때 재고 부족 문제를 방지하려면 어떤 전략을 사용해야 하나요?
Q. 뉴스 기사 웹사이트에서 인기 기사 목록을 보여주는 API의 응답 속도를 개선하기 위해 캐싱을 적용하려고 합니다. 어떤 캐싱 전략을 사용할 수 있으며, 캐시 무효화는 언제 어떻게 처리해야 하는지 설명해주세요.
서버 측 메모리 캐시(Redis 등)를 사용하여 인기 기사 목록 데이터를 저장하고, TTL(Time To Live)을 5~10분으로 설정하여 주기적으로 자동 갱신되도록 합니다. 클라이언트 측에서는 HTTP Cache-Control 헤더를 활용해 브라우저 캐싱도 함께 적용합니다. 새로운 기사가 발행되거나 조회수가 급증하는 등 데이터 변경이 발생하면 해당 캐시 키를 즉시 삭제(Cache Invalidation)하거나 갱신합니다. 캐시 미스(Cache Miss) 발생 시 DB 조회 후 결과를 캐시에 저장하는 Cache-Aside 패턴을 사용합니다.
- • Redis 같은 인메모리 캐시 사용으로 응답 속도 개선
- • TTL 설정으로 자동 캐시 만료 및 갱신
- • 데이터 변경 시 즉시 캐시 무효화 처리
- • Cache-Aside 패턴으로 캐시 미스 처리
만약 캐시 서버가 다운되었을 때 서비스 중단을 방지하기 위한 fallback 전략은 무엇이 있을까요?
Q. 사용자로부터 입력받은 검색어를 그대로 화면에 표시하는 검색 결과 페이지를 개발할 때, XSS(Cross-Site Scripting) 공격을 방지하기 위해 어떤 방법들을 적용해야 하는지 설명해주세요.
사용자 입력값을 DOM에 삽입할 때 innerHTML 대신 textContent나 innerText를 사용하여 HTML 태그가 실행되지 않도록 합니다. React나 Vue 같은 프레임워크를 사용하는 경우 기본적으로 제공되는 이스케이프 기능을 활용하되, dangerouslySetInnerHTML이나 v-html 같은 위험한 기능은 반드시 피합니다. 서버 측에서도 입력값 검증(Validation)과 새니타이제이션(Sanitization)을 수행하여 스크립트 태그나 이벤트 핸들러를 제거합니다. 추가로 CSP(Content Security Policy) 헤더를 설정하여 인라인 스크립트 실행을 차단하는 보안 계층을 추가합니다.
- • textContent 사용으로 HTML 태그 실행 방지
- • 프레임워크의 기본 이스케이프 기능 활용
- • 서버 측 입력값 검증 및 새니타이제이션
- • CSP 헤더로 추가 보안 계층 구성
CSP 헤더를 설정할 때 Google Analytics나 외부 광고 스크립트를 사용해야 한다면 어떻게 정책을 구성해야 하나요?
Q. 실시간 채팅 애플리케이션을 Node.js로 개발할 때, 사용자 수가 증가하면서 단일 서버로 처리하기 어려워졌습니다. 수평적 확장(Horizontal Scaling)을 위해 어떤 아키텍처 변경이 필요한지 설명해주세요.
WebSocket 연결을 유지하는 여러 대의 서버를 로드 밸런서 뒤에 배치하되, Sticky Session을 활성화하여 같은 사용자가 동일한 서버에 연결되도록 합니다. 하지만 서버 간 메시지 전달을 위해 Redis Pub/Sub이나 RabbitMQ 같은 메시지 브로커를 도입하여 한 서버에서 받은 메시지를 다른 서버의 클라이언트들에게도 전달할 수 있게 합니다. 세션 정보는 Redis 같은 외부 저장소에 중앙화하여 어느 서버에서든 사용자 상태를 확인할 수 있도록 합니다. 채팅방별로 샤딩(Sharding)을 적용하여 특정 채팅방은 특정 서버 그룹에서만 처리하도록 최적화할 수도 있습니다.
- • 로드 밸런서와 Sticky Session으로 다중 서버 구성
- • Redis Pub/Sub 등 메시지 브로커로 서버 간 통신
- • 세션 정보 중앙화로 상태 공유
- • 채팅방 기반 샤딩으로 부하 분산
만약 Redis Pub/Sub 대신 Kafka를 사용한다면 어떤 장점이 있으며, 어떤 경우에 Kafka를 선택하는 것이 더 적절한가요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!