PHP 시니어 기술면접
새 면접Q. HTTP/1.1과 HTTP/2의 주요 차이점을 설명하고, PHP 애플리케이션에서 HTTP/2의 Server Push와 Multiplexing 기능을 활용할 때의 이점과 주의사항을 실무 관점에서 설명해주세요. 특히 대규모 API 서버에서 고려해야 할 사항을 포함해주세요.
HTTP/1.1은 요청당 하나의 연결을 사용하며 Head-of-Line Blocking 문제가 있지만, HTTP/2는 하나의 연결에서 여러 스트림을 동시에 처리하는 Multiplexing을 지원합니다. Server Push는 클라이언트 요청 전에 리소스를 미리 전송할 수 있어 API 응답과 함께 관련 데이터를 푸시할 수 있습니다. 그러나 PHP-FPM 환경에서는 요청 단위로 프로세스가 종료되므로 Server Push 구현이 제한적이며, Nginx나 Caddy 같은 웹서버 레벨에서 처리해야 합니다. 대규모 API 서버에서는 불필요한 Push로 인한 대역폭 낭비를 방지하기 위해 클라이언트 캐시 상태를 고려한 선택적 Push 전략이 필요하며, Multiplexing으로 인한 동시 스트림 증가는 서버 메모리 사용량 증가로 이어질 수 있어 적절한 스트림 제한 설정이 필요합니다.
- • HTTP/2의 Multiplexing은 단일 연결에서 여러 요청/응답을 동시 처리하여 HOL Blocking 해결
- • Server Push는 웹서버 레벨에서 구현하며, PHP 애플리케이션은 Link 헤더로 푸시 힌트 제공
- • 대규모 환경에서는 불필요한 Push 방지와 동시 스트림 수 제한으로 리소스 관리 필요
- • PHP-FPM의 요청 단위 실행 모델로 인한 HTTP/2 기능 활용 제약 이해 필요
Swoole이나 ReactPHP 같은 비동기 PHP 런타임을 사용할 때 HTTP/2 활용이 어떻게 달라지며, 기존 PHP-FPM 대비 어떤 이점이 있나요?
Q. 데이터베이스 샤딩(Sharding) 전략의 종류(Range-based, Hash-based, Directory-based)를 설명하고, 각 전략의 장단점을 비교해주세요. 또한 PHP 애플리케이션에서 샤딩을 구현할 때 발생하는 Cross-shard Query와 분산 트랜잭션 문제를 어떻게 해결할 수 있는지 설명해주세요.
Range-based 샤딩은 ID나 날짜 범위로 분할하여 범위 쿼리에 유리하지만 데이터 편중(hotspot) 문제가 발생할 수 있고, Hash-based는 균등 분산이 가능하나 범위 쿼리가 어렵고 샤드 추가 시 리샤딩이 복잡합니다. Directory-based는 유연한 매핑이 가능하지만 디렉토리 서버가 단일 장애점이 될 수 있습니다. Cross-shard Query는 애플리케이션 레벨에서 병렬로 각 샤드를 조회 후 결과를 병합하거나, 자주 조회되는 데이터는 별도의 집계 테이블이나 검색 엔진(Elasticsearch)을 활용합니다. 분산 트랜잭션은 2PC보다는 Saga 패턴이나 이벤트 소싱으로 최종 일관성(Eventual Consistency)을 보장하는 방식으로 설계하며, 보상 트랜잭션(Compensating Transaction)을 통해 롤백을 처리합니다.
- • Range-based는 범위 쿼리 유리, Hash-based는 균등 분산, Directory-based는 유연성 제공
- • Cross-shard Query는 애플리케이션 레벨 병합 또는 별도 집계 시스템 활용
- • 분산 트랜잭션은 Saga 패턴과 보상 트랜잭션으로 최종 일관성 보장
- • 샤딩 키 선택이 가장 중요하며, 비즈니스 쿼리 패턴 분석 필수
실제 서비스에서 사용자 수 증가로 샤드를 추가해야 할 때, 서비스 중단 없이 리샤딩을 수행하는 전략과 PHP 애플리케이션에서의 구현 방법을 설명해주세요.
Q. PHP의 Garbage Collection 메커니즘(Reference Counting과 Cycle Collection)을 설명하고, 순환 참조(Circular Reference)가 메모리 누수를 일으키는 원리와 PHP 5.3 이후 도입된 해결 방법을 설명해주세요. 또한 대용량 데이터 처리 시 GC 튜닝 방법을 포함해주세요.
PHP는 기본적으로 Reference Counting을 사용하여 변수의 참조 횟수가 0이 되면 즉시 메모리를 해제합니다. 그러나 객체 A가 B를 참조하고 B가 다시 A를 참조하는 순환 참조 상황에서는 외부 참조가 사라져도 서로를 참조하여 refcount가 0이 되지 않아 메모리 누수가 발생합니다. PHP 5.3부터 도입된 Cycle Collector는 가능한 순환 참조 루트를 추적하고, 버퍼가 차면 Mark-and-Sweep 알고리즘으로 실제 순환 참조를 탐지하여 해제합니다. 대용량 데이터 처리 시에는 gc_disable()로 GC를 비활성화하고 처리 후 gc_collect_cycles()로 수동 실행하거나, gc_mem_caches()로 캐시된 메모리를 해제하고, 배치 처리 시 unset()으로 명시적으로 변수를 해제하는 것이 효과적입니다.
- • Reference Counting은 즉시 메모리 해제하지만 순환 참조는 처리 불가
- • Cycle Collector는 버퍼 기반 Mark-and-Sweep으로 순환 참조 탐지 및 해제
- • 대용량 처리 시 GC 비활성화 후 수동 실행으로 성능 개선 가능
- • 명시적 unset()과 gc_mem_caches() 활용으로 메모리 관리 최적화
PHP 8.0에서 개선된 GC 성능과 WeakMap, WeakReference의 도입이 순환 참조 문제 해결에 어떤 영향을 주는지 설명해주세요.
Q. 마이크로서비스 아키텍처에서 API Gateway 패턴의 역할과 책임을 설명하고, Backend for Frontend(BFF) 패턴과의 차이점을 설명해주세요. 또한 PHP로 API Gateway를 구현할 때 고려해야 할 성능 이슈와 대안을 제시해주세요.
API Gateway는 클라이언트와 마이크로서비스 사이의 단일 진입점으로 라우팅, 인증/인가, 요청 집계, 프로토콜 변환, Rate Limiting 등을 담당합니다. BFF 패턴은 클라이언트 유형(Web, Mobile, IoT)별로 최적화된 별도의 Gateway를 두어 각 클라이언트의 요구사항에 맞는 API를 제공하는 반면, API Gateway는 모든 클라이언트가 공유하는 단일 게이트웨이입니다. PHP로 API Gateway를 구현하면 요청당 프로세스 생성으로 인한 오버헤드와 동기 블로킹 I/O로 인한 성능 저하가 발생할 수 있어, 실무에서는 Kong, Traefik, AWS API Gateway 같은 전용 솔루션을 사용하고 PHP는 BFF 레이어나 비즈니스 로직 처리에 집중하는 것이 일반적입니다. 만약 PHP로 구현한다면 Swoole이나 RoadRunner로 상주 프로세스를 유지하고 비동기 HTTP 클라이언트로 백엔드 서비스를 호출해야 합니다.
- • API Gateway는 단일 진입점으로 공통 기능 제공, BFF는 클라이언트별 최적화
- • PHP-FPM의 요청 단위 실행 모델은 Gateway 패턴에 부적합
- • 전용 Gateway 솔루션 사용 권장, PHP는 BFF나 비즈니스 로직에 집중
- • PHP 사용 시 Swoole/RoadRunner로 상주 프로세스와 비동기 처리 필수
Service Mesh(Istio, Linkerd)가 도입되면 API Gateway의 역할이 어떻게 변화하며, 둘을 함께 사용할 때의 책임 분리 전략은 무엇인가요?
Q. OAuth 2.0의 주요 Grant Type(Authorization Code, Implicit, Client Credentials, Password)을 설명하고, JWT 기반 인증과 Session 기반 인증의 장단점을 비교해주세요. 또한 대규모 분산 시스템에서 Token Refresh 전략과 Token 탈취 시 대응 방안을 설명해주세요.
Authorization Code는 서버 사이드 앱에서 가장 안전한 방식으로 code 교환 후 token 발급, Implicit은 SPA용으로 간소화되었으나 보안상 deprecated, Client Credentials는 서버간 통신용, Password는 자사 앱에서만 제한적으로 사용됩니다. JWT는 stateless하여 서버 부하가 적고 분산 환경에 유리하지만 즉시 무효화가 어렵고, Session은 서버에서 즉시 제어 가능하지만 세션 저장소 관리와 확장성 이슈가 있습니다. Token Refresh는 Access Token은 짧은 만료(15분), Refresh Token은 긴 만료(2주)로 설정하고, Refresh Token은 데이터베이스에 저장하여 관리합니다. Token 탈취 대응으로는 Refresh Token Rotation(사용 시마다 새 토큰 발급), IP/User-Agent 검증, 의심 활동 감지 시 모든 토큰 무효화, Redis에 블랙리스트 관리 등을 구현합니다.
- • Authorization Code가 가장 안전하며 PKCE 확장으로 보안 강화 가능
- • JWT는 stateless 장점, Session은 즉시 제어 가능 장점으로 하이브리드 사용도 고려
- • Access Token 짧게, Refresh Token 길게 설정하고 DB 저장으로 관리
- • Token Rotation, IP 검증, 블랙리스트로 탈취 대응 및 이상 활동 모니터링 필수
OpenID Connect(OIDC)가 OAuth 2.0에 추가하는 기능과, PHP에서 다중 Identity Provider(Google, Facebook, 자체 인증)를 통합 관리하는 아키텍처를 설계한다면 어떻게 구현하시겠습니까?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!