MongoDB
MongoDB 로그 서버 구조
요청 컨텍스트에 수집된 로그를 전용 로그 서버로 전달하고, 게임 코드별 MongoDB 커넥션으로 저장하는 구조
NestJSMongoDBInterceptorRepository
구성 요소
- MongoLogProvider: 요청 컨텍스트에 컬렉션별 로그를 버퍼링하는 경량 유틸. 다수의 서비스/도메인에서 호출해도 한 요청 단위로 합쳐짐.
- MongoLogInterceptor: 컨트롤러 수행 후 버퍼를 읽어 로그 서버에 비동기 전송. 실패하더라도 본 요청의 응답에는 영향이 없도록 설계.
- Log Server (apps/log): 수신 DTO 검증 → 게임 코드별 리포지토리 선택 → 컬렉션별 batch insert. 파싱/검증 실패는 명확한 에러 코드로 응답.
- Repository: Mongoose 커넥션을 직접 사용하여 컬렉션 핸들로 insertMany 실행. 스키마 고정 없이 유연한 로그 스키마를 수용.
요청 → 저장 시퀀스
- 애플리케이션 코드에서 MongoLogProvider.setMongoLog 호출로 컬렉션별 로그를 요청 컨텍스트에 누적
- 응답 직전 MongoLogInterceptor가 버퍼를 JSON으로 직렬화해 로그 서버에 전송(비동기)
- 로그 서버는 gameCd로 리포지토리를 선택하여 MongoDB에 insertMany로 배치 저장
환경 변수 / 연결
- MONGO_LOG_DOCUMENT_URI: 로그 서버의 Mongo 연결 문자열. 예) mongodb://user:pass@host:27017/survive?authSource=survive
- GAME_CODE: 호출 애플리케이션의 게임 코드. 리포지토리 맵의 키와 대문자 일치 필요(예: SURVIVE).
- 로컬: Docker Compose MongoDB(localhost:13017)에 연결, 운영: Kubernetes의 Service DNS(portfolio-manager-mongodb...) 사용.
데이터 모델 / 저장 방식
- 요청 1건에 여러 컬렉션을 동시에 적재 가능한 배치 저장 구조
- 컬렉션은 자유 스키마. 서비스별로 로그 구조를 독립적으로 진화 가능
- 응답으로는 삽입된 문서의 ObjectId 목록을 컬렉션별로 반환
@Controller('log/mongo')
@ApiTags('Mongo')
export class MongoLogController {
constructor(private readonly mongoLogService: MongoLogService) {}
@Post()
@ApiResponseEntity({ summary: '공통 로그' })
@UseGuards(NfTokenGuard)
@ApiSecurity('nfToken')
async setLog(
@Body() createMongoLogInDto: CreateMongoLogInDto,
): Promise<ResponseEntity<unknown>> {
await this.mongoLogService.setMongoLog(createMongoLogInDto);
return ResponseEntity.ok().build();
}
@Post('search')
@ApiResponseEntity({
type: GetMongoLogsOutDto,
isPagination: true,
summary: '몽고 로그 조회',
})
@UseGuards(NfTokenGuard)
@ApiSecurity('nfToken')
async getMongoLogs(
@Body() getMongoLogsInDto: GetMongoLogsInDto,
): Promise<ResponseEntity<GetMongoLogsOutDto>> {
const getMongoLogsOutDto =
await this.mongoLogService.getMongoLog(getMongoLogsInDto);
return ResponseEntity.ok().body(getMongoLogsOutDto);
}
}MongoLogProvider - 요청 컨텍스트 로그 수집
요청 수명주기 동안 분산된 위치에서 수집되는 로그를 컨텍스트에 누적하고, 응답 직후 인터셉터가 전송할 수 있도록 버퍼링합니다.
ProviderContextInterceptor
핵심 개념
- 요청 컨텍스트에 MongoLogs 구조로 컬렉션별 로그 누적
- 단건/배열 모두 지원, 여러 서비스에서 호출해도 한 요청으로 병합
- 오류는 애플리케이션 흐름에 영향 주지 않도록 내부 로깅 후 무시
@Injectable()
export class MongoLogProvider {
static setMongoLog(
collectionName: string,
contents: any,
): void {
try {
const mongoLogs = ContextProvider.getMongoLogs() ?? ({ logs: {} } as MongoLogs);
if (!mongoLogs.logs[collectionName]) mongoLogs.logs[collectionName] = [];
if (Array.isArray(contents)) {
mongoLogs.logs[collectionName] = [
...mongoLogs.logs[collectionName],
...contents,
];
} else {
mongoLogs.logs[collectionName].push(contents);
}
ContextProvider.setMongoLogs(mongoLogs);
} catch (e) {
Logger.error(collectionName, e);
}
}
}