PHP 미드레벨 기술면접
새 면접Q. PHP에서 세션(Session)의 동작 원리를 설명하고, 대규모 트래픽 환경에서 세션 스토리지를 Database나 Redis로 변경할 때의 이점과 구현 시 고려사항을 설명해주세요. 특히 세션 잠금(Session Locking) 문제와 해결 방법도 포함해주세요.
PHP 세션은 기본적으로 PHPSESSID 쿠키로 식별자를 클라이언트에 전달하고, 서버는 session.save_path에 지정된 경로에 파일로 세션 데이터를 저장합니다. 대규모 환경에서는 파일 기반 세션이 I/O 병목과 서버 간 세션 공유 문제를 일으키므로 Redis나 Database를 사용하는 것이 좋습니다. Redis는 빠른 읽기/쓰기와 TTL 자동 관리가 가능하며, SessionHandlerInterface를 구현하여 커스텀 핸들러를 만들 수 있습니다. 세션 잠금은 session_start() 호출 시 해당 세션 파일에 배타적 락이 걸려 동일 세션의 동시 요청이 순차 처리되는 문제로, session_write_close()를 조기에 호출하거나 읽기 전용 세션(session_start(['read_and_close' => true]))을 사용하여 해결할 수 있습니다.
- • 기본 세션은 파일 기반으로 동작하며 PHPSESSID 쿠키로 식별
- • 대규모 환경에서는 Redis/Database 세션 스토리지로 전환하여 공유와 성능 개선
- • SessionHandlerInterface 구현으로 커스텀 세션 핸들러 작성 가능
- • 세션 잠금 문제는 session_write_close() 조기 호출이나 읽기 전용 모드로 해결
JWT 토큰 기반 인증과 세션 기반 인증을 비교했을 때, 각각의 장단점과 적합한 사용 시나리오는 무엇인가요?
Q. PHP에서 Strategy 패턴을 활용하여 결제 시스템(신용카드, 계좌이체, 페이팔 등)을 설계한다고 할 때, 구조와 이점을 설명하고, Factory 패턴과 함께 사용하는 방법을 제시해주세요.
Strategy 패턴은 알고리즘군을 정의하고 각각을 캡슐화하여 교환 가능하게 만드는 패턴입니다. PaymentStrategyInterface를 정의하고 CreditCardPayment, BankTransferPayment, PaypalPayment 등의 구체 클래스가 이를 구현하도록 합니다. PaymentContext 클래스는 주입받은 전략 객체의 pay() 메서드를 호출하여 결제를 처리하며, 런타임에 전략을 교체할 수 있습니다. Factory 패턴(PaymentStrategyFactory)을 함께 사용하면 결제 타입 문자열을 받아 적절한 전략 객체를 생성하여 반환하므로, 클라이언트 코드가 구체 클래스에 의존하지 않고 확장에 열려있는 구조가 됩니다. 이는 새로운 결제 수단 추가 시 기존 코드 수정 없이 새 전략 클래스만 추가하면 되는 개방-폐쇄 원칙을 따릅니다.
- • Strategy 패턴으로 각 결제 수단을 독립적인 클래스로 캡슐화하여 교환 가능하게 구현
- • 공통 인터페이스(PaymentStrategyInterface)를 통해 다형성 활용
- • Factory 패턴과 결합하여 결제 타입에 따라 적절한 전략 객체 생성
- • 새로운 결제 수단 추가 시 기존 코드 수정 없이 확장 가능(OCP 준수)
Strategy 패턴과 State 패턴의 차이점은 무엇이며, 각각 어떤 상황에 적합한가요?
Q. PHP에서 데이터베이스 트랜잭션의 격리 수준(Isolation Level)이 성능과 데이터 일관성에 미치는 영향을 설명하고, READ COMMITTED와 REPEATABLE READ의 차이를 Phantom Read, Non-Repeatable Read 개념과 함께 설명해주세요. 실무에서 격리 수준을 선택하는 기준도 제시해주세요.
트랜잭션 격리 수준은 동시성과 일관성 사이의 트레이드오프를 조정하는 설정입니다. READ COMMITTED는 커밋된 데이터만 읽을 수 있어 Dirty Read는 방지하지만, 같은 트랜잭션 내에서 같은 쿼리를 두 번 실행했을 때 다른 트랜잭션의 커밋으로 인해 결과가 달라지는 Non-Repeatable Read가 발생할 수 있습니다. REPEATABLE READ는 트랜잭션 시작 시점의 스냅샷을 유지하여 Non-Repeatable Read를 방지하지만, 범위 쿼리에서 다른 트랜잭션이 새 행을 삽입하면 나타나는 Phantom Read가 발생할 수 있습니다(MySQL InnoDB는 Next-Key Lock으로 방지). 실무에서는 일반적인 웹 애플리케이션은 READ COMMITTED로 충분하며, 금융 거래나 재고 관리처럼 데이터 일관성이 중요한 경우 REPEATABLE READ나 SERIALIZABLE을 사용하되 성능 저하와 데드락 가능성을 고려해야 합니다.
- • READ COMMITTED는 커밋된 데이터만 읽지만 Non-Repeatable Read 발생 가능
- • REPEATABLE READ는 트랜잭션 스냅샷 유지로 일관된 읽기 보장하나 Phantom Read 가능
- • 격리 수준이 높을수록 일관성은 높아지지만 동시성과 성능은 저하
- • 비즈니스 요구사항에 따라 적절한 격리 수준 선택 필요
MySQL InnoDB의 MVCC(Multi-Version Concurrency Control) 메커니즘이 어떻게 동작하며, 이것이 트랜잭션 격리 수준 구현에 어떤 역할을 하나요?
Q. RESTful API를 설계할 때 버전 관리 전략(URI 버저닝, Header 버저닝 등)을 비교하고, 하위 호환성을 유지하면서 API를 점진적으로 개선하는 방법을 설명해주세요. 특히 Deprecation 정책과 클라이언트 마이그레이션 전략도 포함해주세요.
API 버전 관리는 URI 버저닝(/api/v1/users), Header 버저닝(Accept: application/vnd.api.v1+json), Query Parameter 방식(?version=1) 등이 있습니다. URI 버저닝은 명확하고 캐싱이 용이하며 가장 널리 사용되지만 URL이 복잡해지고, Header 버저닝은 RESTful 원칙에 더 부합하나 디버깅이 어렵습니다. 하위 호환성 유지를 위해서는 필드 추가는 허용하되 제거나 타입 변경은 새 버전에서 수행하고, 응답에 선택적 필드를 추가할 때는 클라이언트가 무시할 수 있도록 설계합니다. Deprecation 정책은 최소 6개월 전에 응답 헤더(Sunset, Deprecation)로 알리고, 문서에 마이그레이션 가이드를 제공하며, 구버전 사용량을 모니터링하여 충분히 감소한 후 종료합니다. 점진적 마이그레이션을 위해 API Gateway에서 라우팅 규칙을 조정하거나 Feature Flag를 활용할 수 있습니다.
- • URI 버저닝이 가장 명확하고 실용적이나, Header 버저닝은 RESTful 원칙에 더 부합
- • 하위 호환성 유지를 위해 필드 추가는 허용하되 제거/변경은 새 버전에서 수행
- • Deprecation 헤더와 충분한 공지 기간으로 클라이언트 마이그레이션 유도
- • 사용량 모니터링과 점진적 전환으로 안전한 버전 업그레이드
GraphQL을 도입하면 API 버전 관리 문제를 해결할 수 있다고 하는데, REST API 대비 어떤 장단점이 있나요?
Q. 동료가 작성한 PHP 코드에서 과도한 if-else 중첩과 중복 코드가 많아 가독성과 유지보수성이 떨어지는 상황입니다. 코드 리뷰 시 어떤 리팩토링 기법들을 제안하고, 각 기법이 코드 품질을 어떻게 개선하는지 설명해주세요.
과도한 if-else 중첩은 Early Return(Guard Clause) 패턴으로 예외 상황을 먼저 처리하여 중첩을 줄일 수 있습니다. 복잡한 조건문은 의미있는 이름의 메서드로 추출(Extract Method)하여 가독성을 높이고, 유사한 조건 분기는 Strategy 패턴이나 Polymorphism으로 대체할 수 있습니다. 중복 코드는 공통 로직을 별도 메서드나 클래스로 추출하고, 매직 넘버나 문자열은 상수로 정의하여 의미를 명확히 합니다. 긴 메서드는 단일 책임 원칙에 따라 작은 메서드들로 분리하고, 과도한 파라미터는 DTO나 Builder 패턴으로 개선합니다. 리팩토링 시에는 반드시 기존 테스트가 통과하는지 확인하고, 테스트가 없다면 먼저 작성한 후 리팩토링을 진행해야 안전합니다.
- • Early Return으로 중첩 깊이를 줄이고 메인 로직을 명확하게 표현
- • 복잡한 조건문은 메서드 추출이나 Strategy 패턴으로 개선
- • 중복 코드는 공통 로직 추출과 상수화로 제거
- • 리팩토링 전 테스트 작성으로 안전성 확보
SOLID 원칙 중 단일 책임 원칙(SRP)과 개방-폐쇄 원칙(OCP)을 PHP 코드 예시와 함께 설명해주실 수 있나요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!