본문 바로가기

algo-with-me

[algo-with-me] 기능 개발 시작 (6) 작성중..

총 6주 프로젝트에서 2주차 부터 본격적인 개발을 시작했습니다!

1주차에는 개발 시작 전 여러 규칙들을 정하고 저희 프로젝트의 뱡항성을 잡는데 많은 시간을 쏟았습니다. 총 6주라는 프로젝트 기간 중에 약 4주정도를 개발하는 시간으로 쓸 예정이었고 이에 맞춰 모든 개발해야할 기능들을 정리했습니다.

개발할 모든 기능을 작성 한 뒤 주차별로 우선순위를 두어 개발할 기능들을 정했습니다.

그리고 드디어 2주차부터 분배한 기능들의 개발을 시작했습니다.

 

이번 포스트에서는 2주차 기능 개발 내용을 담았습니다.

 

프론트 - 무지, 콘, 네오

백 - 저(제이지), 프로도

 

문제 api 구현

가장 처음 구현할 api는 바로 문제 CRD api입니다. 저희는 알고리즘 대회서비스이기 때문에 알고리즘 문제가 있어야 합니다. 저희 초기 기획에서는 알고리즘 문제는 유저는 생성할 수 없고, 저희 내부적으로 문제를 생성할 수 있도록 하기로 결정했습니다. (나중에 문제 생성, 수정, 삭제는 DB에 다이렉트로 하게 되었습니다..)

 

저는 보통 구현 순서를 entity - dto - service - controller 순으로 합니다. 이렇게 해야 자동완성을 사용할 수 있어 편하더라구요.

 

우선, ERD를 보고 엔티티를 만들어 주었습니다.

프레임 코드가 무엇인지 설명하기에 앞서 저희가 채점을 어떻게 하는지 설명해 드리겠습니다. 우선, 저희는 사용자의 편의를 위해 백준 양식이 아닌 프로그래머스 양식으로 유저가 코드를 작성해 제출 할 수 있도록 하였습니다.

function solution(a) {
	return a;
}

그리고 입출력 테스트 케이스는 파일로 저장해 두었습니다.

그러면 채점을 하기 위해서는 저장된 파일을 읽어 input 값을 solution 함수에 인자로 넣어 실행한 뒤 그 결과값을 저장해둔 파일과 비교해야 합니다.

 

저희는 채점 서버와 제출한 코드를 실행하는 서버를 분리했기 때문에 저 결과값을 또 따로 파일로 저장하도록 했습니다.

 

이런 과정이 들어가 있기 때문에 저희는 프레임 코드라는 개념을 사용하기로 했습니다. 프레임 코드는 테스트케이스 입력을 읽어오고, solution 함수의 결과값을 파일로 저장하는 로직입니다. 사용자가 solution 함수가 적힌 코드를 제출하면, 그 위 아래에 프레임코드를 씌워 동작하도록 한것입니다.

 

그 다음은 dto를 만들었습니다. 문제 생성시 필요한 데이터들을 담았습니다! 그리고 이 dto에 대한 검증을 데코레이터만 붙이면 쉽게 해주는 기능이 있어 그것을 사용하였습니다.

pnpm i class-validator class-transformer

class-transformer - 요청을 파싱하여 인스턴스로 만들어 줍니다.

class-validator - dto의 값들을 검증합니다.

 

import { IsNotEmpty } from 'class-validator';

import { Problem } from '../entities/problem.entity';

export class CreateProblemDto {
  @IsNotEmpty()
  title: string;

  @IsNotEmpty()
  timeLimit: number;

  @IsNotEmpty()
  memoryLimit: number;

  @IsNotEmpty()
  testcaseNum: number;

  @IsNotEmpty()
  frameCode: string;

  toEntity(): Problem {
    const problem = new Problem();
    problem.title = this.title;
    problem.timeLimit = this.timeLimit;
    problem.memoryLimit = this.memoryLimit;
    problem.testcaseNum = this.testcaseNum;
    problem.frameCode = this.frameCode;
    return problem;
  }
}

이런식으로 데코레이터를 붙여주면 요청으로 들어오는 값 검증을 간단하게 할 수 있습니다.

 

다음으로는 서비스 로직을 구현하였습니다. 문제 전체조회, 문제 단건조회, 문제 생성, 문제 삭제 로직을 구현했습니다. url은 rest api를 따르려고 노력하였습니다. 복수형 쓰고, url에 문제 id 넣고와 같은 방식을 사용하였습니다.

 

이제 문제 조회 기능이 추가되었는데, 저희는 대회용 문제 조회 기능이라는 비슷하지만 다른 요구사항이 있었습니다.

문제 조회기능은 말 그대로 문제 제목, 문제 내용을 조회하는 기능이고, 대회용 문제 조회 기능은 처음에 사용자에게 보여줄 solution 함수, 공개된 테스트 케이스 등 전달해 주어야 할 데이터가 더 많습니다.

두 조회 기능에서 응답으로 보내주어야 할 데이터가 다르기 때문에 하나의 api를 같이 쓰기보단 용도에 맞게 따로따로 만드는게 맞다고 생각해서 대회용 문제 조회 기능을 추가해 주었습니다.

 

빨간 색 원을 그려둔 작업을 다 끝냈을 때가 2주차 화요일이었습니다. 원래 redis쪽과 websocket 쪽은 다음주에 구현할 예정이었는데 생각보다 빨리 끝나서 다음주 업무를 가져와 구현하기로 했습니다.

 

우선은, http 통신을 하는 채점 api를 만들고 redis queue 까지 적용시킨 뒤에 websocket 연동을 해봐야겠다고 생각했습니다.

 

그래서 약 2일에 걸쳐 채점 api 구현을 완료하였습니다.