Angular 리드·아키텍트 데이터베이스 기술면접
새 면접Q. 대규모 Angular 기반 SaaS 플랫폼을 설계 중입니다. 멀티 테넌시 환경에서 수천 개의 조직이 각자의 데이터를 가지며, 조직마다 사용자 정의 필드를 추가할 수 있어야 합니다. 이러한 요구사항을 만족하는 데이터베이스 모델링 전략을 설명하고, 각 접근법의 트레이드오프를 분석해주세요.
멀티 테넌시 격리 전략(Shared DB, Separate Schema, Separate DB)과 동적 스키마 확장 방법(EAV, JSONB, 스키마 확장)을 함께 고려해보세요.
멀티 테넌시는 세 가지 전략이 있습니다. Shared Database는 tenant_id로 격리하며 비용 효율적이나 보안과 성능 격리가 약합니다. Separate Schema는 중간 수준의 격리와 비용을 제공하며, Separate Database는 완전한 격리를 보장하지만 운영 복잡도가 높습니다. 사용자 정의 필드는 EAV 패턴(유연하나 쿼리 복잡), JSONB 컬럼(PostgreSQL에서 인덱싱 가능하며 균형적), 또는 동적 스키마 확장(성능 좋으나 마이그레이션 복잡)으로 구현합니다. 저는 Shared Database + JSONB 조합을 선호하는데, Row Level Security로 보안을 강화하고, GIN 인덱스로 JSONB 쿼리 성능을 확보하며, 비용 효율성을 유지할 수 있기 때문입니다. 대규모 엔터프라이즈 고객은 별도 스키마로 분리하는 하이브리드 전략도 고려합니다.
- • 멀티 테넌시 세 가지 격리 전략과 각각의 보안/성능/비용 트레이드오프 이해
- • 사용자 정의 필드 구현을 위한 EAV, JSONB, 동적 스키마 비교
- • 실무적 하이브리드 접근법과 보안 강화 방안 제시
SaaS 플랫폼에서 고객사별 데이터 격리와 커스터마이징 요구사항을 동시에 만족시켜야 할 때 필수적인 설계 결정입니다.
JSONB 컬럼을 사용할 때 쿼리 성능을 최적화하기 위한 인덱싱 전략과 주의사항은 무엇인가요?
Q. Angular 프론트엔드에서 복잡한 필터링과 정렬을 지원하는 대시보드를 개발했는데, 사용자가 10개 이상의 컬럼 중 임의로 조합해서 필터링하고 정렬할 수 있습니다. 데이터는 1억 건 이상이며, 모든 조합에 대해 복합 인덱스를 생성할 수 없는 상황입니다. 이런 환경에서 쿼리 성능을 보장하기 위한 인덱스 전략과 아키텍처 접근법을 설명해주세요.
단일 컬럼 인덱스의 인덱스 머지, 부분 인덱스, 커버링 인덱스, 그리고 OLAP 전용 스토어 분리를 고려해보세요.
이 문제는 인덱스만으로 해결할 수 없으며 아키텍처 수준의 접근이 필요합니다. 먼저 사용 패턴 분석을 통해 상위 80%의 쿼리 조합을 파악하고 해당 복합 인덱스를 우선 생성합니다. 자주 사용되는 필터 조건에는 부분 인덱스를 활용하고, SELECT 절을 최소화해 커버링 인덱스 효과를 극대화합니다. 근본적으로는 OLTP와 OLAP를 분리하여, 대시보드용 읽기 전용 복제본이나 ClickHouse/Elasticsearch 같은 분석 전용 스토어로 데이터를 비동기 동기화합니다. PostgreSQL의 경우 BRIN 인덱스를 시계열 데이터에 활용하거나, Materialized View로 자주 사용되는 집계를 미리 계산합니다. 프론트엔드에서는 페이지네이션과 가상 스크롤링으로 한 번에 가져오는 데이터를 제한하고, 쿼리 결과를 Redis에 캐싱하는 전략도 병행합니다.
- • 사용 패턴 기반 선택적 인덱스 생성과 부분/커버링 인덱스 활용
- • OLTP/OLAP 분리를 통한 아키텍처 레벨 해결
- • Materialized View, 분석 전용 스토어, 캐싱 등 복합적 최적화 전략
비즈니스 인텔리전스 대시보드나 관리자 페이지에서 다양한 필터 조합을 지원해야 할 때 반드시 고려해야 하는 설계 이슈입니다.
Materialized View를 사용할 때 데이터 신선도와 갱신 비용 사이의 트레이드오프를 어떻게 관리하시겠습니까?
Q. 재고 관리 시스템에서 동시에 여러 사용자가 같은 상품을 주문할 때 재고 차감 로직이 있습니다. Read Committed 격리 수준에서 발생할 수 있는 동시성 문제를 설명하고, Serializable 격리 수준으로 변경하는 것과 애플리케이션 레벨 락을 사용하는 것의 장단점을 비교해주세요. 실제 프로덕션 환경에서 어떤 접근법을 선택하시겠습니까?
Lost Update 문제와 격리 수준별 성능 영향, 그리고 SELECT FOR UPDATE, 낙관적/비관적 락의 특성을 고려해보세요.
Read Committed에서는 Lost Update 문제가 발생합니다. 두 트랜잭션이 동시에 재고 10을 읽고 각각 1씩 차감하면 최종 재고가 8이 아닌 9가 됩니다. Serializable 격리 수준은 완전한 직렬화를 보장하지만, 동시성이 크게 떨어지고 교착 상태와 직렬화 실패로 인한 재시도가 빈번해 처리량이 급감합니다. 실무에서는 Read Committed + SELECT FOR UPDATE(비관적 락)를 선호합니다. 재고 조회 시 행 레벨 락을 획득해 다른 트랜잭션을 대기시키며, 격리 수준 변경보다 영향 범위가 제한적입니다. 낙관적 락(version 컬럼)은 충돌이 적을 때 유리하나, 재고처럼 경합이 심한 경우 재시도가 많아 사용자 경험이 나빠집니다. 아키텍처 레벨에서는 Redis의 DECR 같은 원자적 연산이나, 메시지 큐로 주문을 직렬화하는 방법도 고려할 수 있습니다.
- • 격리 수준별 동시성 문제와 성능 트레이드오프 정확한 이해
- • 비관적 락(SELECT FOR UPDATE)과 낙관적 락의 사용 시나리오 구분
- • 실무 환경을 고려한 현실적 해결책 제시
전자상거래 재고 관리, 좌석 예약, 포인트 차감 등 동시 접근이 많은 자원을 다룰 때 필수적인 동시성 제어 지식입니다.
SELECT FOR UPDATE를 사용할 때 교착 상태를 방지하기 위한 전략은 무엇인가요?
Q. Angular 애플리케이션에서 사용자 목록 조회 API의 응답 시간이 5초 이상 걸린다는 보고를 받았습니다. EXPLAIN ANALYZE 결과 Seq Scan이 발생하고 있으며, 적절한 인덱스가 있음에도 옵티마이저가 사용하지 않는 상황입니다. 이런 경우 발생 가능한 원인들과 각각의 해결 방법을 설명해주세요.
통계 정보, 데이터 분포, 타입 불일치, 함수 사용, 카디널리티 등 옵티마이저의 판단 근거를 생각해보세요.
인덱스가 있는데도 사용되지 않는 주요 원인은 다섯 가지입니다. 첫째, 통계 정보가 오래되어 ANALYZE 명령으로 갱신이 필요합니다. 둘째, WHERE 절에서 컬럼에 함수를 적용하면(예: LOWER(name)) 인덱스를 못 쓰므로 함수 기반 인덱스를 생성하거나 쿼리를 재작성합니다. 셋째, 타입 불일치로 암묵적 형변환이 발생하면 인덱스가 무효화되므로 명시적 타입 캐스팅이나 애플리케이션에서 올바른 타입 전달이 필요합니다. 넷째, 데이터 분포상 테이블의 대부분을 읽어야 한다면 옵티마이저가 Seq Scan을 선택할 수 있으며, 이 경우 쿼리 조건을 더 선택적으로 만들거나 부분 인덱스를 고려합니다. 다섯째, 조인 순서나 통계의 카디널리티 추정이 잘못되었다면 힌트를 사용하거나 쿼리 구조를 개선합니다.
- • 통계 정보 갱신과 함수 사용으로 인한 인덱스 무효화 인식
- • 타입 불일치와 데이터 분포에 따른 옵티마이저 판단 이해
- • 각 원인별 구체적인 해결 방법 제시
프로덕션 환경에서 갑작스런 성능 저하가 발생했을 때 빠르게 원인을 파악하고 해결해야 하는 실무 상황입니다.
EXPLAIN ANALYZE 결과에서 실제 실행 시간과 예상 비용의 차이가 클 때 어떻게 해석하고 대응하시겠습니까?
Q. 레거시 모놀리식 시스템을 마이크로서비스로 전환하는 프로젝트를 리드하고 있습니다. 현재 하나의 PostgreSQL 데이터베이스를 여러 서비스가 공유하는 상황에서, 서비스별로 데이터베이스를 분리해야 합니다. 주문과 상품 서비스가 강하게 결합되어 있고 트랜잭션 일관성이 중요한데, 이를 안전하게 분리하기 위한 전략과 데이터 정합성 보장 방법을 설명해주세요.
Saga 패턴, 이벤트 소싱, CDC, 그리고 단계적 분리 전략을 고려해보세요.
데이터베이스 분리는 단계적으로 진행해야 합니다. 먼저 Strangler Fig 패턴으로 공유 DB를 유지하면서 서비스 경계를 논리적으로 분리하고, 서비스 간 직접 DB 접근을 API 호출로 전환합니다. 물리적 분리 시점에는 먼저 읽기 전용 복제본을 각 서비스에 할당하고, CDC(Change Data Capture)로 데이터 동기화를 검증합니다. 트랜잭션 일관성은 분산 환경에서 2PC 대신 Saga 패턴을 사용하며, Orchestration 방식으로 중앙에서 보상 트랜잭션을 관리하거나 Choreography 방식으로 이벤트 기반 조율을 선택합니다. 최종 일관성을 받아들이되, 비즈니스 크리티컬한 경우 주문 서비스가 상품 정보 스냅샷을 가지는 등 데이터 중복을 허용합니다. Outbox 패턴으로 이벤트 발행과 DB 변경의 원자성을 보장하고, 멱등성 키로 중복 처리를 방지합니다. 전환 기간 동안은 양방향 동기화와 데이터 검증 도구를 운영해 정합성을 모니터링합니다.
- • Strangler Fig 패턴을 통한 단계적이고 안전한 분리 전략
- • Saga 패턴과 Outbox 패턴으로 분산 환경에서 데이터 일관성 보장
- • 비즈니스 요구사항에 따른 데이터 중복과 최종 일관성 수용
레거시 시스템을 현대적인 아키텍처로 전환할 때 데이터베이스 분리는 가장 어렵고 리스크가 큰 작업으로, 아키텍트의 핵심 역량이 요구됩니다.
Saga 패턴에서 보상 트랜잭션이 실패하는 경우 어떻게 처리하시겠습니까?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!