프레임워크 비교
프레임워크 이름으로 승자를 정하지 말고, 병목과 팀의 운영 능력을 먼저 명시합니다.
1. 런타임과 동시성
한 줄 결론: I/O 대기와 CPU 작업을 분리하고, 각 런타임에서 공유 자원을 막는 코드가 무엇인지 설명할 수 있어야 합니다.
- Node.js: JavaScript 콜백은 이벤트 루프에서 실행되고 일부 파일·DNS·암호화 작업은 libuv Worker Pool을 사용합니다. 둘 중 하나를 오래 점유하면 다른 요청의 지연이 커집니다.
- NestJS: 동시성의 바닥은 Node.js와 같고, 모듈·가드·인터셉터 같은 구조가 추가됩니다. CPU 집약 작업은 워커나 별도 서비스로 경계를 둡니다.
- Spring: Spring MVC는 Servlet 기반 요청 처리 모델이며, 비동기·논블로킹 체인이 실제 요구일 때 WebFlux를 선택합니다. 블로킹 저장소를 그대로 쓰면 WebFlux의 이점이 제한됩니다.
- ASP.NET Core: 비동기 I/O 완료까지 스레드를 붙잡지 않고, 계속 작업은 ThreadPool에서 수행합니다. 동기 블로킹과 요청마다 무분별한
Task.Run은 피합니다.
시니어 면접 포인트: “동시 요청이 많다”와 “CPU 병렬 계산이 많다”를 구분하고, 이벤트 루프 지연·ThreadPool starvation·큐 길이·p95/p99 지연을 함께 관측한다고 답합니다.
2. 애플리케이션 구조와 DI
한 줄 결론: DI는 객체 생성을 숨기는 장치가 아니라 의존성 경계와 수명을 명시하는 설계 도구입니다.
- Node.js: 순수 런타임은 구조를 강제하지 않아 함수 조합, 팩터리, 외부 컨테이너를 팀이 선택합니다. 자유도만큼 합의와 테스트 규율이 필요합니다.
- NestJS: Module이 기능 경계를, Provider가 주입 대상을 표현합니다. 기본 singleton 외 request·transient scope는 비용과 전파 범위를 검토합니다.
- Spring: IoC 컨테이너가 Bean 생성과 연결을 맡습니다. 기본 singleton Bean에 요청 상태를 보관하지 않고, 프록시와 스코프 경계를 이해합니다.
- ASP.NET Core: 기본 컨테이너의 Singleton·Scoped·Transient DI 생명주기를 사용합니다. 요청 Scoped를 Singleton이 직접 캡처하지 않게 합니다.
시니어 면접 포인트: 프레임워크별 이름을 외우는 데서 끝내지 말고, 수명 불일치·숨은 서비스 로케이터·순환 의존성이 테스트 격리와 장애 범위에 미치는 영향을 설명합니다.
3. 데이터 접근
한 줄 결론: ORM은 반복 매핑을 줄이지만, 생성 SQL과 트랜잭션 경계를 이해해야 추상화 누수를 통제할 수 있습니다.
- Node.js: Prisma는 스키마·생성 클라이언트 중심, TypeORM은 엔티티·리포지터리 중심 선택지를 제공합니다. 둘 다 실제 쿼리와 인덱스를 확인합니다.
- NestJS: Prisma·TypeORM 등을 모듈과 Provider로 감싸 애플리케이션 계층과 격리하되, 과도한 범용 리포지터리로 쿼리 의도를 지우지 않습니다.
- Spring: JPA/Hibernate의 영속성 컨텍스트와 지연 로딩, 변경 감지를 이해하고 N+1과 트랜잭션 밖 접근을 점검합니다.
- ASP.NET Core: EF Core의 LINQ 번역·변경 추적·projection을 활용하되, 로그와 실행 계획으로 SQL 가시성을 유지합니다.
시니어 면접 포인트: “ORM 대 SQL” 이분법 대신 조회·명령 모델, 추적 필요 여부, 대량 쓰기, 인덱스, 잠금과 일관성 요구로 선택 근거를 제시합니다.
4. 성능 판단
한 줄 결론: 벤치마크 순위보다 실제 요청의 CPU·I/O·할당·직렬화 비중과 배포 조건을 재현하는 측정이 우선입니다.
- Node.js: 이벤트 루프 지연, Worker Pool 포화, 힙과 GC, 네이티브 애드온 비용을 프로파일링합니다.
- NestJS: Node 지표에 더해 DI scope, 파이프·가드·인터셉터, 직렬화 계층의 핫 패스를 측정합니다.
- Spring: JVM 워밍업·GC·스레드 풀·Servlet/WebFlux 선택과 콜드 스타트 조건을 함께 봅니다.
- ASP.NET Core: dotnet-counters·dotnet-trace·프로파일러로 할당, GC, ThreadPool, 예외, 직렬화 비용을 확인합니다.
시니어 면접 포인트: 동일 데이터·동일 외부 의존성·동일 컨테이너 제한에서 부하를 재현하고, 처리량과 꼬리 지연·오류율·비용을 함께 비교한다고 답합니다.
5. 테스트와 관측성
한 줄 결론: 테스트 가능성과 관측성은 부가 기능이 아니라 운영 중 가설을 빠르게 검증하는 설계 속성입니다.
- Node.js: 함수·모듈 경계를 작게 두고, 구조화 로그와 Event Loop·메모리 메트릭, 비동기 추적 문맥을 연결합니다.
- NestJS: TestingModule로 Provider를 교체하고, 가드·파이프·인터셉터는 단위 및 전 구간 테스트의 책임을 나눕니다.
- Spring: 단위 테스트와 슬라이스·통합 테스트를 목적별로 구분하며, Micrometer·프로파일러·추적 문맥을 활용합니다.
- ASP.NET Core: DI 대체와 TestServer/WebApplicationFactory 계열 격리를 사용하고, ILogger·Meter·Activity 기반 신호를 상관관계 ID로 잇습니다.
시니어 면접 포인트: 로그만 늘리지 말고 요청률·오류율·지연, 자원 포화, 프로파일 결과를 같은 배포 버전과 추적 ID로 연결하는 방식을 설명합니다.
6. 운영과 배포
한 줄 결론: 배포 단위의 크기보다 런타임 지원 정책, 종료 계약, 상태 점검, 복구 절차를 팀이 반복 실행할 수 있는지가 중요합니다.
- Node.js: LTS 런타임과 lockfile을 고정하고, SIGTERM 수신 후 새 요청 중단·진행 요청 종료·강제 종료 제한을 둡니다.
- NestJS: Node 운영 기준에 lifecycle hook과 어댑터 설정을 더하며, readiness에서 실제 제공 가능 상태만 노출합니다.
- Spring: JDK·프레임워크 조합, JVM 메모리 제한, graceful shutdown, Actuator 기반 상태 점검을 배포 계약에 포함합니다.
- ASP.NET Core: .NET 지원 버전, 컨테이너 메모리, Host 종료 토큰, Kestrel·프록시 제한, health check를 조율합니다.
시니어 면접 포인트: 네 프레임워크 모두 무상태 요청 계층은 수평 확장하기 쉽지만, 세션·락·인메모리 캐시·백그라운드 작업의 소유권을 외부화하거나 샤딩해야 한다고 짚습니다.
7. 모바일 게임 적합성
한 줄 결론: ASP.NET Core는 C# 역량을 활용하기 좋지만, Unity 코드 공유 자체를 목표로 삼기보다 서버 권한·배포 독립성·운영 경험을 우선합니다.
| 결정 축 | Node.js | NestJS | Spring | ASP.NET Core |
| 팀 역량·채용 | JavaScript 런타임·비동기 운영 역량 | TypeScript와 구조화된 서버 개발 경험 | Java/JVM 운영 인력과 성숙한 생태계 | C# 백엔드 역량과 .NET 운영 경험 |
| Unity 연계 | 언어 중립 계약 생성 | DTO 계약을 모듈 경계에 배치 | 언어 중립 계약 생성 | DTO·규칙 일부 공유 가능하나 클라이언트를 신뢰 경계 안에 두지 않음 |
| 실시간 경계 | I/O 게이트웨이와 CPU 작업 격리 | 게이트웨이·가드·인터셉터 구조 활용 | MVC 또는 WebFlux를 의존성 특성에 맞게 선택 | SignalR·소켓과 일반 API를 분리하고 상태 소유권 명시 |
| 비실시간 | 작은 서비스·운영 도구 구성 | 상점·운영 도구를 모듈화 | 복잡한 도메인·트랜잭션 경험 활용 | 계정·결제·우편·랭킹 API에 C# 생산성 활용 |
시니어 면접 포인트: 최종 선택은 기능 적합성뿐 아니라 온콜 경험, 관측 도구, 보안 패치, 채용 시장, 기존 데이터 계층과의 통합 비용을 가중치로 둔 결정 행렬로 제시합니다.
ASP.NET Core 심층 학습
1. Kestrel, Host, 리버스 프록시
개념
WebApplication/Generic Host는 DI·구성·로깅·애플리케이션 수명을 묶고, Kestrel은 HTTP 요청을 HttpContext로 노출합니다. Kestrel은 직접 공개할 수도 있고 IIS·Nginx 같은 리버스 프록시 뒤에 둘 수도 있습니다.
실무 함정
프록시의 원본 IP·스킴 전달을 신뢰 네트워크 없이 허용하거나, 프록시와 Kestrel의 본문 크기·타임아웃 제한을 다르게 두면 보안과 장애 분석이 흐려집니다. 종료 시 readiness를 먼저 내리고 Host 종료 토큰 안에서 진행 요청과 백그라운드 작업을 정리합니다.
게임 서버 적용
점검 배포에서는 새 로그인·매칭 요청을 차단하고, 재화 저장과 큐 메시지 확정처럼 소유 중인 작업에 명시적 종료 기한을 둡니다.
30초 답변
“Kestrel은 HTTP 서버, Host는 구성·DI·로깅·수명 관리자입니다. 프록시 경계를 명시하고 readiness와 graceful shutdown을 연결해 배포 중 손실을 줄입니다.”
2분 답변
프록시가 TLS 종료·라우팅·보호 기능을 맡을 수 있지만 애플리케이션도 전달 헤더 신뢰 범위와 요청 제한을 알아야 합니다. 종료 신호가 오면 트래픽 유입을 멈추고, 취소 토큰을 작업에 전달하며, 제한 시간 이후 재처리 가능한 상태로 남깁니다. 종료 시간과 강제 종료 건수를 배포 지표로 검증합니다.
2. 미들웨어 순서와 scoped 의존성
개념
미들웨어는 등록 순서로 요청을 통과하고 역순으로 응답을 통과합니다. 다음 구성 요소를 호출하지 않으면 단락됩니다. 전역 예외 처리는 앞쪽에, 인증은 인가보다 앞에 두고 라우팅 메타데이터가 필요한 구성 요소는 라우팅 이후에 둡니다.
실무 함정
일반 미들웨어 인스턴스는 앱 수명 동안 재사용될 수 있으므로 scoped 서비스를 생성자에 캡처하지 않습니다. 요청별 의존성은 InvokeAsync 매개변수로 받거나 factory 기반 미들웨어를 사용합니다.
public sealed class PlayerContextMiddleware(RequestDelegate next)
{
public async Task InvokeAsync(HttpContext context, IPlayerSession session)
{
await session.LoadAsync(context.RequestAborted);
await next(context);
}
}
게임 서버 적용
상관관계 ID → 예외 처리 → 인증 → 인가 → endpoint 순서를 문서화하고, 점검 단락 응답에도 동일한 오류 계약과 추적 ID를 제공합니다.
30초 답변
“순서가 동작입니다. 예외 처리는 바깥쪽, 인증은 인가 앞에 두며, scoped 의존성은 요청 시점에 해석해 captive dependency를 막습니다.”
2분 답변
각 미들웨어의 전제와 단락 조건을 표로 관리합니다. 인증 전 사용자 정보가 필요하거나 예외 처리 뒤에서 오류가 새는 순서 문제를 통합 테스트로 검증하고, 매 요청 새 scope의 서비스는 InvokeAsync 주입을 사용합니다.
3. DI 생명주기와 자원 소유권
개념
Singleton은 컨테이너 수명, Scoped는 웹 요청 단위, Transient는 해석할 때마다 생성됩니다. 컨테이너가 만든 IDisposable은 컨테이너가 해당 scope 종료 시 정리합니다.
실무 함정
Singleton이 Scoped를 직접 가지는 captive dependency는 요청 상태를 잘못 공유합니다. 임시 disposable을 루트 컨테이너에서 반복 해석하지 말고, 필요 수명이 짧으면 팩터리나 명시적 scope를 설계합니다.
게임 서버 적용
DbContext와 플레이어 요청 문맥은 Scoped, 불변 설정과 thread-safe 클라이언트는 Singleton 후보입니다. 백그라운드 Singleton 서비스에서 Scoped가 필요하면 IServiceScopeFactory로 작업마다 scope를 만들고 즉시 정리합니다.
30초 답변
“수명은 상태와 자원 소유권 계약입니다. 긴 수명의 서비스가 짧은 수명을 캡처하지 않게 하고, 컨테이너가 만든 disposable은 컨테이너에 정리를 맡깁니다.”
2분 답변
수명 선택 때 thread safety, 요청 격리, 연결 소유권을 봅니다. scope validation을 켜고, 백그라운드 작업은 IServiceScopeFactory로 별도 scope를 만든 뒤 작업 종료와 함께 폐기합니다. 서비스 로케이터 대신 생성자 의존성으로 계약을 드러냅니다.
4. async/await, ThreadPool, 취소
개념
비동기 I/O는 대기 중 스레드를 반환해 동시 처리 여지를 높입니다. CancellationToken은 강제 종료가 아니라 호출자가 더 이상 결과를 원하지 않는다는 협력 신호이며, 타임아웃 정책과 요청 취소를 하위 호출에 전달합니다.
실무 함정
.Result·Wait()와 동기 I/O는 ThreadPool starvation과 꼬리 지연을 유발할 수 있습니다. CPU 작업을 요청마다 Task.Run으로 감싸는 것은 용량을 늘리지 않으므로 bounded queue나 별도 워커를 검토합니다.
app.MapPost("/players/{id}/reward", async (
string id, RewardRequest request, GameDbContext db,
CancellationToken cancellationToken) =>
{
var player = await db.Players.SingleAsync(
p => p.Id == id, cancellationToken);
player.Grant(request.ItemId);
await db.SaveChangesAsync(cancellationToken);
return Results.NoContent();
});
게임 서버 적용
클라이언트 연결이 끊긴 조회·검증은 중단하되, 이미 외부 결제가 확정된 보상은 단순 취소하지 않고 멱등 키와 비동기 보상 흐름으로 완결합니다.
30초 답변
“async는 스레드를 더 만드는 기능이 아니라 I/O 대기 중 반환하는 모델입니다. 요청 취소와 타임아웃을 DB·HTTP 호출까지 전달하고, 커밋 경계는 업무 의미에 맞게 정합니다.”
2분 답변
전체 호출 스택을 비동기로 유지하고 ThreadPool queue·thread count·지연을 봅니다. 취소는 OperationCanceledException을 정상 경로와 구분해 기록하며, 취소 가능한 읽기와 반드시 완결해야 할 커밋 후 작업을 나눕니다.
5. GC, LOH, 할당 관리
개념
.NET GC는 세대별 수집으로 짧게 사는 객체를 효율적으로 회수합니다. 큰 객체는 LOH에 배치되고 Gen 2 수집과 연관되어 일시 정지와 메모리 비용에 영향을 줄 수 있습니다.
실무 함정
측정 없이 struct·Span·pooling을 늘리면 복잡성과 데이터 잔류 위험만 커질 수 있습니다. ArrayPool<T>로 빌린 버퍼는 반드시 반환하고, 민감 정보 초기화와 실제 사용 길이를 관리합니다.
게임 서버 적용
랭킹 직렬화·대량 패킷·스냅샷 생성의 할당률, Gen 2/LOH 크기, GC pause를 부하에서 먼저 측정한 뒤 재사용·스트리밍·페이지네이션을 적용합니다.
30초 답변
“GC 튜닝은 할당 프로파일에서 시작합니다. 핫 패스의 큰 임시 버퍼를 줄이고 필요하면 ArrayPool을 쓰되, 반환과 데이터 정리까지 소유권으로 관리합니다.”
2분 답변
할당률과 pause가 SLO에 실제 영향을 주는지 확인하고 call stack을 찾습니다. 작은 객체의 수명 단축, projection·스트리밍, 큰 버퍼 재사용 순으로 바꾸며 변경 전후 꼬리 지연과 메모리를 비교합니다.
6. EF Core 조회 성능
개념
추적 쿼리는 엔티티 원본 값과 identity resolution을 관리해 SaveChanges에 사용합니다. 읽기 전용은 AsNoTracking과 DTO projection으로 필요한 열만 가져오는 선택을 검토합니다.
실무 함정
지연 로딩이나 반복 탐색으로 생기는 N+1, 무제한 Include, 클라이언트가 필요 없는 전체 엔티티 반환을 피합니다. compiled query는 쿼리 컴파일 비용이 병목으로 측정되고 모양이 반복될 때만 적용합니다.
게임 서버 적용
우편함·전투 기록은 페이지네이션과 projection을 쓰고, SQL 로그·실행 계획·왕복 횟수로 인덱스와 쿼리 형태를 검증합니다.
30초 답변
“읽기는 기본적으로 필요한 열만 projection하고 추적 필요성을 명시합니다. N+1은 SQL 왕복을 관측해 없애고 compiled query는 측정된 반복 핫 패스에만 씁니다.”
2분 답변
추적은 업데이트 편의와 identity resolution 이점도 있으므로 항상 끄는 규칙은 피합니다. 데이터 크기·중복·왕복·생성 SQL을 비교하고, 먼저 쿼리와 인덱스를 개선한 뒤 컴파일 비용이 남으면 compiled query를 검토합니다.
7. 트랜잭션과 낙관적 동시성
개념
한 번의 SaveChanges는 지원되는 관계형 공급자에서 기본적으로 트랜잭션으로 실행됩니다. 동시성 토큰은 읽은 값이 갱신 전까지 유지됐는지 조건에 포함하고, 충돌 시 DbUpdateConcurrencyException으로 드러납니다.
실무 함정
트랜잭션 안에서 원격 API를 기다리거나 사용자 입력을 기다리면 잠금 시간이 길어집니다. 격리 수준을 높이는 것만으로 모든 업무 경쟁이 해결되지 않으며 재시도 시 업무 규칙을 다시 검증해야 합니다.
for (var attempt = 0; attempt < 3; attempt++)
{
try
{
player.Spend(cost);
await db.SaveChangesAsync(cancellationToken);
break;
}
catch (DbUpdateConcurrencyException) when (attempt < 2)
{
await db.Entry(player).ReloadAsync(cancellationToken);
player.ValidateCanSpend(cost);
}
}
게임 서버 적용
재화 차감은 짧은 DB 트랜잭션과 동시성 토큰을 사용하고, 요청 멱등 키·원장 유일 제약으로 네트워크 재시도까지 방어합니다.
30초 답변
“동시성 토큰으로 lost update를 감지하고, 충돌하면 최신 값을 다시 읽어 업무 규칙을 재검증합니다. 트랜잭션은 짧게 유지하고 외부 호출은 분리합니다.”
2분 답변
격리 수준, 동시성 토큰, 유일 제약은 서로 다른 실패를 막습니다. 재화처럼 경쟁이 많은 경로는 원장과 멱등 키를 함께 두며, 제한 재시도와 충돌 지표를 운영합니다. 재시도 후에도 실패하면 사용자에게 안전한 재요청 계약을 제공합니다.
8. 보안과 Rate Limiting
개념
인증은 주체를 확인하고 인가는 해당 자원·행동 권한을 판단합니다. 입력 검증, 출력 인코딩, 비밀 관리, 최소 권한을 계층별로 적용하며 ASP.NET Core Rate Limiting 정책으로 공정성과 애플리케이션 안정성을 보조합니다.
실무 함정
속도 제한은 대규모 DDoS를 애플리케이션 하나가 막는 장치가 아닙니다. CDN·WAF·네트워크 계층 보호와 함께 쓰고, 프록시 IP 신뢰와 사용자·기기·엔드포인트별 키의 우회 가능성을 검토합니다.
게임 서버 적용
로그인·쿠폰·닉네임 검색에 서로 다른 정책을 두고, 공격 시 정상 이용자를 모두 차단하지 않도록 계정·IP·디바이스 신호와 단계적 거부를 조합합니다. 비밀은 소스와 이미지에 넣지 않습니다.
30초 답변
“인증 후 자원 단위 인가를 하고, 입력은 서버가 다시 검증합니다. Rate Limiting은 남용과 자원 고갈 완화용이며 DDoS는 엣지·네트워크 보호와 함께 대응합니다.”
2분 답변
신뢰 경계를 클라이언트, 프록시, API, 데이터 저장소로 나눕니다. 정책 키와 한도를 엔드포인트 위험에 맞추고 429·재시도 정보와 지표를 제공합니다. 비밀 회전, 감사 로그, 최소 권한, 침해 시 폐기 절차까지 운영 계약으로 설명합니다.
9. 캐시와 일관성
개념
IMemoryCache는 프로세스 로컬이라 인스턴스 간 공유되지 않고, Redis 같은 분산 캐시는 여러 인스턴스가 공유할 수 있습니다. 캐시는 원본 데이터의 소유자가 아니며 만료·무효화·장애 시 동작을 함께 설계합니다.
실무 함정
동시 만료 때 원본으로 몰리는 캐시 스탬피드를 막기 위해 single-flight, 만료 지터, stale-while-revalidate 같은 전략을 선택합니다. 분산 캐시를 쓰면 네트워크 지연과 직렬화, 부분 실패가 추가됩니다.
게임 서버 적용
정적 마스터 데이터는 버전 키로 캐시하기 쉽지만, 재화 잔액처럼 강한 일관성이 필요한 값은 캐시를 권위 저장소로 취급하지 않습니다.
30초 답변
“로컬 캐시는 빠르지만 인스턴스별이고, 분산 캐시는 공유되지만 네트워크 실패가 생깁니다. 데이터별 허용 가능한 stale 시간과 무효화 주체부터 정합니다.”
2분 답변
cache-aside에서 miss·만료·원본 장애를 분리해 관측합니다. 인기 키는 single-flight와 지터로 보호하고, 쓰기 후 무효화 실패를 대비해 버전 키나 이벤트를 사용합니다. 적중률만 아니라 원본 부하와 stale 오류를 봅니다.
10. 관측성, OpenTelemetry 분산 추적, SLO
개념
구조화 로깅은 검색 가능한 속성을 남기고, RED는 요청률·오류·지연, USE는 자원 사용률·포화·오류를 봅니다. OpenTelemetry의 trace·metric·log 상관관계로 서비스 경계를 잇습니다.
실무 함정
플레이어 ID·토큰·채팅 원문 같은 민감 정보를 무분별하게 기록하지 않습니다. 모든 요청의 고카디널리티 label과 전체 trace를 보존하면 비용과 조회 품질이 악화되므로 샘플링·보존·마스킹 정책을 둡니다.
게임 서버 적용
로그인 성공률, 매칭 지연, 재화 처리 오류율을 사용자 여정 SLI로 정의하고, SLO 오류 예산 소진 시 배포 중지와 롤백·완화 runbook으로 연결합니다.
30초 답변
“로그·메트릭·trace를 배포 버전과 상관관계 ID로 연결하고, 사용자 관점 SLO를 경보 기준으로 씁니다. 장애 때는 범위 확인, 완화, 원인 분석 순서입니다.”
2분 답변
RED로 API 증상을, USE로 자원 원인을 좁히고 trace로 느린 의존성을 찾습니다. 경보는 SLO 소진 속도에 맞춰 잡음을 줄이며, 먼저 롤백·기능 차단·용량 보호로 영향을 완화합니다. 사후에는 타임라인과 탐지·복구 지연을 개선 과제로 남깁니다.
모바일 게임 서버 시나리오
설계 답변은 요구를 먼저 좁히고, 정합성·실패·관측·확장의 순서로 검증합니다.
1. 출시일 로그인 폭주
요구사항 질문
예상 동시 접속, 허용 대기 시간, 익명·기존 사용자 우선순위, 목표 성공률과 DB의 안전 처리량을 확인합니다.
핵심 설계
CDN·WAF 뒤 입구 Rate Limiting과 용량이 제한된 대기열을 두고, 인증 확인과 토큰 발급 경로를 분리합니다. 클라이언트에는 지수 백오프와 jitter가 포함된 재시도 시점을 줍니다.
정합성
로그인 시 쓰기를 최소화하고 세션·토큰 발급은 요청 ID로 중복을 식별합니다. 대기 순서는 절대 공정성보다 등급별 정책과 만료 규칙을 명시합니다.
실패 모드
인증 저장소가 느려지면 입구 허용량을 낮추고 신규 로그인을 대기시킵니다. 무제한 재시도와 열린 연결이 DB 연결 풀을 고갈시키지 않게 합니다.
관측 지표
대기열 길이·예상 대기 시간, 허용·거부·로그인 성공률, DB 연결 풀·CPU, 토큰 발급 p95/p99와 재시도율을 봅니다.
확장 전략
무상태 입구와 토큰 발급기를 수평 확장하되, DB 안전 한도를 기준으로 전체 허용률을 조정합니다. 지역·플랫폼별 셀로 장애 범위를 줄입니다.
꼬리 질문
- 대기열 서버 자체가 병목이면 어떤 정보를 근사치로 제공합니까?
- VIP 우선순위가 일반 사용자 기아를 만들지 않게 하려면?
2. 인벤토리 재화 지급
요구사항 질문
재화가 소모성인지, 음수 허용 여부, 지급 근거와 감사 보존 기간, 한 플레이어의 최대 쓰기 빈도를 묻습니다.
핵심 설계
명령 ID를 멱등 키로 받고 DB 유니크 제약으로 중복을 차단합니다. 불변 원장을 먼저 기록하고 현재 잔액은 원장과 같은 짧은 트랜잭션에서 갱신합니다.
정합성
플레이어 버전 열로 낙관적 동시성을 적용하고 충돌 시 최신 잔액에서 규칙을 다시 검증합니다. 원장 합계와 잔액을 주기적으로 대조합니다.
실패 모드
응답 유실 뒤 같은 명령이 오면 기존 결과를 반환합니다. 원장 저장은 성공하고 후속 알림이 실패하면 outbox에서 재처리합니다.
관측 지표
멱등 중복률, 동시성 충돌률, 원장·잔액 불일치, 트랜잭션 p99, 플레이어별 쓰기 편향과 outbox 적체를 봅니다.
확장 전략
플레이어 ID로 쓰기 소유권을 샤딩하고 핫 플레이어를 제한합니다. 읽기 모델은 비동기로 만들되 지급 확인은 권위 저장소 결과를 사용합니다.
꼬리 질문
- 명령 ID 보존 기간이 끝난 뒤 재요청은 어떻게 처리합니까?
- 원장과 잔액 불일치가 발견되면 어느 쪽을 기준으로 복구합니까?
3. 실시간 랭킹과 시즌 정산
요구사항 질문
순위 갱신 빈도, 동점 규칙, 상위·내 주변 조회, 시즌 종료 시점의 정확성 및 보상 완료 기한을 확인합니다.
핵심 설계
Redis Sorted Set은 실시간 점수·순위 조회에 사용하고, 모든 점수 변경은 영속 원장에 기록합니다. 시즌 마감에는 입력을 버전으로 봉인한 스냅샷을 만듭니다.
정합성
이벤트 ID로 중복 갱신을 막고 동점 키를 고정합니다. 최종 보상은 Redis 현재값이 아니라 재현 가능한 마감 스냅샷을 기준으로 지급합니다.
실패 모드
Redis 장애 시 최근 스냅샷이나 제한된 조회로 강등하고 영속 이벤트에서 재구축합니다. 마감 중 지연 이벤트의 포함 기준을 시즌 버전으로 판정합니다.
관측 지표
갱신 지연, Redis 메모리·명령 p99, 원장 대비 점수 불일치, 스냅샷 소요 시간, 보상 적체와 중복 지급률을 봅니다.
확장 전략
게임 모드·리전별 보드를 분할하고 상위권 병합은 별도 집계 계층에서 수행합니다. 과거 시즌은 불변 저장소로 내려 온라인 집합을 작게 유지합니다.
꼬리 질문
- 마감 직전 늦게 도착한 승리 이벤트를 어디까지 인정합니까?
- 수백만 명의 내 주변 순위를 효율적으로 조회하려면?
4. 앱스토어 결제 검증
요구사항 질문
지원 스토어, 구독·소모품 유형, 환불과 보류 상태, 검증 지연 허용치, 고객 지원의 수동 복구 권한을 확인합니다.
핵심 설계
클라이언트 영수증을 신뢰하지 않고 스토어 서버에서 검증합니다. 영수증·거래 ID에 유일 제약을 두고 검증 결과, 보상 명령, outbox를 원자적으로 저장합니다.
정합성
동일 거래는 한 번만 보상하고 상태 전이는 단조롭게 관리합니다. 환불은 원거래를 참조하는 보상 원장으로 남겨 감사 가능하게 합니다.
실패 모드
스토어 타임아웃은 지급 실패로 확정하지 않고 보류 큐에서 제한 재시도합니다. DB 커밋 뒤 응답 유실은 거래 ID 조회로 기존 결과를 반환합니다.
관측 지표
스토어별 검증 성공·보류·거부율, 지연 p99, 중복 거래 차단, 보상 outbox 나이, 환불 처리량과 수동 개입 건수를 봅니다.
확장 전략
스토어 어댑터를 격리하고 검증 워커를 수평 확장합니다. 재시도는 jitter와 회로 차단을 쓰며 거래 ID 기준 파티션으로 순서를 유지합니다.
꼬리 질문
- 스토어 검증 API가 몇 시간 중단되면 사용자 경험을 어떻게 설계합니까?
- 환불 후 이미 소비한 재화는 어떤 정책으로 처리합니까?
5. 라이브 이벤트 무중단 배포
요구사항 질문
대상 세그먼트, 시작·종료의 시간 정확도, 클라이언트 최소 버전, 긴급 중단 권한과 롤백 허용 시간을 묻습니다.
핵심 설계
불변 설정 버전과 스키마 검증을 두고 피처 플래그로 내부·일부 리전·전체 순서로 단계적 출시합니다. 모든 변경은 작성자·승인자와 함께 감사 기록에 남깁니다.
정합성
요청 동안 같은 설정 버전을 사용하고 보상 명령에 이벤트 버전을 기록합니다. 서버 시간이 권위이며 중복 참여는 유일 제약으로 막습니다.
실패 모드
오류율이나 경제 지표가 임계치를 넘으면 kill switch로 신규 참여를 막고 이전 설정 버전으로 롤백합니다. 이미 지급된 보상은 삭제하지 않고 보상 정책을 적용합니다.
관측 지표
설정 버전별 참여·완료·오류율, 보상 발행량, 경제 인플레이션 신호, 플래그 전파 지연과 롤백 소요 시간을 봅니다.
확장 전략
버전 설정을 CDN·로컬 캐시에 배포하되 짧은 전파 지연을 계약으로 둡니다. 세그먼트 계산은 미리 구체화하고 핫 경로에서 복잡한 규칙 평가를 피합니다.
꼬리 질문
- 두 설정 버전이 동시에 보일 때 보상 일관성을 어떻게 지킵니까?
- 잘못 지급된 이벤트 보상을 회수할 기준은 무엇입니까?
6. 치팅과 리플레이 공격 방어
요구사항 질문
보호할 가치, 클라이언트 변조 가능성, 허용 시계 오차, 차단 전 증거 수준과 오탐 시 복구 절차를 확인합니다.
핵심 설계
요청에 nonce·timestamp·signature를 검증하고 짧은 재사용 창을 둡니다. 결과·재화·쿨다운은 서버 권위 데이터로 다시 계산하며 위험 행위는 속도 제한합니다.
정합성
nonce 소비와 명령 처리를 같은 원자 경계 또는 멱등 기록으로 연결합니다. 서명은 기기 신뢰의 보조 신호일 뿐 클라이언트 값을 권위로 만들지 않습니다.
실패 모드
캐시 장애로 nonce 확인이 불가능하면 고위험 거래는 보류하고 저위험 읽기는 제한 허용합니다. 즉시 영구 차단보다 격리·추가 검증으로 오탐 피해를 줄입니다.
관측 지표
서명 실패·nonce 재사용·시간 오차 분포, 계정별 행동 속도, 탐지 규칙별 정탐·오탐, 이의 제기와 해제 시간을 봅니다.
확장 전략
저비용 규칙은 입구에서, 행동 그래프와 이상 탐지는 비동기 파이프라인에서 수행합니다. 규칙 버전을 기록해 판정 재현성과 단계적 출시를 보장합니다.
꼬리 질문
- 모바일 기기 시계가 크게 틀린 정상 사용자는 어떻게 처리합니까?
- 서명 비밀이 유출됐을 때 회전과 하위 호환은 어떻게 합니까?
7. 멀티 리전 플레이어 상태
요구사항 질문
지역별 지연 SLO, 데이터 주권, 허용 가능한 RPO·RTO, 지역 이동 빈도와 전체 리전 장애 시 기능 우선순위를 묻습니다.
핵심 설계
플레이어마다 홈 리전을 지정하고 상태 쓰기 소유권을 한 리전에 둡니다. 타 리전은 홈으로 라우팅하며 읽기 모델과 복구 사본은 비동기 복제합니다.
정합성
epoch가 포함된 소유권 토큰으로 이전 리전의 늦은 쓰기를 거부합니다. 홈 이전은 쓰기 동결·복제 확인·소유권 전환의 명시적 절차로 수행합니다.
실패 모드
리전 간 단절 때 양쪽 쓰기를 열지 않고 비소유 리전은 읽기 전용 또는 제한 기능으로 강등합니다. 승격은 합의된 RPO 손실과 재조정 절차를 따릅니다.
관측 지표
홈 라우팅 지연, 복제 lag, epoch 거부, 리전별 오류 예산, 장애 감지·승격·복구 시간과 실제 RPO를 측정합니다.
확장 전략
플레이어를 리전 안에서 다시 샤딩하고 인기 길드 같은 교차 플레이어 기능은 별도 소유권을 둡니다. 셀 단위 배포로 부분 장애 범위를 제한합니다.
꼬리 질문
- 홈 리전 복구 뒤 임시 리전의 변경을 어떻게 재조정합니까?
- 길드 전쟁처럼 여러 홈 리전을 묶는 쓰기는 어떻게 설계합니까?