From 203be82ae94739dad26388add521bac587168531 Mon Sep 17 00:00:00 2001 From: vvzvvv Date: Wed, 7 Jan 2026 17:08:06 +0900 Subject: [PATCH 1/6] =?UTF-8?q?add:=20=ED=8C=8C=EC=9D=BC=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/server/src/problems/validation/handler-resolver.ts | 0 .../src/problems/validation/handlers/unit-validation.handler.ts | 0 .../server/src/problems/validation/handlers/validation.handler.ts | 0 apps/server/src/problems/validation/validation.service.ts | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/server/src/problems/validation/handler-resolver.ts create mode 100644 apps/server/src/problems/validation/handlers/unit-validation.handler.ts create mode 100644 apps/server/src/problems/validation/handlers/validation.handler.ts create mode 100644 apps/server/src/problems/validation/validation.service.ts diff --git a/apps/server/src/problems/validation/handler-resolver.ts b/apps/server/src/problems/validation/handler-resolver.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/server/src/problems/validation/handlers/unit-validation.handler.ts b/apps/server/src/problems/validation/handlers/unit-validation.handler.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/server/src/problems/validation/handlers/validation.handler.ts b/apps/server/src/problems/validation/handlers/validation.handler.ts new file mode 100644 index 0000000..e69de29 diff --git a/apps/server/src/problems/validation/validation.service.ts b/apps/server/src/problems/validation/validation.service.ts new file mode 100644 index 0000000..e69de29 From e22402feda1e18da86bc1f27acf56eb43e89c696 Mon Sep 17 00:00:00 2001 From: vvzvvv Date: Wed, 7 Jan 2026 17:13:33 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EA=B2=80=EC=A6=9D=20=ED=95=B8?= =?UTF-8?q?=EB=93=A4=EB=9F=AC=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80=20-=20ValidationHandler=20?= =?UTF-8?q?=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20(support,=20validate=20=EB=A9=94=EC=84=9C=EB=93=9C)?= =?UTF-8?q?=20-=20=EB=AC=B8=EC=A0=9C=20=ED=83=80=EC=9E=85=EB=B3=84=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EA=B8=B0=EB=B0=98=20=EA=B5=AC?= =?UTF-8?q?=EC=A1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../validation/handlers/validation.handler.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/server/src/problems/validation/handlers/validation.handler.ts b/apps/server/src/problems/validation/handlers/validation.handler.ts index e69de29..67b477f 100644 --- a/apps/server/src/problems/validation/handlers/validation.handler.ts +++ b/apps/server/src/problems/validation/handlers/validation.handler.ts @@ -0,0 +1,19 @@ +import { ConfigDto } from 'src/problems/dto/submit-request.dto'; +import { SubmitResponseDto } from 'src/problems/dto/submit-response.dto'; + +export interface ValidationHandler { + /** + * 문제 타입(ex. unit)에 대해 핸들러가 지원되는지 여부를 반환하는 메서드 + * @param problemType 문제 타입 문자열 + * @returns 지원 여부 (true/false) + */ + support(problemType: string): boolean; + + /** + * 제출된 풀이를 검증하고 결과를 반환하는 메서드 + * @param submitConfig 제출된 풀이 객체 + * @param problemData 문제의 메타데이터 (우선은 이렇게 둠) + * @returns 검증 결과 객체 + */ + validate(submitConfig: ConfigDto, problemData: any): SubmitResponseDto; +} From f7b9012428fa37d7ffa5d6b7568b2252ca03335b Mon Sep 17 00:00:00 2001 From: vvzvvv Date: Wed, 7 Jan 2026 19:34:45 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EB=AC=B8=EC=A0=9C=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84=20(?= =?UTF-8?q?=ED=83=80=EC=9E=85=EB=B3=84=20=EA=B2=80=EC=A6=9D)=20-=20Validat?= =?UTF-8?q?ionService:=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81=EC=9D=84?= =?UTF-8?q?=20=ED=95=B8=EB=93=A4=EB=9F=AC=EC=97=90=20=EC=9C=84=EC=9E=84=20?= =?UTF-8?q?-=20HandlerResolver:=20=EB=AC=B8=EC=A0=9C=20=ED=83=80=EC=9E=85(?= =?UTF-8?q?ex.=20unit)=EC=97=90=20=EB=A7=9E=EB=8A=94=20=ED=95=B8=EB=93=A4?= =?UTF-8?q?=EB=9F=AC=20=EC=84=A0=ED=83=9D=20-=20UnitValidationHandler:=20?= =?UTF-8?q?=EC=9C=A0=EB=8B=9B=20=EB=AC=B8=EC=A0=9C=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20-=20MVP=EC=9A=A9=20=ED=95=98=EB=93=9C?= =?UTF-8?q?=EC=BD=94=EB=94=A9=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C=EC=A7=81?= =?UTF-8?q?=EC=9D=B4=20=ED=8F=AC=ED=95=A8=EB=90=98=EC=96=B4=20=EC=9E=88?= =?UTF-8?q?=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../problems/validation/handler-resolver.ts | 20 ++++++++++++ .../handlers/unit-validation.handler.ts | 31 +++++++++++++++++++ .../problems/validation/validation.service.ts | 13 ++++++++ 3 files changed, 64 insertions(+) diff --git a/apps/server/src/problems/validation/handler-resolver.ts b/apps/server/src/problems/validation/handler-resolver.ts index e69de29..567accb 100644 --- a/apps/server/src/problems/validation/handler-resolver.ts +++ b/apps/server/src/problems/validation/handler-resolver.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@nestjs/common'; +import { ValidationHandler } from './handlers/validation.handler'; +import { UnitValidationHandler } from './handlers/unit-validation.handler'; + +@Injectable() +export class HandlerResolver { + private handlers: Map; + + constructor(private readonly unitHandler: UnitValidationHandler) { + this.handlers = new Map([['unit', this.unitHandler]]); + } + + resolve(problemType: string): ValidationHandler { + const handler = this.handlers.get(problemType); + if (!handler) { + throw new Error(`${problemType} 에 대한 ValidationHandler가 없습니다.`); + } + return handler; + } +} diff --git a/apps/server/src/problems/validation/handlers/unit-validation.handler.ts b/apps/server/src/problems/validation/handlers/unit-validation.handler.ts index e69de29..b2906c8 100644 --- a/apps/server/src/problems/validation/handlers/unit-validation.handler.ts +++ b/apps/server/src/problems/validation/handlers/unit-validation.handler.ts @@ -0,0 +1,31 @@ +import { ValidationHandler } from './validation.handler'; +import { SubmitResponseDto } from 'src/problems/dto/submit-response.dto'; +import { ConfigDto } from 'src/problems/dto/submit-request.dto'; + +export class UnitValidationHandler implements ValidationHandler { + support(problemType: string): boolean { + return problemType === 'unit'; + } + + validate(submitConfig: ConfigDto, problemData: any): SubmitResponseDto { + // test 용 검증 로직: 제출한 풀이가 problemData.answer와 일치하는지 확인 + const answer = (submitConfig.configInfo?.answer ?? '') as string; + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + const expectedAnswer = problemData.answer as string; + + if (answer === expectedAnswer) { + return { result: 'PASS', feedback: [] }; + } + + return { + result: 'FAIL', + feedback: [ + { + field: 'answer', + code: 'WRONG_ANSWER', + message: '틀렸습니다.', + }, + ], + }; + } +} diff --git a/apps/server/src/problems/validation/validation.service.ts b/apps/server/src/problems/validation/validation.service.ts index e69de29..ada6abd 100644 --- a/apps/server/src/problems/validation/validation.service.ts +++ b/apps/server/src/problems/validation/validation.service.ts @@ -0,0 +1,13 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigDto } from '../dto/submit-request.dto'; +import { HandlerResolver } from './handler-resolver'; + +@Injectable() +export class ValidationService { + constructor(private readonly handlerResolver: HandlerResolver) {} + + validate(problemType: string, submitConfig: ConfigDto, problemData: any) { + const handler = this.handlerResolver.resolve(problemType); + return handler.validate(submitConfig, problemData); + } +} From daf9c84cf2af3fbbca7a00213202883b7ce52385 Mon Sep 17 00:00:00 2001 From: vvzvvv Date: Wed, 7 Jan 2026 19:48:08 +0900 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20ProblemsService=EA=B0=80=20Vali?= =?UTF-8?q?dationService=EB=A5=BC=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD=20-=20=EA=B2=80=EC=A6=9D=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=EC=9D=84=20ValidationService=EB=A1=9C=20?= =?UTF-8?q?=EC=9C=84=EC=9E=84=20-=20ProblemsService=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=EC=A7=81=EC=A0=91=20=EA=B2=80=EC=A6=9D=ED=95=98=EB=8D=98=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0=20-=20ValidationService?= =?UTF-8?q?=EB=A5=BC=20=EC=A3=BC=EC=9E=85=EB=B0=9B=EC=95=84=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EC=9C=84=EC=9E=84=20-=20(test=20=EC=A7=84=ED=96=89?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=B4)=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20problemData=20=EB=AA=A9?= =?UTF-8?q?=20=EA=B0=9D=EC=B2=B4=EB=A1=9C=20=EC=B2=98=EB=A6=AC=ED=95=A8=20?= =?UTF-8?q?-=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=ED=8C=A8=ED=84=B4=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=EC=9D=84=20=EC=9C=84=ED=95=9C=20=EB=A6=AC?= =?UTF-8?q?=ED=8C=A9=ED=86=A0=EB=A7=81=20=EC=9E=91=EC=97=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/server/src/problems/problems.service.ts | 30 +++++++++----------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/apps/server/src/problems/problems.service.ts b/apps/server/src/problems/problems.service.ts index e5868c4..35c4aba 100644 --- a/apps/server/src/problems/problems.service.ts +++ b/apps/server/src/problems/problems.service.ts @@ -1,27 +1,25 @@ import { Injectable } from '@nestjs/common'; import { SubmitRequestDto } from './dto/submit-request.dto'; import { SubmitResponseDto } from './dto/submit-response.dto'; +import { ValidationService } from './validation/validation.service'; @Injectable() export class ProblemsService { + constructor(private readonly validationService: ValidationService) {} + submit(problemId: number, body: SubmitRequestDto): SubmitResponseDto { - const problem_type = body.submitConfig?.[0]; - const answer = (problem_type?.configInfo?.answer ?? '') as string; + // MOCK 문제 데이터 + const problemData = { + problemType: 'unit', + answer: '1234', + }; - // test: 정답이 1234이면 PASS, 아니면 FAIL - const isCorrect = answer === '1234'; + const result = this.validationService.validate( + problemData.problemType, + body.submitConfig[0], + problemData, + ); - return isCorrect - ? { result: 'PASS', feedback: [] } - : { - result: 'FAIL', - feedback: [ - { - field: 'answer', - code: 'WRONG_ANSWER', - message: '틀렸습니다.', - }, - ], - }; + return result; } } From 4b82796ef8ed76112a7f3f18b5d25ffcedc599c0 Mon Sep 17 00:00:00 2001 From: vvzvvv Date: Wed, 7 Jan 2026 19:48:32 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=EB=AC=B8=EC=A0=9C=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=EC=97=90=20=EA=B2=80=EC=A6=9D=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EB=B0=8F=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/server/src/problems/problems.module.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/server/src/problems/problems.module.ts b/apps/server/src/problems/problems.module.ts index 6aa9c76..60eeb2d 100644 --- a/apps/server/src/problems/problems.module.ts +++ b/apps/server/src/problems/problems.module.ts @@ -1,9 +1,17 @@ import { Module } from '@nestjs/common'; import { ProblemsController } from './problems.controller'; import { ProblemsService } from './problems.service'; +import { ValidationService } from './validation/validation.service'; +import { HandlerResolver } from './validation/handler-resolver'; +import { UnitValidationHandler } from './validation/handlers/unit-validation.handler'; @Module({ controllers: [ProblemsController], - providers: [ProblemsService], + providers: [ + ProblemsService, + ValidationService, + HandlerResolver, + UnitValidationHandler, + ], }) export class ProblemsModule {} From d82c74adb7a6638b1ac62fab2db76b2b82401d19 Mon Sep 17 00:00:00 2001 From: vvzvvv Date: Thu, 8 Jan 2026 13:10:56 +0900 Subject: [PATCH 6/6] =?UTF-8?q?refactor:=20=EB=AC=B8=EC=A0=9C=20=EC=9C=A0?= =?UTF-8?q?=ED=98=95=EC=9D=B8=20ProblemType=20=EC=9D=84=20string=20?= =?UTF-8?q?=EC=97=90=EC=84=9C=20enum=20=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/server/src/problems/problems.service.ts | 3 ++- apps/server/src/problems/types/problem-type.enum.ts | 4 ++++ apps/server/src/problems/validation/handler-resolver.ts | 7 ++++--- .../validation/handlers/unit-validation.handler.ts | 5 +++-- .../src/problems/validation/handlers/validation.handler.ts | 5 +++-- apps/server/src/problems/validation/validation.service.ts | 7 ++++++- 6 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 apps/server/src/problems/types/problem-type.enum.ts diff --git a/apps/server/src/problems/problems.service.ts b/apps/server/src/problems/problems.service.ts index 35c4aba..5cff317 100644 --- a/apps/server/src/problems/problems.service.ts +++ b/apps/server/src/problems/problems.service.ts @@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common'; import { SubmitRequestDto } from './dto/submit-request.dto'; import { SubmitResponseDto } from './dto/submit-response.dto'; import { ValidationService } from './validation/validation.service'; +import { ProblemType } from './types/problem-type.enum'; @Injectable() export class ProblemsService { @@ -10,7 +11,7 @@ export class ProblemsService { submit(problemId: number, body: SubmitRequestDto): SubmitResponseDto { // MOCK 문제 데이터 const problemData = { - problemType: 'unit', + problemType: ProblemType.UNIT, answer: '1234', }; diff --git a/apps/server/src/problems/types/problem-type.enum.ts b/apps/server/src/problems/types/problem-type.enum.ts new file mode 100644 index 0000000..1f8183d --- /dev/null +++ b/apps/server/src/problems/types/problem-type.enum.ts @@ -0,0 +1,4 @@ +export enum ProblemType { + UNIT = 'unit', + SCENARIO = 'scenario', +} diff --git a/apps/server/src/problems/validation/handler-resolver.ts b/apps/server/src/problems/validation/handler-resolver.ts index 567accb..064f3b0 100644 --- a/apps/server/src/problems/validation/handler-resolver.ts +++ b/apps/server/src/problems/validation/handler-resolver.ts @@ -1,16 +1,17 @@ import { Injectable } from '@nestjs/common'; import { ValidationHandler } from './handlers/validation.handler'; import { UnitValidationHandler } from './handlers/unit-validation.handler'; +import { ProblemType } from '../types/problem-type.enum'; @Injectable() export class HandlerResolver { - private handlers: Map; + private handlers: Map; constructor(private readonly unitHandler: UnitValidationHandler) { - this.handlers = new Map([['unit', this.unitHandler]]); + this.handlers = new Map([[ProblemType.UNIT, this.unitHandler]]); } - resolve(problemType: string): ValidationHandler { + resolve(problemType: ProblemType): ValidationHandler { const handler = this.handlers.get(problemType); if (!handler) { throw new Error(`${problemType} 에 대한 ValidationHandler가 없습니다.`); diff --git a/apps/server/src/problems/validation/handlers/unit-validation.handler.ts b/apps/server/src/problems/validation/handlers/unit-validation.handler.ts index b2906c8..d19f609 100644 --- a/apps/server/src/problems/validation/handlers/unit-validation.handler.ts +++ b/apps/server/src/problems/validation/handlers/unit-validation.handler.ts @@ -1,10 +1,11 @@ import { ValidationHandler } from './validation.handler'; import { SubmitResponseDto } from 'src/problems/dto/submit-response.dto'; import { ConfigDto } from 'src/problems/dto/submit-request.dto'; +import { ProblemType } from 'src/problems/types/problem-type.enum'; export class UnitValidationHandler implements ValidationHandler { - support(problemType: string): boolean { - return problemType === 'unit'; + support(problemType: ProblemType): boolean { + return problemType === ProblemType.UNIT; } validate(submitConfig: ConfigDto, problemData: any): SubmitResponseDto { diff --git a/apps/server/src/problems/validation/handlers/validation.handler.ts b/apps/server/src/problems/validation/handlers/validation.handler.ts index 67b477f..44633f5 100644 --- a/apps/server/src/problems/validation/handlers/validation.handler.ts +++ b/apps/server/src/problems/validation/handlers/validation.handler.ts @@ -1,13 +1,14 @@ import { ConfigDto } from 'src/problems/dto/submit-request.dto'; import { SubmitResponseDto } from 'src/problems/dto/submit-response.dto'; +import { ProblemType } from 'src/problems/types/problem-type.enum'; export interface ValidationHandler { /** * 문제 타입(ex. unit)에 대해 핸들러가 지원되는지 여부를 반환하는 메서드 - * @param problemType 문제 타입 문자열 + * @param problemType 문제 타입 * @returns 지원 여부 (true/false) */ - support(problemType: string): boolean; + support(problemType: ProblemType): boolean; /** * 제출된 풀이를 검증하고 결과를 반환하는 메서드 diff --git a/apps/server/src/problems/validation/validation.service.ts b/apps/server/src/problems/validation/validation.service.ts index ada6abd..6371638 100644 --- a/apps/server/src/problems/validation/validation.service.ts +++ b/apps/server/src/problems/validation/validation.service.ts @@ -1,12 +1,17 @@ import { Injectable } from '@nestjs/common'; import { ConfigDto } from '../dto/submit-request.dto'; import { HandlerResolver } from './handler-resolver'; +import { ProblemType } from '../types/problem-type.enum'; @Injectable() export class ValidationService { constructor(private readonly handlerResolver: HandlerResolver) {} - validate(problemType: string, submitConfig: ConfigDto, problemData: any) { + validate( + problemType: ProblemType, + submitConfig: ConfigDto, + problemData: any, + ) { const handler = this.handlerResolver.resolve(problemType); return handler.validate(submitConfig, problemData); }