PHP 미드레벨 시스템 설계 면접

PHP 미드레벨 (3~7년) 시스템 설계 5문항 조회수 68 · 2026-07-07 (화) 03:11:04
1 API 설계
Medium

Q. 대규모 B2B SaaS 플랫폼에서 멀티테넌시(Multi-tenancy) 아키텍처를 설계할 때, Database per Tenant, Schema per Tenant, Shared Schema 방식의 차이점과 각각의 장단점을 설명해주세요. 특히 테넌트별 데이터 격리, 비용 효율성, 확장성, 백업/복구 전략 측면에서 비교해주세요.

A. 모범답안

Database per Tenant는 각 고객사마다 독립된 DB를 사용하여 완벽한 격리와 커스터마이징이 가능하지만 운영 비용이 높고, Schema per Tenant는 하나의 DB에 테넌트별 스키마를 분리하여 중간 수준의 격리를 제공하며, Shared Schema는 모든 테넌트가 동일 테이블을 공유하되 tenant_id로 구분하여 비용 효율적이지만 데이터 격리가 약합니다. B2B 엔터프라이즈 고객이 많다면 Database per Tenant, 중소기업 대상이라면 Shared Schema가 적합하며, 하이브리드 방식으로 VIP 고객은 독립 DB, 일반 고객은 공유 스키마를 사용하는 전략도 고려할 수 있습니다.

핵심 포인트
  • • Database per Tenant: 완벽한 격리, 높은 비용, 개별 백업 가능
  • • Schema per Tenant: 중간 수준 격리, 연결 풀 공유 가능
  • • Shared Schema: 비용 효율적, tenant_id 필터링 필수, Row-Level Security 활용
  • • 테넌트 규모와 SLA 요구사항에 따라 하이브리드 전략 고려
Follow-up 질문

Shared Schema 방식에서 실수로 tenant_id 필터를 누락하여 다른 테넌트 데이터가 노출되는 것을 방지하기 위한 안전장치를 어떻게 구현하시겠습니까?

2 데이터베이스 설계
Hard

Q. 실시간 채팅 애플리케이션에서 사용자 간 메시지 데이터를 저장하는 데이터베이스 스키마를 설계할 때, 관계형 DB(MySQL)와 NoSQL(MongoDB, Cassandra)의 적합성을 비교하고, 각 DB를 선택했을 때의 스키마 설계 방식과 인덱싱 전략을 설명해주세요. 특히 메시지 조회, 읽지 않은 메시지 카운트, 검색 기능을 효율적으로 처리하는 방법을 포함해주세요.

A. 모범답안

MySQL은 트랜잭션과 복잡한 쿼리가 필요한 경우 적합하며 messages 테이블에 (room_id, created_at) 복합 인덱스와 (receiver_id, is_read, created_at) 인덱스를 생성하여 조회 성능을 확보합니다. MongoDB는 채팅방별로 document를 구성하고 메시지를 배열로 저장하여 한 번의 쿼리로 대화 내역을 가져올 수 있으며, Cassandra는 시계열 데이터에 최적화되어 파티션 키를 (room_id, date)로 설정하고 클러스터링 키를 created_at으로 하여 대용량 메시지를 효율적으로 처리합니다. 읽지 않은 메시지 카운트는 별도의 unread_counts 테이블이나 Redis를 활용하여 실시간으로 관리하고, 전문 검색은 Elasticsearch를 추가로 도입하는 것이 효과적입니다.

핵심 포인트
  • • MySQL: 트랜잭션 보장, 복합 인덱스로 범위 쿼리 최적화
  • • MongoDB: 채팅방 단위 document, 배열 내장으로 조회 성능 향상
  • • Cassandra: 시계열 데이터 최적화, 파티션 키 설계가 성능의 핵심
  • • 읽지 않은 메시지는 Redis 카운터로 별도 관리
  • • 검색 기능은 Elasticsearch 도입 고려
Follow-up 질문

채팅방당 메시지가 수백만 건 이상 쌓였을 때 MongoDB의 배열 기반 설계에서 발생할 수 있는 문제점과 해결 방법은 무엇입니까?

3 캐싱 전략
Medium

Q. 뉴스 포털 사이트에서 기사 상세 페이지의 조회수를 실시간으로 집계하면서도 DB 부하를 최소화하는 시스템을 설계해주세요. Redis를 활용한 조회수 증가 처리, DB 동기화 전략(Write-back), 그리고 정확도와 성능 사이의 트레이드오프를 어떻게 조정할지 설명해주세요.

A. 모범답안

