MySQL 미드레벨 시스템 설계 면접
새 면접Q. 대규모 전자상거래 시스템에서 주문(Order)과 주문상품(OrderItem) 테이블을 설계할 때, 주문 총액을 주문 테이블에 중복 저장할지 매번 계산할지 결정해야 합니다. 각 방식의 장단점을 데이터 일관성, 성능, 확장성 관점에서 비교하고, 실무에서 어떤 방식을 선택할지 이유와 함께 설명해주세요.
주문 총액을 주문 테이블에 중복 저장하는 것이 실무에서 일반적으로 선호됩니다. 매번 계산하는 방식은 데이터 일관성은 보장하지만 조회 시마다 JOIN과 집계 연산이 필요해 성능이 저하되고, 주문 내역 조회가 빈번한 전자상거래 특성상 부적합합니다. 중복 저장 방식은 조회 성능이 우수하고 주문 확정 시점의 가격을 정확히 보존할 수 있으며, 트랜잭션 내에서 총액 계산 후 저장하고 애플리케이션 레벨에서 검증 로직을 추가하면 일관성도 충분히 보장할 수 있습니다. 또한 환불, 부분 취소 등 복잡한 비즈니스 로직 처리 시 히스토리 추적이 용이합니다.
- • 조회 성능: 중복 저장 시 집계 연산 불필요, 단순 SELECT로 조회 가능
- • 데이터 일관성: 트랜잭션과 애플리케이션 검증으로 보장 가능
- • 비즈니스 요구사항: 주문 확정 시점의 가격 보존 필요
- • 확장성: 복잡한 할인, 쿠폰 로직 적용 시 계산 결과 저장이 유리
주문 총액을 저장하는 방식을 선택했을 때, 주문상품의 가격이나 수량이 변경되는 경우 데이터 일관성을 어떻게 보장할 수 있을까요?
Q. 월간 활성 사용자 1000만 명 규모의 SNS 서비스에서 사용자 피드(Feed) 시스템을 설계한다고 가정합니다. 팔로우한 사용자들의 최신 게시물을 보여주는 기능을 구현할 때, Pull 방식(조회 시 실시간 집계)과 Push 방식(게시 시 팔로워 피드에 미리 저장)의 장단점을 비교하고, 하이브리드 방식을 적용한다면 어떤 기준으로 사용자를 구분할지 MySQL 설계와 함께 설명해주세요.
Pull 방식은 게시 시 부하가 없고 저장 공간이 효율적이지만 조회 시 다중 JOIN과 정렬이 필요해 응답 속도가 느립니다. Push 방식은 조회 성능이 우수하지만 팔로워가 많은 인플루언서 게시 시 대량의 쓰기 작업이 발생하고 저장 공간이 증가합니다. 하이브리드 방식에서는 팔로워 수를 기준으로 일반 사용자는 Push 방식을, 팔로워 1만 명 이상 인플루언서는 Pull 방식을 적용합니다. 테이블 설계 시 user_feed 테이블(user_id, post_id, created_at)에 (user_id, created_at) 복합 인덱스를 생성하고, 인플루언서 게시물은 캐시(Redis)에 저장 후 조회 시 병합하는 방식으로 구현합니다.
- • Pull 방식: 저장 효율적이나 조회 시 성능 저하, 실시간성 보장
- • Push 방식: 조회 빠르나 쓰기 부하 높음, 팬아웃 문제 발생
- • 하이브리드 전략: 팔로워 수 기준으로 방식 분리, 인플루언서는 캐싱 활용
- • 인덱스 설계: 시간순 정렬을 위한 복합 인덱스 필수
팔로워 수가 100만 명인 인플루언서가 게시물을 작성할 때, Pull 방식으로도 성능 문제가 발생할 수 있습니다. 이를 해결하기 위한 추가적인 최적화 방안은 무엇이 있을까요?
Q. MySQL과 Redis를 함께 사용하는 시스템에서 데이터 업데이트 시 캐시 일관성을 유지하기 위한 전략으로 Cache-Aside, Write-Through, Write-Behind 패턴이 있습니다. 각 패턴의 동작 방식과 장단점을 설명하고, 전자상거래의 상품 재고 관리 시스템에서는 어떤 패턴이 적합한지 이유와 함께 설명해주세요.
Cache-Aside는 애플리케이션이 캐시 미스 시 DB 조회 후 캐시에 저장하는 방식으로 구현이 간단하지만 업데이트 시 캐시 무효화 타이밍 이슈가 있습니다. Write-Through는 DB 쓰기와 동시에 캐시를 업데이트해 일관성이 높지만 쓰기 지연이 발생합니다. Write-Behind는 캐시에 먼저 쓰고 비동기로 DB에 반영해 성능은 우수하나 장애 시 데이터 손실 위험이 있습니다. 재고 관리는 정합성이 매우 중요하므로 Write-Through 패턴이 적합하며, 재고 차감 시 DB 트랜잭션 내에서 UPDATE 후 캐시를 즉시 갱신하고, 추가로 분산 락을 활용해 동시성 제어를 강화해야 합니다.
- • Cache-Aside: 읽기 중심, 캐시 무효화 전략 필요
- • Write-Through: 강한 일관성, 쓰기 지연 발생
- • Write-Behind: 높은 성능, 데이터 손실 위험
- • 재고 관리: 정합성 우선, Write-Through + 분산 락 조합
Write-Through 패턴을 사용할 때 DB 업데이트는 성공했지만 캐시 업데이트가 실패하는 경우, 데이터 불일치를 어떻게 해결할 수 있을까요?
Q. 대용량 데이터를 조회하는 API에서 페이지네이션을 구현할 때 Offset 기반 방식과 Cursor 기반 방식이 있습니다. 각 방식의 MySQL 쿼리 구조와 성능 특성을 설명하고, 실시간으로 데이터가 추가/삭제되는 SNS 타임라인 API에서는 어떤 방식이 적합한지 이유와 함께 설명해주세요.
Offset 방식은 LIMIT offset, count 형태로 구현되며 페이지 번호 기반 탐색이 가능하지만, offset이 커질수록 MySQL이 건너뛸 행을 모두 스캔해야 해 성능이 저하되고 데이터 변경 시 중복/누락이 발생할 수 있습니다. Cursor 방식은 WHERE id > last_id ORDER BY id LIMIT count 형태로 마지막 조회 지점을 기준으로 다음 데이터를 가져오며, 인덱스를 효율적으로 활용해 일정한 성능을 보장하고 실시간 데이터 변경에도 안정적입니다. SNS 타임라인은 최신순 조회가 주요 패턴이고 데이터가 실시간으로 변경되므로 Cursor 방식이 적합하며, created_at과 id를 조합한 복합 커서로 정확한 페이지네이션을 구현할 수 있습니다.
- • Offset 방식: 페이지 번호 접근 가능, 깊은 페이지에서 성능 저하
- • Cursor 방식: 일정한 성능, 실시간 데이터 변경에 안정적
- • 인덱스 활용: Cursor는 WHERE 조건으로 인덱스 range scan 가능
- • 타임라인 특성: 최신순 조회, 무한 스크롤에 Cursor 적합
Cursor 기반 페이지네이션에서 사용자가 이전 페이지로 돌아가는 기능을 구현하려면 어떻게 설계해야 할까요?
Q. 멀티 테넌트(Multi-Tenant) SaaS 애플리케이션에서 MySQL 데이터베이스를 설계할 때, 테넌트별 데이터 격리 전략으로 DB 분리, 스키마 분리, 테이블 내 컬럼 구분 방식이 있습니다. 각 방식의 장단점을 보안, 성능, 운영 복잡도, 비용 관점에서 비교하고, 테넌트 수가 1000개 이상이고 각 테넌트 데이터 크기가 다양한 B2B SaaS에서는 어떤 전략이 적합한지 설명해주세요.
DB 분리 방식은 완벽한 격리와 테넌트별 최적화가 가능하지만 관리 복잡도와 비용이 높아 소수의 대규모 테넌트에 적합합니다. 스키마 분리는 적절한 격리와 성능을 제공하지만 수백 개 이상의 스키마 관리가 어렵고 마이그레이션이 복잡합니다. 테이블 내 컬럼 구분(tenant_id)은 관리가 단순하고 비용 효율적이지만 쿼리마다 tenant_id 조건 필수이며 인덱스 설계가 중요합니다. 1000개 이상 테넌트의 B2B SaaS에서는 기본적으로 테이블 내 컬럼 구분 방식을 사용하되, 모든 테이블의 첫 번째 인덱스 컬럼에 tenant_id를 포함하고, 데이터 크기가 큰 상위 5% 테넌트는 별도 DB로 분리하는 하이브리드 전략이 적합합니다.
- • DB 분리: 최고 격리, 높은 비용, 소수 대형 테넌트용
- • 스키마 분리: 중간 수준 격리, 관리 복잡도 높음
- • 컬럼 구분: 비용 효율적, tenant_id 인덱스 전략 필수
- • 하이브리드 전략: 일반 테넌트는 공유, 대형은 분리
테이블 내 컬럼 구분 방식에서 개발자가 실수로 tenant_id 조건을 누락해 다른 테넌트 데이터에 접근하는 것을 방지하기 위한 기술적 안전장치는 무엇이 있을까요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!