PHP 미드레벨 프레임워크 기술면접
새 면접Q. Laravel의 Service Container에서 bind()와 singleton()의 차이점을 설명하고, 각각 어떤 상황에서 사용하는 것이 적절한지 실무 예시와 함께 설명해주세요. 또한 contextual binding은 언제 사용하나요?
bind()는 매번 새로운 인스턴스를 생성하는 반면, singleton()은 첫 호출 시 생성된 인스턴스를 재사용합니다. bind()는 요청마다 상태가 달라지는 서비스(예: 현재 사용자 컨텍스트를 담는 객체)에 적합하고, singleton()은 무상태 서비스나 공유 자원(예: 로거, 캐시 관리자)에 적합합니다. Contextual binding은 같은 인터페이스를 다른 클래스에서 다른 구현체로 주입받아야 할 때 사용합니다. 예를 들어 ImageController에서는 FileSystemStorage를, VideoController에서는 S3Storage를 주입받도록 설정할 수 있습니다.
- • bind()는 매번 새 인스턴스 생성, singleton()은 인스턴스 재사용
- • 상태를 가진 객체는 bind(), 무상태 공유 서비스는 singleton() 사용
- • Contextual binding으로 컨텍스트별 다른 구현체 주입 가능
Laravel에서 Service Provider의 register()와 boot() 메서드의 차이점과 각각에서 수행해야 하는 작업은 무엇인가요?
Q. Symfony의 HTTP Kernel 컴포넌트가 요청을 처리하는 전체 라이프사이클을 설명하고, 각 단계에서 발생하는 이벤트(KernelEvents)와 미들웨어가 어떻게 작동하는지 설명해주세요. 특히 서브 요청(sub-request)의 개념과 사용 사례도 포함해주세요.
Symfony HTTP Kernel은 요청을 받아 kernel.request 이벤트를 발생시키고, 라우터가 컨트롤러를 결정하면 kernel.controller 이벤트가 발생합니다. 컨트롤러 실행 후 kernel.view 이벤트(응답이 없을 경우), 그리고 kernel.response 이벤트를 거쳐 최종 응답을 반환하고 kernel.terminate 이벤트로 종료됩니다. 예외 발생 시 kernel.exception 이벤트가 처리합니다. 서브 요청은 메인 요청 내에서 내부적으로 또 다른 요청을 처리하는 것으로, ESI(Edge Side Includes)나 컨트롤러 내에서 다른 컨트롤러를 렌더링할 때 사용됩니다. 각 이벤트 리스너는 우선순위에 따라 실행되며, 미들웨어 패턴으로 요청/응답을 가로채 수정할 수 있습니다.
- • 요청 처리 순서: kernel.request → 라우팅 → kernel.controller → 실행 → kernel.response → kernel.terminate
- • 각 단계마다 이벤트 리스너를 통해 요청/응답 조작 가능
- • 서브 요청은 메인 요청 내에서 독립적인 요청 처리 수행, ESI나 내부 렌더링에 활용
Symfony의 EventDispatcher가 Laravel의 Event 시스템과 어떻게 다르며, 각각의 장단점은 무엇인가요?
Q. Laravel Eloquent에서 Eager Loading과 Lazy Loading의 차이를 설명하고, Lazy Eager Loading(load 메서드)은 언제 사용하나요? 또한 관계가 깊게 중첩된 경우(예: 게시글 → 댓글 → 작성자 → 프로필) 최적화 전략을 제시해주세요.
Lazy Loading은 관계 데이터를 실제 접근할 때 쿼리를 실행하여 N+1 문제를 발생시키고, Eager Loading(with 메서드)은 초기 쿼리 시점에 조인으로 미리 로드하여 쿼리 수를 줄입니다. Lazy Eager Loading(load 메서드)은 이미 조회된 모델 컬렉션에 대해 나중에 관계를 로드할 때 사용하며, 조건부로 관계 로드가 필요한 경우 유용합니다. 깊은 중첩 관계는 점 표기법(with('comments.author.profile'))으로 한 번에 로드하고, 필요한 컬럼만 선택(select)하며, 관계별 조건(wherePivot, whereHas)을 활용해 불필요한 데이터 로드를 방지합니다.
- • Lazy Loading은 N+1 문제 유발, Eager Loading으로 쿼리 최적화
- • Lazy Eager Loading은 이미 로드된 컬렉션에 조건부로 관계 추가 시 사용
- • 중첩 관계는 점 표기법과 컬럼 선택으로 최적화
Eloquent의 HasManyThrough와 MorphMany 관계의 차이점과 각각의 사용 사례를 설명해주세요.
Q. Laravel과 Symfony에서 미들웨어(Middleware)의 실행 순서를 제어하는 방법을 설명하고, 전역 미들웨어, 라우트 미들웨어, 미들웨어 그룹의 차이점과 각각의 적절한 사용 사례를 제시해주세요. 또한 미들웨어에서 요청을 조기에 종료(early return)할 때의 주의사항은 무엇인가요?
Laravel에서는 Kernel 클래스의 $middleware 배열 순서로 전역 미들웨어가 실행되고, $middlewarePriority로 우선순위를 지정할 수 있습니다. 전역 미들웨어는 모든 요청에 적용(예: CORS, 세션), 라우트 미들웨어는 특정 라우트에만 적용(예: 인증, 권한), 미들웨어 그룹은 관련 미들웨어를 묶어 재사용합니다. Symfony는 이벤트 리스너의 우선순위로 제어합니다. 미들웨어에서 조기 종료 시 반드시 Response 객체를 반환해야 하며, 이후 미들웨어나 terminate 메서드가 실행되지 않으므로 로깅이나 정리 작업이 누락될 수 있음을 고려해야 합니다.
- • 전역 미들웨어는 모든 요청, 라우트 미들웨어는 특정 라우트, 그룹은 재사용 가능한 묶음
- • 실행 순서는 배열 순서나 우선순위로 제어
- • 조기 종료 시 Response 반환 필수, terminate 단계 미실행 주의
미들웨어에서 예외가 발생했을 때 프레임워크가 어떻게 처리하며, 전역 예외 핸들러와의 상호작용은 어떻게 이루어지나요?
Q. Laravel의 Queue 시스템에서 Job의 실패 처리 메커니즘을 설명하고, failed(), retryUntil(), backoff() 메서드의 역할과 차이점을 설명해주세요. 또한 Horizon을 사용한 큐 모니터링과 동적 워커 스케일링 전략, 그리고 Job Batching을 활용한 대량 작업 처리 방법을 제시해주세요.
Laravel Job은 tries 속성만큼 재시도하며 실패 시 failed() 메서드가 호출되어 실패 처리 로직을 실행합니다. retryUntil()은 특정 시간까지만 재시도하도록 제한하고, backoff()는 재시도 간격을 지수적으로 증가시켜 외부 서비스 과부하를 방지합니다. Horizon은 Redis 기반 큐 모니터링 대시보드로, 큐별 처리량과 실패율을 실시간으로 확인하고 워커 수를 동적으로 조정합니다. Job Batching은 여러 Job을 하나의 배치로 묶어 전체 완료 여부를 추적하고, then(), catch(), finally() 콜백으로 배치 단위 후처리를 수행할 수 있어 대량 이메일 발송이나 데이터 마이그레이션에 유용합니다.
- • failed()는 최종 실패 시 처리, retryUntil()은 시간 제한, backoff()는 재시도 간격 조절
- • Horizon으로 큐 모니터링 및 워커 동적 스케일링 가능
- • Job Batching으로 대량 작업을 묶어 진행 상황 추적 및 배치 단위 후처리
Laravel에서 Job 체이닝(Chain)과 Job Batching의 차이점은 무엇이며, 각각 어떤 상황에서 사용하는 것이 적절한가요?
아직 댓글이 없습니다. 첫 번째 댓글을 남겨보세요!