BOJ는 어떻게 만들어졌을까?

2019년 8월 5일 업데이트

이 글의 새로운 버전이 업로드 되었습니다.

본문

Baekjoon Online Judge는 어떻게 만들어졌을까요?

2010년 BOJ의 처음 모습은 매우 간단했습니다.

1

웹 서버는 Apache, 언어는 PHP, DB는 MySQL을 사용했습니다. 채점은 채점 관리와 채점으로 이루어져 있는데, 채점 관리가 MySQL에서 채점할 채점 번호를 받아와서 채점 프로그램을 실행시키는 형식이었습니다. 채점 프로그램을 채점이 완료된 후에 직접 DB에 결과를 넣는 방식이었습니다. 채점 관리와 채점 프로그램을 C언어로 작성되어 있었습니다.

자 이제 2012년입니다. 여기서 중요한 사건이 발생합니다. 웹을 좀 예쁘게 만들어 보고 싶다는 생각이 듭니다. 그 당시에 iOS 앱을 주로 만들고 있었던 저는 MVC를 이용하기로 했습니다.

Django (Python)CakePHP (PHP), Codeigniter(PHP)를 모두 해보았지만, 모두 손에 익지 않았고, 결국 저는 스스로 온라인 저지를 위한 프레임워크를 만들기로 했습니다.

View Template는 직접 작성하는 것이 까다로웠기 때문에, Smarty를 사용하기로 결정했습니다.

MVC에서 모델(M)과 컨트롤러(C)는 직접 PHP로 구현했습니다.

2

조금 복잡해졌네요.

이 때까지는 problem.php?id=1014 와 같은 형식의 주소를 사용하고 있었습니다. /problem/1014 와 같은 URL 을 만들기 위해서, Apache에서 rewrite rule을 이용하기 시작했습니다.

2012년에는 게시판이 없었고, UserVoice를 이용해서 잘못된 데이터에 대한 신고만을 받고 있었습니다.

이 때 생긴 새로운 기능이 문제집입니다.

문제집은 아직 PHP에 익숙하지 않을 때 만든 기능입니다. 그래서, 지금도 조금 느리고 사용하기 불편합니다 ㅠㅠ (빨리 손을 봐야 할텐데요)

이 당시 제 실력으로 문제집 클리어는 도저히 빠르게 구현할 수가 없었습니다. 따라서, Python 스크립트를 작성해서 1시간에 1번씩 문제집 클리어 명단을 업데이트 하기로 했습니다. 1시간에 1번 스크립트를 실행시키는 것은 cron을 이용했습니다.

3

지금은 없지만, 코딩이란 기능도 이 때쯤에 생겼다가 2015년 초에 사라졌었습니다. 코딩이 추가되니 조금 구성이 복잡해졌습니다.

코딩은 채점과 거의 비슷한 기능이었기 때문에, 유사한 생김새를 갖습니다.

4.png

2012년에 만들어서 거의 업데이트 없이 아직까지 사람들이 사용하는 서비스가 하나 더 있습니다. Command Line Submit Tool 인데, shell에서 바로 제출할 수 있게 하는 서비스입니다.  이를 제공하기 위해 서버에서 간단한 API를 제공하기 시작했습니다.

이렇게 서비스를 계속하다가 2014년에 MySQL을 MariaDB로 바꾸게 됩니다.

사용자가 점점 늘어나다보니, 예전에 사용자가 없을 때는 미처 몰랐던 문제점이 생기기 시작했습니다. 일부 페이지가 매우 느리게 구현되어 있었던 것입니다.

페이지를 캐싱하기 시작했습니다. 결과를 캐싱하기 위해서 Redis를 사용하기 시작했습니다.

6.png

페이지를 캐싱하다보니, 몇몇 페이지에 굳이 MySQL에 넣어도 되지 않을 정보들이 보이기 시작했습니다. 대표적으로 각 유저의 탑코더/코드포스 레이팅입니다. 이건 날아가도 금방 다시 가져올 수 있는 데이터입니다. 이러한 데이터들을 Redis에 넣기로 결정했습니다.

7.png

이제 부분 점수 문제를 구현해야 하는 시점입니다.

채점 프로그램과 스페셜 저지 프로그램 사이에 연결 통로가 필요합니다. 지금 채점한 프로그램이 몇 점인지를 전달해줄 마땅한 방법을 모르겠었습니다. 따라서 이것도 Redis에 저장하기로 했습니다.

8

그러던 사이에 코딩은 사라지게 되었고, 채점 서버는 총 2대가 되었습니다. 채점 서버가 2개가 되었습니다.

9

여기서부터는 앞으로의 계획입니다.

채점 서버가 2대가 되다보니 데이터간의 싱크를 맞추는 일이 번거롭습니다. 데이터를 Amazon S3에 올려두고, 다운받으면서 채점을 하려고 합니다.

10.png

채점은 더 많은 언어의 지원과 채점 프로그램 오류로 인한 런타임 에러(C++에서 sync_with_stdio를 쓰지 못하는 문제)를 해결하기 위해서 Docker로 바꿀 예정입니다.

지금은 채점 번호의 홀짝을 기준으로 채점1과 채점2로 나누어서 채점을 하고 있습니다. 채점을 이렇게 하다보면 채점 독식과 같은 현상이 일어났을 때, 재빠르게 처리를 할 수가 없습니다. 따라서, 채점은 다음과 같은 모습으로 바뀔 예정입니다.

11.png

이제 여기서 서버를 Amazon으로 이전하고 여러 개의 작은 서버를 이용해서 서비스를 제공하려고 합니다.

서버를 제외한 나머지 서비스는 아래와 같이 사용하고 있습니다.

사용했던 서비스 입니다.

사용할 예정인 서비스 입니다.

사용하고 있는 주요 도구 및 프로그램은 다음과 같습니다.

  • bower: 웹 패키지 매니저
  • npm: node.js 패키지 매니저
  • composer: PHP 패키지 매니저
  • Grunt: 자동화
  • git: 소스 버젼 관리

웹에서 사용하고 있는 주요 라이브러리입니다.

사용할 라이브러리나 프레임워크 입니다.

BOJ는 어떻게 만들어졌을까?”에 대한 답글 9개

  1. 맨처음 구현된 아키텍쳐에서
    사용자가 솔루션코드를 제출하면, 솔루션코드 데이터가 DB에 저장되고
    이를 체점서버가 읽는방식으로 구현된건가요??? 그렇다면 이는 어떤방식으로 구현했는지 알수있을까요??
    지금 생각나는건 단순 배치프로그램 돌리는거 밖에 생각이 안나네요..ㅎㅎ

    좋아요

    1. 채점 서버가 읽고 컴파일해서 실행합니다.

      이 글에 작성된 구조를 사용했을 당시에는 1초마다 채점이 되지 않은 솔루션 정보를 가져와서 채점했습니다.

      좋아요

  2. 이제 이해가되네요 감사합니다. 추가로 궁금한게 현재 백준사이트에서 솔루션코드 제출하면 실시간으로 갱신되는 채점결과%는 PHP서버가 DB서버에게 채점이 끝날때까지 계속 채점결과데이터를 요청하는건가요?

    좋아요

댓글 남기기

About Baekjoon

스타트링크 블로그에서 지루한 글을 담당하고 있습니다!