- 멀티모듈이란 무엇이고, 하나의 프로젝트를 여러 모듈로 구성했을 때 얻을 수 있는 장점은 무엇인가요
- Redis와 같은 캐시 시스템을 도입하는 이유는 무엇인가요? 캐시를 사용했을 때 얻을 수 있는 장점과 발생할 수 있는 문제점에 대해 설명해주세요.
- Scale-up과 Scale-out의 차이점은 무엇인가요? 각각의 장단점에 대해 설명해주세요.
- 특정 사용자가 짧은 시간 동안 API를 과도하게 호출하여 서버에 부하를 주고 있습니다. 이를 제한하기 위해 어떤 방법을 사용할 수 있을까요?
- 이미지나 동영상과 같은 정적 콘텐츠 요청이 증가하면서 서버의 트래픽과 응답 시간이 증가하고 있습니다. 이를 개선하기 위해 어떤 방법을 사용할 수 있을까요?
- 동기 통신과 비동기 통신의 차이점은 무엇인가요? 각각 어떤 상황에서 사용하는 것이 적절한가요?
- 데이터베이스 Replication이란 무엇인가요? Replication을 사용하는 이유와 장단점에 대해 설명해주세요.
- 로드 밸런서(Load Balancer)란 무엇인가요? 대표적인 로드 밸런싱 방식에 대해 설명해주세요.
- Web Server와 WAS에 대해 설명해주세요.
- 본인이 진행한 프로젝트의 전체 아키텍처에 대해 설명해주세요.
- 도커를 사용해서 배포를 진행하셨는데 도커를 사용하신 이유는 무엇인가요?
2. Redis와 같은 캐시 시스템을 도입하는 이유는 무엇인가요? 캐시의 장점과 문제점은 무엇인가요?
자주 조회되지만 자주 바뀌지 않는 데이터를 빠르게 제공하고, DB나 외부 API의 반복 작업을 줄이기 위해 캐시를 사용합니다. Redis를 활용하면 여러 서버가 같은 캐시를 공유할 수 있어 조회 지연과 원본 시스템의 부하를 줄일 수 있습니다.
흔한 방식인 Cache-Aside에서는 캐시를 먼저 조회하고, 값이 없으면 원본에서 읽어 캐시에 저장합니다. 대신 원본 데이터가 바뀐 뒤 캐시가 갱신되기 전까지 오래된 값이 보일 수 있으므로 TTL과 쓰기 시 무효화 정책을 정해야 합니다. 인기 데이터의 TTL이 동시에 만료되면 요청이 원본에 몰릴 수 있고, Redis 장애나 메모리 부족에도 대비해야 합니다. 따라서 캐시가 없어도 원본 조회로 기능을 유지할지, 어떤 데이터에 얼마 동안의 불일치를 허용할지를 먼저 정하겠습니다.
원본 데이터가 변경되면 캐시를 어떻게 갱신하거나 무효화하나요?
쓰기가 성공한 뒤 해당 키를 삭제하거나 새 값으로 갱신합니다. 삭제 방식은 다음 조회 때 원본에서 다시 채워 단순하지만, 쓰기와 무효화가 실패하거나 순서가 엇갈리면 오래된 값이 남을 수 있습니다. TTL을 보조 수단으로 두고, 강한 일관성이 필요한 조회는 캐시를 우회합니다.
인기 키의 캐시가 만료되어 요청이 한꺼번에 DB로 몰리면 어떻게 대응하나요?
같은 키에 대해 한 요청만 원본을 조회하도록 잠금이나 단일 실행을 적용하고, 나머지는 잠시 기다리거나 허용되는 경우 이전 값을 제공할 수 있습니다. TTL에 작은 무작위 값을 더해 여러 키가 동시에 만료되는 것도 줄입니다.
Redis가 장애를 일으켰을 때 서비스는 어떻게 동작해야 하나요?
캐시가 없어도 가능한 조회는 타임아웃 후 원본으로 우회하되, 원본이 갑자기 과부하되지 않도록 요청량을 제한합니다. 캐시가 세션이나 락처럼 필수 상태를 맡는다면 단순 우회가 불가능하므로 복제·장애 조치와 기능별 실패 정책을 따로 설계해야 합니다.
3. Scale-up과 Scale-out의 차이점과 장단점은 무엇인가요?
Scale-up은 서버 한 대의 CPU·메모리 같은 자원을 늘리는 것이고, Scale-out은 서버 대수를 늘려 요청을 분산하는 것입니다. Scale-up은 애플리케이션 변경이 적고 운영이 단순하지만, 장비의 성능 한계가 있고 한 대의 장애에 취약합니다. Scale-out은 처리량과 가용성을 높일 수 있고 필요한 만큼 단계적으로 증설할 수 있지만, 로드 밸런싱과 배포·모니터링이 복잡해집니다. 특히 여러 서버가 요청을 처리하므로 세션을 서버 메모리에만 두지 않는 등 상태 공유 문제를 해결해야 합니다. 병목이 DB에 있다면 애플리케이션 서버만 늘려서는 효과가 제한적이므로, 먼저 병목 지표를 확인하고 증설 대상을 결정하겠습니다.
서버를 늘리기 전에 어느 계층이 병목인지 어떻게 확인하나요?
요청량과 응답 시간의 평균·상위 백분위, 오류율을 먼저 보고 애플리케이션의 CPU·메모리·스레드 사용량, DB 쿼리 시간과 커넥션 풀 대기, 외부 API 지연을 함께 확인합니다. 부하 테스트나 추적 정보를 통해 시간이 실제로 쓰이는 구간을 찾은 뒤 증설 대상을 정합니다.
Scale-out 환경에서 사용자 세션이나 서버 내부 상태는 어떻게 관리하나요?
서버별 메모리에만 세션을 두면 다음 요청이 다른 서버로 갈 때 상태를 찾지 못할 수 있습니다. 세션을 Redis와 같은 공유 저장소에 두거나 인증 방식을 재설계하고, 업로드 파일과 작업 상태 같은 데이터도 서버 인스턴스의 로컬 저장소에만 의존하지 않도록 합니다.
애플리케이션 서버를 늘렸는데 응답 시간이 개선되지 않는다면 무엇을 점검하나요?
DB·외부 API·공유 락처럼 모든 서버가 함께 쓰는 자원이 병목인지 확인합니다. 로드 밸런서가 요청을 고르게 보내는지, 커넥션 풀이 과도하게 커져 DB를 압박하는지도 살펴야 합니다. 서버 대수만 늘린다고 전체 처리 경로의 병목이 사라지지는 않습니다.
4. 특정 사용자가 API를 과도하게 호출할 때 어떻게 제한하나요?
답변 예시: 사용자별로 일정 시간 동안 허용할 요청 수를 정하는 Rate Limiting을 적용하겠습니다. 인증된 사용자는 사용자 ID, 비인증 요청은 IP나 API 키 등을 기준으로 제한할 수 있지만, IP만 사용하면 NAT 뒤의 여러 사용자가 함께 제한될 수 있어 정책을 구분해야 합니다. 짧은 순간의 요청 폭증을 어느 정도 허용하면서 평균 호출량을 제한하려면 토큰 버킷 방식을 사용할 수 있습니다. 서버가 여러 대라면 각 서버의 메모리에서 따로 제한하지 않고 Redis 같은 공유 저장소에서 토큰 차감을 원자적으로 처리해야 우회가 어렵습니다. 한도를 넘으면 HTTP 429 Too Many Requests와 Retry-After로 재시도 시점을 알려 주고, 사용자·API별 한도와 차단 현황을 모니터링하겠습니다.
IP 기준으로 제한하면 어떤 정상 사용자가 영향을 받을 수 있나요?
회사·학교·통신사 NAT 뒤의 여러 사용자가 같은 공인 IP를 공유할 수 있습니다. 이들을 한 사용자로 취급하면 정상 요청까지 차단되므로, 로그인 사용자는 계정이나 API 키를 우선 기준으로 삼고 비인증 요청은 IP 기준의 한도를 별도로 조정합니다.
여러 서버에서 동시에 요청이 들어와도 제한 횟수를 정확히 지키려면 어떻게 구현하나요?
각 서버의 로컬 카운터 대신 공유 저장소에서 검사와 차감을 하나의 원자적 연산으로 수행합니다. 예를 들어 Redis Lua 스크립트로 토큰 버킷의 남은 토큰과 갱신 시각을 함께 처리하면 동시 요청의 경쟁을 줄일 수 있습니다.
토큰 버킷과 고정 윈도우 방식은 순간적인 요청 폭증을 어떻게 다르게 처리하나요?
고정 윈도우는 일정 구간마다 카운터가 초기화되어 구간 끝과 다음 구간 시작에 요청이 몰리면 짧은 시간에 거의 두 배의 요청을 허용할 수 있습니다. 토큰 버킷은 일정 속도로 토큰을 채우고 저장된 토큰만큼 버스트를 허용하므로 평균 속도와 최대 버스트 크기를 따로 제어할 수 있습니다.
5. 정적 콘텐츠 요청 증가로 트래픽과 응답 시간이 늘면 어떻게 개선하나요?
답변 예시: 이미지와 동영상은 애플리케이션 서버에서 매번 전달하기보다 오브젝트 스토리지에 저장하고 CDN을 통해 제공하겠습니다. CDN의 엣지 서버가 사용자와 가까운 곳에서 콘텐츠를 반환하면 원본 서버의 트래픽과 전송 지연을 줄일 수 있습니다. 변경되지 않는 파일은 파일명에 버전이나 해시를 넣고 긴 Cache-Control 유효 기간을 설정해 브라우저와 CDN이 재사용하게 합니다. 이미지 크기·포맷을 최적화하고 동영상은 필요에 따라 적응형 스트리밍을 사용하면 전송량도 줄일 수 있습니다. 갱신되는 파일은 URL 버전 변경이나 CDN 무효화 전략이 필요하고, 비공개 콘텐츠라면 서명 URL 등으로 접근을 제어해야 합니다.
CDN에 캐시된 이미지를 교체하거나 삭제해야 할 때 어떻게 반영하나요?
새 파일에 버전이나 해시가 포함된 URL을 부여하면 브라우저와 CDN이 새 콘텐츠로 요청합니다. 같은 URL을 유지해야 한다면 CDN 무효화를 요청하고, 브라우저 캐시의 만료 정책도 확인해야 합니다. 삭제가 시급한 파일은 원본 접근까지 차단해야 합니다.
공개하면 안 되는 파일을 CDN으로 전달할 때 접근 권한은 어떻게 제어하나요?
원본 스토리지를 비공개로 두고 CDN만 원본에 접근하게 합니다. 사용자에게는 권한 확인 후 짧은 만료 시간의 서명 URL 또는 서명 쿠키를 발급할 수 있습니다. 캐시 키와 만료 정책이 사용자별 접근 권한을 무시하지 않는지도 확인해야 합니다.
CDN을 도입한 뒤 성능 개선을 어떤 지표로 확인하나요?
CDN 캐시 적중률, 원본으로 향하는 요청 수와 전송량, 사용자 위치별 응답 시간, 이미지·동영상 로딩 지표를 전후 비교합니다. 캐시 적중률만 높아도 파일 크기가 크거나 사용자와 엣지 사이가 느리면 체감 성능은 기대보다 작을 수 있습니다.
6. 동기 통신과 비동기 통신의 차이점과 적절한 사용 상황은 무엇인가요?
답변 예시: 동기 통신은 요청한 쪽이 상대의 처리 결과를 받아야 다음 흐름을 진행하는 방식이고, 비동기 통신은 요청을 전달한 뒤 결과를 기다리는 동안 다른 일을 진행할 수 있는 방식입니다. 예를 들어 로그인 성공 여부처럼 즉시 결과가 필요한 작업은 동기 API 호출이 자연스럽고, 주문 완료 후 이메일 발송처럼 본 처리와 분리할 수 있는 작업은 메세지 큐를 통한 비동기 처리에 적합합니다. 비동기는 호출자의 대기 시간을 줄이고 순간적인 작업량을 큐에 쌓아 완충할 수 있지만, 처리 완료가 늦어질 수 있고 실패 재시도·중복 처리·순서 보장이 어려워집니다. 그래서 작업 상태를 추적하고 소비자가 중복 메시지를 안전하게 처리하도록 설계해야 합니다. 동기·비동기는 완료 결과를 다루는 방식이며, 스레드가 대기하는지 나타내는 블로킹·논블로킹과는 구분합니다.
메시지 큐에 작업을 넣은 뒤 소비자가 실패하면 어떻게 재처리하나요?
처리가 성공한 뒤에만 메시지를 확인 처리하고, 실패하면 제한된 횟수와 간격으로 재시도합니다. 계속 실패하는 메시지는 별도 실패 큐에 보내 원인을 확인하고 재처리합니다. 무한 재시도가 다른 메시지의 처리를 막지 않도록 해야 합니다.
같은 메시지가 두 번 전달되어도 결과가 중복되지 않게 하려면 어떻게 하나요?
메시지에 고유한 작업 ID를 넣고 소비자가 이미 처리한 ID인지 확인합니다. DB의 고유 제약이나 상태 전이 조건을 사용해 결과 기록과 중복 방지를 함께 처리할 수 있습니다. 메시지 전달은 중복될 수 있다고 가정하고, 업무 결과가 멱등하도록 만드는 것이 핵심입니다.
비동기 처리 결과를 사용자에게 알려 줘야 한다면 어떤 방법을 사용하나요?
요청 시 작업 ID를 반환하고 상태 조회 API를 제공할 수 있습니다. 더 빠른 알림이 필요하면 SSE나 WebSocket, 푸시 알림을 사용할 수 있습니다. 알림 연결이 끊겨도 최종 상태를 다시 조회할 수 있도록 상태를 영속적으로 기록합니다.
7. 데이터베이스 Replication이란 무엇이며, 왜 사용하나요? 장단점은 무엇인가요?
두 개 이상의 DBMS 이용하여 Master/Slave (수직적)구조를 활용하여 DB의 부하를 분산 시키는 기술 입니다.
읽기 요청을 Replica로 분산해 원본의 조회 부하를 줄이고, 원본 장애 시 Replica를 승격해 복구 시간을 단축할 수 있습니다. 다만 일반적인 비동기 복제에서는 원본에 커밋된 변경이 Replica에 아직 반영되지 않을 수 있어, 저장 직후 Replica를 조회하면 이전 값이 보일 수 있습니다. 즉시 최신 값이 필요한 조회는 원본으로 보내거나 복제 적용을 기다리는 정책이 필요합니다. 장애 조치 시에는 최신 Replica를 선택하고 이전 원본의 쓰기를 차단해야 하며, 복제 지연과 오류를 모니터링해야 합니다. 잘못된 삭제도 복제되므로 Replication은 별도 백업을 대체하지 않습니다.
사용자가 저장한 직후 이전 값이 조회되는 문제를 어떻게 해결하나요?
저장 직후처럼 최신 값이 필수인 요청은 원본 DB로 라우팅합니다. 더 엄격한 보장이 필요하면 해당 변경이 Replica에 적용될 때까지 기다릴 수도 있지만 조회 지연이 늘어납니다. 어떤 화면과 API에 Read-After-Write 일관성이 필요한지 먼저 구분해야 합니다.
원본 DB 장애 시 Replica를 승격할 때 데이터 손실과 이중 쓰기를 어떻게 방지하나요?
복제 적용 위치를 확인해 가능한 한 최신 Replica를 선택하되, 비동기 복제에서 아직 전달되지 않은 쓰기는 잃을 수 있음을 인정해야 합니다. 승격 전 기존 원본이 더 이상 쓰기를 받지 못하도록 차단하고 애플리케이션의 접속 경로를 새 원본으로 전환합니다. 손실 허용 범위가 작다면 복제 방식과 복구 절차를 별도로 설계해야 합니다.
Replica가 있는데도 별도의 백업이 필요한 이유는 무엇인가요?
잘못된 DELETE나 데이터 손상도 Replica에 복제되기 때문입니다. 백업은 복제와 독립적으로 보관하고, 필요한 시점으로 복구할 수 있도록 전체·증분 백업과 로그 기반 복구 절차를 마련해야 합니다.
8. 로드 밸런서란 무엇이며, 대표적인 분산 방식은 무엇인가요?
로드 밸런서는 여러 서버 앞에서 요청을 건강한 서버로 분산하는 장치 또는 소프트웨어입니다.
단일 서버의 과부하를 줄이고, 서버 추가와 장애 시 우회를 가능하게 합니다. 대표적으로 요청을 순서대로 보내는 라운드 로빈, 연결 수가 적은 서버를 고르는 최소 연결, 서버 성능 차이를 반영하는 가중치 방식이 있습니다. 요청별 처리 시간이 다르다면 단순 라운드 로빈보다 최소 연결 방식이 유리할 수 있지만, 연결 수가 실제 CPU 부하와 항상 같지는 않으므로 서비스 특성에 맞춰 선택해야 합니다. L4는 주로 IP·포트 같은 전송 계층 정보를, L7은 HTTP 경로·헤더 등을 보고 분산할 수 있습니다. 실제 운영에서는 분산 알고리즘과 함께 헬스 체크, 타임아웃, 세션 처리 정책이 중요합니다.
L4 로드 밸런서와 L7 로드 밸런서는 어떤 정보를 기준으로 요청을 분산하나요?
L4는 주로 IP·포트와 TCP/UDP 연결 정보를 보고 전달합니다. L7은 HTTP를 해석해 호스트, 경로, 헤더 등을 기준으로 라우팅할 수 있어
/api와/images를 서로 다른 서버군으로 보낼 수 있습니다. 세부 기능은 제품과 설정에 따라 달라집니다.
한 서버가 응답하지 않을 때 로드 밸런서는 어떻게 이를 감지하고 요청을 우회하나요?
정기적인 헬스 체크나 연결 실패를 통해 비정상 인스턴스를 대상에서 제외합니다. 복구된 서버는 정상 확인 후 다시 추가하며, 실패 판정 기준과 검사 간격을 너무 민감하거나 느리지 않게 조정해야 합니다. 진행 중이던 요청의 재시도는 작업의 멱등성도 고려해야 합니다.
세션을 서버 메모리에 저장하는 서비스에서 요청을 여러 서버로 분산하면 어떤 문제가 생기나요?
로그인 요청을 처리한 서버와 다음 요청을 처리한 서버가 다르면 다음 서버가 세션을 찾지 못할 수 있습니다. 스티키 세션으로 같은 서버에 보내는 방법도 있지만 장애와 증설에 약하므로, 공유 세션 저장소나 서버 간 상태 의존을 줄이는 설계가 일반적으로 더 안정적입니다.
9. Web Server와 WAS에 대해 설명해주세요.
웹 서버는 HTTP 요청을 받아 정적 파일을 제공하거나 요청을 뒤쪽 애플리케이션으로 전달하는 역할을 합니다.
WAS는 애플리케이션 코드를 실행해 요청마다 달라지는 응답을 만들며, DB 조회와 비즈니스 로직 처리 등을 담당합니다.
예를 들어 Nginx가 TLS 종료와 정적 파일 제공, 리버스 프록시 역할을 하고, Spring Boot의 내장 Tomcat과 애플리케이션이 API 요청을 처리할 수 있습니다. 둘을 함께 사용하면 정적 콘텐츠 전송과 동적 요청 처리를 분리하고, 웹 서버에서 여러 애플리케이션 인스턴스로 요청을 분산할 수 있습니다. 다만 경계가 절대적인 것은 아닙니다. WAS도 정적 파일을 제공할 수 있고, 웹 서버도 프록시·캐싱 등 다양한 기능을 수행합니다.
Nginx를 Spring Boot 애플리케이션 앞에 두면 어떤 역할을 맡길 수 있나요?
TLS 종료, 정적 파일 제공, 리버스 프록시, 요청 크기 제한, 타임아웃 설정 등을 맡길 수 있습니다. 여러 Spring Boot 인스턴스가 있다면 요청 분산도 가능합니다. 다만 프록시를 한 대만 운영하면 그 자체가 단일 장애 지점이 될 수 있습니다.
웹 서버 없이 Spring Boot의 내장 Tomcat만으로 서비스를 운영할 수도 있나요?
가능합니다. 내장 Tomcat이 HTTP 요청을 직접 받고 Spring 애플리케이션이 동적 응답과 정적 리소스를 제공할 수 있습니다. 별도 웹 서버는 TLS 종료, 정적 파일 전송, 프록시·로드 밸런싱 등 운영상 필요가 있을 때 추가합니다.
리버스 프록시와 로드 밸런서는 어떤 관계인가요?
리버스 프록시는 클라이언트를 대신해 뒤쪽 서버에 요청을 전달하는 역할이고, 로드 밸런싱은 여러 서버 중 요청 대상을 고르는 기능입니다. 하나의 리버스 프록시가 로드 밸런서 역할까지 할 수 있지만, 모든 리버스 프록시가 반드시 요청을 여러 서버에 분산하는 것은 아닙니다.