정글

CGI

nkdev 2025. 5. 5. 10:54

CGI란?

  • 웹 서버와 외부 프로그램이 통신할 때 사용되는 표준 인터페이스
  • 사용자의 요청이 동적인 처리를 필요로 할 때 웹 서버가 외부 프로그램을 실행시킨 후 그 결과를 응답으로 보내야 하는데, 이 때 웹 서버가 외부 프로그램과 상호작용할 때 지켜야 할 규약 혹은 인터페이스
  • CGI는 초기 웹 개발에서 매우 중요한 역할을 했지만, 현대의 웹 개발에서는 더 효율적이고 강력한 기술들로 대체되고 있음 (Node.js, Django같은 현대 프레임워크)
  • 프로그램의 출력 결과를 HTML로 포장해서 브라우저에게 전달

나는 CGI를 어느정도 정리하고 글을 쓰는 중이라서 위 내용이 어떤 말인지 이해가 되는데, 처음 보는 사람들은 이해하기 어려울 것이라고 생각한다. 그래서 CGI가 등장하게 된 배경을 먼저 설명하자면 다음과 같다.

 

CGI가 등장하게 된 배경

  • 초창기 웹은 .html, .jpg와 같은 단순한 정적(static) 파일만 제공할 수 있었음
  • 하지만 사용자 입력, 검색, 계산 등 동적인 응답이 필요해짐
  • 이에 따라 웹 서버가 외부 프로그램을 실행해서 그 결과를 응답으로 제공할 수 있도록 CGI라는 규약을 만듦
  • 단순한 HTML만으로는 동적 응답을 처리할 수 없으므로 웹 서버는 클라이언트가 전달해준 데이터를 사용하여 외부 프로그램을 돌리고 그 반환값을 사용해 다시 HTML을 만들어서 다시 브라우저에게 전달해주는 방식이 CGI

요약하면 단순한 정적 웹 서버가 동적으로 동작하기 위해 외부 프로그램을 실행해 요청에 따라 맞춤 HTML을 생성하도록 한 것이 CGI 기법이다. CGI 동작 흐름을 간단하게 정리해보면 다음과 같다.

 

 

CGI 동작 흐름

  1. 웹 브라우저가 HTTP Request를 웹 서버에게 날린다.
  2. 웹 서버는 동적 데이터 처리가 필요하다고 판단되면 CGI 프로그램을 게이트웨이로 외부 프로그램을 실행시킨다.
  3. 웹 서버는 외부 프로그램 실행 결과를 받아서 다시 웹 브라우저에게 전송한다.

이 과정은 CGI 처리 흐름을 간단하게만 나타낸 것이고 소켓 생성, 시스템콜, CGI 스크립트를 해석하는 인터프리터 호출, 표준 출력으로 HTTP Response 생성 등 많은 과정이 생략되어있다.

이제 tiny web server를 만들면서 그 과정들을 하나 하나 이해하고 구현해야 하므로 더 디테일하게 알아보자.

한 블로그에서 CGI 프로그램의 예시를 가져왔다. (CSAPP 책에는 11.5.4 동적 컨텐츠의 처리에서 다음 과정이 나와있다. 책과 블로그 예시의 차이점은 설명할 예정)

 

CGI 프로그램 예시

1. 클라이언트의 HTTP 요청

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>CGI Form Example</title>
</head>
<body>
    <form action="/cgi-bin/welcome.py" method="post">
        <label for="name">Enter your name:</label>
        <input type="text" id="name" name="name">
        <input type="submit" value="Submit">
    </form>
</body>
</html>

2. CGI 프로그램 (파이썬 스크립트로 작성됨)

  • CGI 프로그램은 어떤 언어로도 작성될 수 있다.
  • 책에는 CGI 프로그램이 C언어로 쓰여져있고 블로그에는 스크립트 언어인 파이썬으로 작성되었다.
  • 파이썬 같은 스크립트 언어의 경우 CGI 스크립트 맨 첫 번째 줄에 #!/usr/bin/env python 와 같이 shebang으로 인터프리터의 경로를 지정해줘야 한다.
  • 왜냐하면 웹 서버가 CGI 프로그램을 execve() 시스템콜로 실행할 때, c언어의 경우 컴파일 하면 그것 자체가 완전한 실행 파일(binary)이 되기 때문에 cpu가 바로 실행할 수 있지만 파이썬과 같은 스크립트 파일의 경우 인터프리터에게 해석을 맡겨야 cpu가 실행할 수 있게 된다. 
  • 인터프리터 : 프로그래밍 언어로 작성된 코드를 한 줄씩 읽어서 실행해주는 프로그램. cpu가 텍스트로 작성된 cgi 파일을 직접 실행할 수 없으므로 첫 줄에는 shebang으로 어떤 인터프리터를 사용할지 지정해주어 execve()가 shebang을 참고해 인터프리터를 호출할 수 있도록 한다.
  • execve() : 리눅스에서 프로그램을 실행하는 시스템콜(system call). pathname에 있는 프로세스를 실행해서 현재 프로세스를 해당 프로세스로 덮어씌워 실행시킨다. 함수 형태는 다음과 같다.
int execve(const char* pathname, char* const argv[], char const envp[]);
#!/usr/bin/env python3

import cgi
import cgitb

cgitb.enable()  # 디버깅을 위해 CGI 트레이스백 활성화

print("Content-Type: text/html")    # HTML로 응답을 보냄
print()                             # 빈 줄로 헤더와 본문을 구분

# 폼 데이터 파싱
form = cgi.FieldStorage()
name = form.getvalue('name')

print("<html><head>")
print("<title>CGI Form Response</title>")
print("</head><body>")
print("<h1>Welcome, {}</h1>".format(name if name else "Guest"))
print("</body></html>")

 

3. CGI 스크립트에 실행 권한 부여

chmod 755 welcome.py

4. Apache 웹 서버 설정 파일에 다음과 같이 설정하여 CGI 스크립트를 사용할 수 있게 설정

<Directory "/path/to/cgi-bin">
    AllowOverride None
    Options +ExecCGI
    Require all granted
    AddHandler cgi-script .py
</Directory>

5. 웹 브라우저에서 http://example/form.html에 접근하여 폼에 이름을 입력하고 제출하면 CGI 스크립트 welcome.py가 실행되어 입력된 이름을 포함한 환영 메시지가 출력

 

책에는 cgi 동작 흐름을 이해하기 전 클라이언트-서버 간 소켓을 통해 read/write와 같은 간단한 동작만 수행하는 에코 서버를 먼저 소개한다. 다음 포스팅에는 에코 서버 코드를 해석해보겠다.

 

'정글' 카테고리의 다른 글

OSI 7 Layers/TCP/UDP/HTTP  (4) 2025.05.06
에코 서버(1) - 호스트와 서비스 변환  (0) 2025.05.05
정적 전역 변수  (2) 2025.04.29
RBTree 정리  (0) 2025.04.18
포인터.. 왜 쓸까?  (2) 2025.04.18