Redis의 INCR 명령어로 article:views:{article_id} 키에 조회수를 실시간 증가시키고, 매 N회 증가마다 또는 일정 시간 간격으로 배치 작업을 통해 DB에 동기화하는 Write-back 방식을 사용합니다. Redis에서 INCRBY로 증가된 값을 가져온 후 UPDATE articles SET views = views + ? WHERE id = ? 쿼리로 일괄 반영하며, Redis 장애에 대비해 DB의 현재 값을 주기적으로 Redis에 백업합니다. 정확도가 중요하다면 동기화 주기를 짧게, 성능이 중요하다면 길게 설정하고, 실시간 조회수는 Redis 값과 DB 값을 합산하여 표시합니다. Redis Cluster를 사용하면 조회수 집계를 분산 처리할 수 있습니다.

핵심 포인트
  • • Redis INCR로 실시간 증가, DB 부하 최소화
  • • 배치 작업으로 주기적 동기화(Write-back 패턴)
  • • Redis 장애 대비 DB 값 백업 및 복구 전략
  • • 정확도 vs 성능 트레이드오프는 동기화 주기로 조정
  • • 표시 시 Redis + DB 값 합산 고려
Follow-up 질문

동일 사용자가 새로고침으로 조회수를 무한 증가시키는 것을 방지하기 위한 중복 집계 방지 전략을 설명해주세요.

4 보안
Hard

Q. 금융 서비스 API에서 민감한 개인정보(주민등록번호, 계좌번호 등)를 DB에 저장할 때 암호화 전략을 설계해주세요. 대칭키/비대칭키 암호화 선택 기준, 키 관리 방법(Key Rotation), 암호화된 데이터의 검색 가능성, 그리고 PHP에서 안전하게 구현하는 방법을 설명해주세요.

A. 모범답안

개인정보는 AES-256 대칭키 암호화로 저장하며, 암호화 키는 환경 변수나 AWS KMS, HashiCorp Vault 같은 키 관리 서비스에 보관합니다. 검색이 필요한 필드는 해시값을 별도 컬럼에 저장하되, 레인보우 테이블 공격 방지를 위해 사용자별 고유 salt를 사용하고, 부분 검색이 필요하면 토큰화(Tokenization) 방식을 고려합니다. Key Rotation은 새 키로 암호화된 데이터를 추가하고 구 키로 암호화된 데이터는 점진적으로 재암호화하며, 키 버전을 데이터와 함께 저장합니다. PHP에서는 openssl_encrypt/decrypt 함수를 사용하고, IV(Initialization Vector)를 매번 랜덤 생성하여 암호문과 함께 저장하며, 암호화된 데이터는 Base64 인코딩하여 저장합니다.

핵심 포인트
  • • AES-256 대칭키 암호화, 키는 KMS나 Vault에 보관
  • • 검색용 해시는 사용자별 salt와 함께 별도 저장
  • • Key Rotation: 키 버전 관리, 점진적 재암호화
  • • PHP openssl 함수 사용, 랜덤 IV 생성 필수
  • • 토큰화로 민감 데이터 분리 보관 고려
Follow-up 질문

암호화 키가 유출되었을 때 즉시 취해야 할 조치와 장기적인 복구 전략을 설명해주세요.

5 시스템 확장성
Hard

Q. 실시간 협업 문서 편집 서비스(Google Docs 유사)를 PHP로 구축할 때, WebSocket을 이용한 실시간 동기화, 동시 편집 충돌 해결(Operational Transformation 또는 CRDT), 그리고 수평 확장 시 서버 간 메시지 브로드캐스팅 전략을 설계해주세요.

A. 모범답안

PHP에서는 Ratchet이나 Swoole로 WebSocket 서버를 구현하고, 사용자의 편집 이벤트를 실시간으로 수신합니다. 동시 편집 충돌은 Operational Transformation(OT)으로 각 편집 작업에 위치와 버전 정보를 포함시켜 서버에서 변환하거나, CRDT(Conflict-free Replicated Data Type) 기반으로 각 클라이언트의 변경이 자동으로 병합되도록 설계합니다. 수평 확장 시에는 Redis Pub/Sub을 중앙 메시지 브로커로 사용하여 한 서버에서 받은 편집 이벤트를 다른 서버의 WebSocket 연결에도 브로드캐스팅하며, 문서별로 채널을 분리하여 불필요한 메시지 전파를 방지합니다. 문서 상태는 주기적으로 DB에 스냅샷으로 저장하고, 이벤트 소싱 패턴으로 모든 편집 이력을 보관하여 버전 관리와 롤백을 지원합니다.

핵심 포인트
  • • Ratchet/Swoole로 WebSocket 서버 구현
  • • OT 또는 CRDT로 동시 편집 충돌 해결
  • • Redis Pub/Sub으로 서버 간 메시지 브로드캐스팅
  • • 문서별 채널 분리로 메시지 전파 최적화
  • • 이벤트 소싱으로 편집 이력 보관 및 스냅샷 저장
Follow-up 질문

WebSocket 연결이 끊어졌다가 재연결될 때 놓친 편집 내용을 동기화하는 방법을 설명해주세요.

댓글 0

로그인 후 댓글을 작성할 수 있습니다.

아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!