- 초기 웹 시대에 널리 쓰였던 CGI 프로그램이 현대 하드웨어에서 여전히 높은 성능을 낼 수 있음을 실험으로 확인함
- CGI는 프로세스별로 요청을 처리해 메모리 관리가 자동으로 이뤄지고, 배포가 단순한 장점이 있음
- 벤치마크 결과, 평범한 16스레드 CPU 서버에서도 초당 2400건 이상, 하루 2억 건 이상 요청 처리 가능성을 입증함
- Go 언어와 SQLite로 작성된 guestbook.cgi 예제 코드 및 Dockerfile을 오픈소스로 공개함
- CGI는 지금은 흔히 쓰이지 않지만, 여전히 실용적이고 현대적인 대안이 될 수 있음을 보여줌
CGI 프로그램과 동작 원리
- 2000년대 초반에는 CGI(Common Gateway Interface) 프로그램이 동적 웹사이트 구축의 주요 방식이었음
- 대부분 Perl이나 C 언어로 작성되었으며, 성능 향상을 위해 C가 선택되기도 했음
- CGI의 개념은 간단하지만 강력함
- 웹서버는 환경 변수에 요청 메타데이터(HTTP 헤더, 쿼리 등) 설정
- 별도의 프로세스 생성하여 CGI 프로그램 실행
- 요청 본문을 stdin으로 전달
- 프로그램의 stdout을 HTTP 응답으로 캡처
- stderr 출력을 서버 에러 로그로 전달함
- 프로그램이 요청을 마치면 프로세스가 종료되어 파일 디스크립터 및 메모리가 자동 해제됨
- 개발자 입장에서는 신규 버전 배포도 cgi-bin/ 디렉터리에 파일만 복사하면 배포가 끝나 매우 간단했음
Hug of death(트래픽 폭주)
- 2000년대 초반 웹서버 대부분은 1~2 CPU, 1~4GB 메모리 환경이 일반적임
- Apache 웹서버가 접속마다 httpd 프로세스를 fork하는 구조 특성상, 다수 접속 시 메모리 요구량이 증가함
- 동시 접속이 100개를 넘기 힘들었고, 유명 사이트에 링크만 걸려도 서버가 쉽게 과부하되는 경우가 많았음
- ( Slashdot Effect : 그 당시 유명했던 Slashdot에 링크가 올라오면 트래픽이 쏟아짐. 요즘의 해커뉴스 탑에 오르는 것과 비슷)
현대 서버 환경에서의 CGI
- 현재는 384개의 CPU 스레드를 가진 서버도 출현, 비교적 작은 VM에서도 16개의 CPU 제공 가능
- CPU 및 메모리 성능이 대폭 향상됨
- CGI 프로그램은 별도 프로세스 기반이므로 멀티코어를 자연스럽게 활용 가능함
- 이러한 점 때문에 현대 하드웨어에서 CGI 프로그램이 얼마나 빠른지 직접 벤치마크 테스트를 진행함
- 실험은 AMD 3700X(16스레드) 서버에서 수행함
벤치마크 주요 결과
- 간단한 CGI 프로그램을 Apache와 Go
net/http서버 환경 모두에서 테스트 -
guestbook.cgi 프로그램 설명
- 방문자가 웹사이트 하단에 댓글을 남길 수 있는 간단한 방명록 프로그램 구현
- Go 언어와 SQLite 사용, 최대한 단순하지만 현실성 있도록 설계
- 소스코드와 Dockerfile 모두 GitHub에 공개함
- HTTP 부하 생성 도구
plow를 사용해 16개 연결로 10만 건씩 요청 수행 - 평범한 하드웨어상에서도 초당 2,400건 이상, 즉 하루 2억 건 이상 요청 처리 가능함
- 현재 CGI가 대세는 아니나, 여전히 실제 서비스 운영에서도 사용 가능함
-
Apache 환경에서의 write 벤치마크
- 초당 약 2468건의 요청 처리, 평균 6.47ms의 응답 지연 시간
- 10만 건의 POST 요청을 40.5초 만에 처리
- 대부분 요청이 7ms 내 응답, 극소수만 100ms 초과
- 실질적으로 높은 쓰기 처리 성능 입증
-
Apache 환경에서의 read 벤치마크
- 초당 약 1959건의 요청 처리, 평균 8.16ms의 응답 지연 시간
- 10만 건의 GET 요청을 51초 만에 처리
- 절반 이상의 요청은 8ms 이내, 최대 지연도 31ms에 그침
- 읽기 성능 역시 충분히 우수함
-
Go net/http 환경에서의 write 벤치마크
- 초당 약 2742건의 요청 처리, 평균 5.83ms의 응답 지연 시간
- 10만 건의 POST 요청을 36.4초 만에 처리
- 처리량은 평균 2,742 RPS, 평균 지연 5.8ms로 Apache보다 수치상 더 나은 성능
- 95% 이상의 요청이 6ms 이내 처리됨
- Go 환경에서의 CGI도 충분한 실전 성능 보유
-
Go net/http 환경에서의 read 벤치마크
- 초당 약 2469건의 요청 처리, 평균 6.47ms의 응답 지연 시간
- 10만 건의 GET 요청을 40.4초 만에 처리
- 대부분의 요청이 7ms 안에 서비스 가능
- 읽기 처리량과 응답 속도 모두 Apache와 비슷하거나 우수함
결론 및 링크
- CGI 프로그램은 최신 하드웨어에서 초고속 동시성, 간단한 배포, 운영체제가 자동 자원 해제 등의 장점 보유
- 현대적인 프레임워크에 비해 극히 단순하지만, 일정 규모 서비스에는 지금도 실전 활용 가능
- 방명록 예제 및 벤치마크 실험 데이터는 아래 깃허브에 공개
https://github.com/Jacob2161/cgi-bin