Code-API 서비스 전체 구조
위 구조는 CodeController를 중심으로 각 구성 요소가 연결되는 방식이다. 각 구성 요소는 다음과 같은 역할을 수행한다.
- CodeController: 전형적인 REST API 서버의 컨트롤러 역할을 하며, 클라이언트 요청을 받아 처리한다. 클라이언트에서 전달된 코드 실행 요청을 CodeService로 전달하고, 결과를 반환한다.
- CodeService: 코드 실행 로직의 핵심 서비스 계층이다. 요청받은 언어에 맞게 Runner 인터페이스의 구현체를 선택하고, 적절한 컴파일러 또는 인터프리터를 호출하여 코드를 실행하도록 한다.
- Runner: 각 언어의 코드 실행을 위한 인터페이스로, 언어별로 다른 실행 방식을 처리할 수 있도록 한다.
- JavaRunnerImpl / PythonRunnerImpl: Runner 인터페이스의 구현체로, 각각 자바와 파이썬 코드를 실행하는 로직을 포함한다. JavaRunnerImpl은 자바 컴파일러를 호출해 자바 코드를 실행하고, PythonRunnerImpl은 파이썬 인터프리터를 호출해 파이썬 코드를 실행한다.
이 구조는 CodeService에서 각 언어의 구현체를 스위칭하여 사용할 수 있게 설계되어 있어, 확장성 및 유지보수성에 유리하다. 추가 언어를 지원하려면 Runner 인터페이스의 새로운 구현체를 추가하여 쉽게 확장할 수 있다.
Code-API 서비스 상세 내용
1. Runner
Runner는 코드 실행을 위한 인터페이스로, 언어별 실행 방식에 따라 다양한 구현체를 가질 수 있도록 설계되었다. 주된 메서드는 다음과 같다:
- runCode(String code, String input): 주어진 코드와 입력을 실행하고, 결과를 반환한다. 실행 중 발생하는 예외를 처리한다.
- stopCode(): 실행 중인 프로세스를 강제로 종료한다. 코드 실행이 중단되어야 할 경우에 호출된다.
Runner 인터페이스는 언어별로 다른 코드 실행 방식을 정의할 수 있도록 JavaRunnerImpl, PythonRunnerImpl 등 구현체에서 구체화된다.
1.1 JavaRunnerImpl
JavaRunnerImpl은 자바 코드를 컴파일하고 실행하기 위한 Runner의 구현체다. 주요 기능은 다음과 같다:
- 컴파일 단계:
- 주어진 자바 코드를 .java 파일로 저장하고, javac 명령어를 사용하여 컴파일한다.
- 컴파일 시 발생하는 오류를 출력으로 반환하여, 코드에 문제가 있을 경우 이를 확인할 수 있도록 한다.
- 실행 단계:
- 컴파일이 성공하면, java 명령어를 통해 생성된 클래스 파일을 실행한다.
- 실행 시 입력이 필요한 경우, 프로세스의 출력 스트림을 통해 입력 데이터를 전달한다.
- 실행 결과와 오류 출력을 수집하여 반환한다.
- 리소스 정리:
- 코드 실행이 완료되면 .java 및 .class 파일을 삭제하여 불필요한 파일을 정리한다.
- 프로세스 종료:
- stopCode 메서드로 실행 중인 프로세스를 강제로 종료하며, 프로세스가 5초 내에 종료되지 않으면 destroyForcibly()로 강제 종료한다.
JavaRunnerImpl은 자바 코드 컴파일 및 실행의 모든 단계에서 발생할 수 있는 오류와 결과를 관리하여, 코드의 성공 여부와 결과를 클라이언트에 반환한다.
1.2 PythonRunnerImpl
PythonRunnerImpl은 파이썬 코드를 실행하기 위한 Runner의 구현체다. 주요 기능은 다음과 같다:
- 실행 단계:
- python3 -c 명령어를 통해 주어진 파이썬 코드를 직접 실행한다.
- 실행 중 입력이 필요한 경우 프로세스의 출력 스트림을 통해 입력 데이터를 전달한다.
- 실행 결과를 수집하고, 표준 오류 스트림을 통해 발생하는 오류를 따로 수집하여 실행 성공 여부에 따라 반환한다.
- 프로세스 종료:
- stopCode 메서드로 실행 중인 프로세스를 종료하며, 5초 내에 프로세스가 종료되지 않을 경우 destroyForcibly()를 통해 강제 종료한다.
PythonRunnerImpl은 파이썬 코드의 실행과 오류 처리를 전담하며, 실행 결과 및 오류 메시지를 클라이언트에 반환하여 코드 실행의 성공 여부를 확인할 수 있게 한다.
이 구조를 통해 Runner 인터페이스와 그 구현체들은 특정 언어에 맞는 코드 실행 방식을 정의하고, 다양한 언어 지원을 위한 확장 가능성을 제공한다. 추가 언어를 지원하려면 Runner의 새로운 구현체를 작성해 쉽게 확장할 수 있다.
2. CodeService
CodeService 클래스는 코드 실행과 저장, 조회 기능을 제공하는 서비스 계층으로, 다양한 언어로 작성된 코드를 실행하고 데이터베이스에 저장하며, 저장된 코드를 조회할 수 있도록 한다. 주요 메서드는 다음과 같다.
2.1 runCode
- 기능: 클라이언트에서 요청한 코드와 입력 데이터를 받아 언어에 맞는 Runner 구현체를 통해 코드를 실행하고, 실행 결과를 반환한다.
- 구현:
- codeReqDto에 설정된 언어에 따라 JavaRunnerImpl 또는 PythonRunnerImpl을 선택하여 코드 실행 환경을 설정한다.
- ExecutorService와 Future를 사용해 비동기로 코드를 실행하며, 실행 시간 제한(10초)을 설정하여 무한 실행을 방지한다.
- 실행 중 예외가 발생할 경우 오류 메시지를 포함한 CodeRespDto를 반환하며, 실행이 완료되면 stopCode 메서드로 실행 중인 프로세스를 종료한다.
- 데이터베이스에 요청된 코드가 존재하지 않으면 새로 저장하고, 이미 존재하면 해당 코드를 업데이트한다.
2.2 saveCode
- 기능: 클라이언트에서 전달받은 코드를 데이터베이스에 저장한다.
- 구현:
- userId, problemId, language를 기준으로 데이터베이스에 기존 코드가 있는지 조회하고, 없을 경우 새로 저장하며, 기존 코드가 있으면 업데이트한다.
- 코드 변경 사항을 쉽게 관리하고 저장할 수 있도록 지원하는 메서드다.
2.3 getCode
- 기능: 특정 사용자(userId)가 특정 문제(problemId)와 언어(language)로 저장한 코드를 데이터베이스에서 조회하여 반환한다.
- 구현:
- 데이터베이스에서 요청한 코드가 존재하지 않을 경우 null을 반환한다.
- 저장된 코드를 불러와 클라이언트에게 제공하여 사용자가 저장된 코드로 작업을 이어갈 수 있도록 한다.
이 클래스는 코드 실행을 위한 언어 선택 및 비동기 실행, 코드 저장과 조회 등의 기능을 통해 코드 실행 API의 핵심 로직을 담당하며, 클라이언트가 다양한 언어의 코드를 효율적으로 실행하고 관리할 수 있도록 지원한다.
'Web > 코테 준비용 서비스 만들기' 카테고리의 다른 글
06. API Gateway 서버 제작 (1) (0) | 2024.11.10 |
---|---|
05. AI API 서버 제작 (0) | 2024.11.09 |
03. 스크래핑 API 서버 제작 (0) | 2024.11.07 |
02. 서비스를 구상해보자! (3) | 2024.10.29 |
01. 코테 준비를 위한 서비스를 만들어보자! (0) | 2024.10.29 |