산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> C 언어

C++ CGI 웹 프로그래밍 마스터하기

CGI란?

CGI(Common Gateway Interface)는 웹 서버와 사용자 정의 스크립트 간 정보 교환 방식을 정의하는 표준 모음입니다. 현재 NCSA에서 관리하며, CGI는 HTTP 서버 같은 정보 서버와 외부 게이트웨이 프로그램이 인터페이스하는 표준으로 정의됩니다. 현재 버전은 CGI/1.1이며 CGI/1.2가 진행 중입니다.

웹 브라우징 과정

하이퍼링크를 클릭해 웹 페이지나 URL을 탐색할 때 일어나는 일:

  1. 브라우저가 HTTP 웹 서버에 연락해 URL(파일명) 요청
  2. 웹 서버가 URL을 파싱해 파일명 찾기. 파일이 있으면 브라우저로 전송, 없으면 에러 메시지 반환
  3. 브라우저가 서버 응답을 받아 파일 또는 에러 메시지 표시

하지만 HTTP 서버를 특정 디렉터리의 파일이 요청될 때 파일을 돌려보내는 대신 프로그램으로 실행하고, 그 출력을 브라우저에 표시하도록 설정할 수 있습니다. 이것이 CGI의 핵심입니다.

CGI 아키텍처 다이어그램

C++ CGI 웹 프로그래밍 마스터하기

웹 서버 설정

CGI 프로그래밍 전에 웹 서버가 CGI를 지원하고 CGI 프로그램을 처리하도록 구성되었는지 확인해야 합니다. HTTP 서버가 실행할 모든 CGI 프로그램은 미리 구성된 디렉터리에 보관되며, 관례적으로 /var/www/cgi-bin이라고 부릅니다. CGI 파일은 C++ 실행 파일이지만 관례적으로 .cgi 확장자를 사용합니다.

Apache 기본 설정은 /var/www/cgi-bin에서 CGI 프로그램을 실행합니다. 다른 디렉터리를 지정하려면 httpd.conf에서 다음 섹션을 수정:

<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options ExecCGI
    Order allow,deny
    Allow from all
</Directory>
<Directory "/var/www/cgi-bin">
    Options All
</Directory>

첫 번째 CGI 프로그램

#include <iostream>
using namespace std;

int main() {
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n";
    cout << "<head>\n";
    cout << "<title>Hello World - 첫 번째 CGI 프로그램</title>\n";
    cout << "</head>\n";
    cout << "<body>\n";
    cout << "<h2>Hello World! 이것은 내 첫 CGI 프로그램입니다</h2>\n";
    cout << "</body>\n";
    cout << "</html>\n";
    return 0;
}

위 코드를 컴파일해 실행 파일 이름을 cplusplus.cgi로 하고 /var/www/cgi-bin에 둡니다. 실행 권한 부여: chmod 755 cplusplus.cgi

HTTP 헤더

Content-type:text/html\r\n\r\n 줄은 브라우저가 콘텐츠를 이해하도록 전송되는 HTTP 헤더의 일부입니다. 모든 HTTP 헤더는 필드명: 필드값 형태입니다.

번호 헤더 및 설명
1 Content-type: 반환되는 파일의 형식을 정의하는 MIME 문자열. 예: Content-type:text/html
2 Expires: Date 정보가 무효해지는 날짜. 브라우저가 페이지 갱신 시점 결정에 사용. 형식: 01 Jan 1998 12:00:00 GMT
3 Location: URL 요청된 URL 대신 반환할 URL. 리디렉션에 사용
4 Last-modified: Date 리소스의 최종 수정일
5 Content-length: N 반환되는 데이터의 길이(바이트). 브라우저가 다운로드 예상 시간 계산에 사용
6 Set-Cookie: String 문자열을 통해 쿠키 설정

CGI 환경 변수

모든 CGI 프로그램은 다음 환경 변수에 접근할 수 있으며, CGI 프로그램 작성 시 중요한 역할을 합니다.

번호 변수명 및 설명
1 CONTENT_TYPE 클라이언트가 서버로 전송하는 첨부 콘텐츠의 데이터 타입(파일 업로드 등)
2 CONTENT_LENGTH POST 요청에서만 사용 가능한 쿼리 정보의 길이
3 HTTP_COOKIE 설정된 쿠키를 키-값 쌍 형태로 반환
4 HTTP_USER_AGENT 요청을 보낸 사용자 에이전트 정보(브라우저 이름 등)
5 PATH_INFO CGI 스크립트의 경로
6 QUERY_STRING GET 메서드 요청과 함께 전송된 URL 인코딩 정보
7 REMOTE_ADDR 요청한 원격 호스트의 IP 주소. 로깅이나 인증에 유용
8 REMOTE_HOST 요청한 호스트의 정규화된 이름. 없으면 REMOTE_ADDR로 IP 확인
9 REQUEST_METHOD 요청에 사용된 메서드. 주로 GET, POST
10 SCRIPT_FILENAME CGI 스크립트의 전체 경로
11 SCRIPT_NAME CGI 스크립트 이름
12 SERVER_NAME 서버의 호스트명 또는 IP 주소
13 SERVER_SOFTWARE 서버가 실행 중인 소프트웨어 이름과 버전

예제: 모든 CGI 환경 변수 출력

#include <iostream>
#include <stdlib.h>
using namespace std;

const string ENV[24] = {
    "COMSPEC", "DOCUMENT_ROOT", "GATEWAY_INTERFACE",
    "HTTP_ACCEPT", "HTTP_ACCEPT_ENCODING", "HTTP_ACCEPT_LANGUAGE",
    "HTTP_CONNECTION", "HTTP_HOST", "HTTP_USER_AGENT",
    "PATH", "QUERY_STRING", "REMOTE_ADDR", "REMOTE_PORT",
    "REQUEST_METHOD", "REQUEST_URI", "SCRIPT_FILENAME",
    "SCRIPT_NAME", "SERVER_ADDR", "SERVER_ADMIN", "SERVER_NAME",
    "SERVER_PORT", "SERVER_PROTOCOL", "SERVER_SIGNATURE", "SERVER_SOFTWARE"
};

int main() {
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>CGI 환경 변수</title>\n</head>\n<body>\n";
    cout << "<table border=\"0\" cellspacing=\"2\">";
    for (int i = 0; i < 24; i++) {
        cout << "<tr><td>" << ENV[i] << "</td><td>";
        char *value = getenv(ENV[i].c_str());
        if (value != 0) cout << value;
        else cout << "환경 변수가 존재하지 않습니다.";
        cout << "</td></tr>\n";
    }
    cout << "</table></body></html>\n";
    return 0;
}

C++ CGI 라이브러리

실제 예제에서는 CGI 프로그램이 많은 연산을 수행해야 합니다. C++용 CGI 라이브러리는 ftp://ftp.gnu.org/gnu/cgicc/에서 다운로드 가능하며 설치 단계:

$ tar xzf cgicc-X.X.X.tar.gz
$ cd cgicc-X.X.X/
$ ./configure --prefix=/usr
$ make
$ make install

GET 및 POST 메서드

브라우저에서 웹 서버로, 최종적으로 CGI 프로그램으로 정보를 전달해야 하는 상황이 많습니다. 브라우저가 주로 사용하는 두 가지 메서드는 GET과 POST입니다.

GET 메서드로 정보 전달

GET 메서드는 인코딩된 사용자 정보를 페이지 요청에 덧붙여 전송합니다. 페이지와 인코딩 정보는 ? 문자로 구분:

https://www.test.com/cgi-bin/cpp.cgi?key1=value1&key2=value2

GET은 기본 메서드이며 브라우저의 위치 표시줄에 긴 문자열이 나타납니다. 비밀번호 등 민감한 정보 전달에는 절대 사용하지 마세요. 크기 제한이 있어 요청 문자열에 최대 1024자까지 전달 가능합니다.

GET 사용 시 정보는 QUERY_STRING HTTP 헤더로 전달되며, CGI 프로그램에서 QUERY_STRING 환경 변수로 접근 가능합니다.

단순 URL 예제: GET 메서드

/cgi-bin/cpp_get.cgi?first_name=ZARA&last_name=ALI

C++ CGI 라이브러리를 사용한 처리 프로그램:

#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;

int main() {
    Cgicc formData;
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>GET 및 POST 메서드 사용</title>\n</head>\n<body>\n";
    
    form_iterator fi = formData.getElement("first_name");
    if (!fi->isEmpty() && fi != (*formData).end()) {
        cout << "이름: " << **fi << endl;
    } else {
        cout << "이름이 입력되지 않았습니다" << endl;
    }
    cout << "<br/>\n";
    
    fi = formData.getElement("last_name");
    if (!fi->isEmpty() && fi != (*formData).end()) {
        cout << "성: " << **fi << endl;
    } else {
        cout << "성이 입력되지 않았습니다" << endl;
    }
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

컴파일: g++ -o cpp_get.cgi cpp_get.cpp -lcgicc

HTML 폼 예제: GET 메서드

<form action="/cgi-bin/cpp_get.cgi" method="get">
    이름: <input type="text" name="first_name"><br/>
    성: <input type="text" name="last_name" />
    <input type="submit" value="제출" />
</form>

POST 메서드로 정보 전달

POST 메서드는 GET과 같은 방식으로 정보를 패키징하지만, URL 뒤의 텍스트 문자열로 보내는 대신 별도 메시지로 전송합니다. 이 메시지는 표준 입력 형태로 CGI 스크립트에 들어옵니다. 같은 cpp_get.cgi 프로그램이 POST도 처리합니다.

체크박스 데이터 전달

여러 옵션 선택 시 체크박스 사용:

<form action="/cgi-bin/cpp_checkbox.cgi" method="POST" target="_blank">
    <input type="checkbox" name="maths" value="on" /> 수학
    <input type="checkbox" name="physics" value="on" /> 물리
    <input type="submit" value="과목 선택" />
</form>

라디오 버튼 데이터 전달

단일 옵션 선택 시 라디오 버튼 사용:

<form action="/cgi-bin/cpp_radiobutton.cgi" method="post" target="_blank">
    <input type="radio" name="subject" value="maths" checked="checked"/> 수학
    <input type="radio" name="subject" value="physics" /> 물리
    <input type="submit" value="과목 선택" />
</form>

텍스트 영역 데이터 전달

여러 줄 텍스트 전달 시 TEXTAREA 요소 사용:

<form action="/cgi-bin/cpp_textarea.cgi" method="post" target="_blank">
    <textarea name="textcontent" cols="40" rows="4">여기에 텍스트 입력...</textarea>
    <input type="submit" value="제출" />
</form>

드롭다운 박스 데이터 전달

많은 옵션 중 하나 또는 두 개 선택 시 드롭다운 박스 사용:

<form action="/cgi-bin/cpp_dropdown.cgi" method="post" target="_blank">
    <select name="dropdown">
        <option value="Maths" selected>수학</option>
        <option value="Physics">물리</option>
    </select>
    <input type="submit" value="제출"/>
</form>

CGI에서 쿠키 사용

HTTP는 상태 없는 프로토콜이지만, 상용 웹사이트에서는 페이지 간 세션 정보 유지가 필요합니다. 쿠키는 방문자 선호도, 구매 내역, 수수료 등 더 나은 방문자 경험이나 사이트 통계를 위해 정보를 기억하고 추적하는 가장 효율적인 방법입니다.

작동 원리

서버가 방문자 브라우저에 쿠키 형태로 데이터를 보냅니다. 브라우저가 쿠키를 수락하면 방문자 하드 드라이브에 일반 텍스트 레코드로 저장됩니다. 방문자가 사이트 내 다른 페이지에 도착하면 쿠키를 검색할 수 있고, 서버는 저장된 내용을 알 수 있습니다.

쿠키는 5개의 가변 길이 필드로 구성된 일반 텍스트 데이터 레코드입니다:

쿠키 설정

브라우저에 쿠키를 보내는 것은 매우 쉽습니다. 이 쿠키들은 Content-type 필드 전에 HTTP 헤더와 함께 전송됩니다.

#include <iostream>
using namespace std;

int main() {
    cout << "Set-Cookie:UserID = XYZ;\r\n";
    cout << "Set-Cookie:Password = XYZ123;\r\n";
    cout << "Set-Cookie:Domain = www.tutorialspoint.com;\r\n";
    cout << "Set-Cookie:Path = /perl;\n";
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>CGI 쿠키</title>\n</head>\n<body>\n";
    cout << "쿠키 설정 중" << endl;
    cout << "<br/>\n</body>\n</html>\n";
    return 0;
}

Set-Cookie HTTP 헤더로 쿠키를 설정합니다. Expires, Domain, Path 같은 속성은 선택 사항입니다. 쿠키는 매직 라인 Content-type:text/html\r\n\r\n 전에 설정해야 합니다.

쿠키 검색

설정된 모든 쿠키를 쉽게 검색할 수 있습니다. 쿠키는 CGI 환경 변수 HTTP_COOKIE에 저장되며 형태는 다음과 같습니다:

key1=value1; key2=value2; key3=value3....

C++ CGI 라이브러리를 사용한 쿠키 검색 예제:

#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;

int main() {
    Cgicc cgi;
    const_cookie_iterator cci;
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>CGI 쿠키</title>\n</head>\n<body>\n";
    cout << "<table border=\"0\" cellspacing=\"2\">";
    
    const CgiEnvironment& env = cgi.getEnvironment();
    for (cci = env.getCookieList().begin(); cci != env.getCookieList().end(); ++cci) {
        cout << "<tr><td>" << cci->getName() << "</td><td>";
        cout << cci->getValue();
        cout << "</td></tr>\n";
    }
    cout << "</table><br/>\n</body>\n</html>\n";
    return 0;
}

파일 업로드 예제

파일 업로드 시 HTML 폼의 enctype 속성을 multipart/form-data로 설정해야 합니다. type="file"인 input 태그가 "찾아보기" 버튼을 생성합니다.

<html>
<body>
<form enctype="multipart/form-data" action="/cgi-bin/cpp_uploadfile.cgi" method="post">
    <p>파일: <input type="file" name="userfile" /></p>
    <p><input type="submit" value="업로드" /></p>
</form>
</body>
</html>

파일 업로드 처리 스크립트 cpp_uploadfile.cpp:

#include <iostream>
#include <vector>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <cgicc/CgiDefs.h>
#include <cgicc/Cgicc.h>
#include <cgicc/HTTPHTMLHeader.h>
#include <cgicc/HTMLClasses.h>
using namespace std;
using namespace cgicc;

int main() {
    Cgicc cgi;
    cout << "Content-type:text/html\r\n\r\n";
    cout << "<html>\n<head>\n<title>CGI 파일 업로드</title>\n</head>\n<body>\n";
    
    const_file_iterator file = cgi.getFile("userfile");
    if (file != cgi.getFiles().end()) {
        cout << HTTPContentHeader(file->getDataType());
        file->writeToStream(cout);
    }
    cout << "<파일 업로드 성공>\n";
    cout << "</body>\n</html>\n";
    return 0;
}

위 예제는 cout 스트림에 내용을 쓰지만, 파일 스트림을 열어 업로드된 파일 내용을 원하는 위치에 저장할 수도 있습니다.

C 언어

  1. C# 네임스페이스 마스터하기: 구성, 범위, 모범 사례
  2. C++ 연산자 마스터하기: 유형별 완벽 가이드와 실전 예제
  3. C++ 주석: 가독성 높고 유지보수하기 좋은 코드 작성법
  4. C++ 배열을 함수에 전달하는 방법: 실전 가이드
  5. C 프로그래밍 입문: 시스템 프로그래밍의 기초 다지기
  6. C++ 프로그래밍 언어: 개요와 핵심 특징
  7. C++ 상수와 리터럴 완전 정복: 타입, 문법, 모범 사례
  8. C++ 연산자 종합 가이드: 종류, 사용법, 우선순위
  9. C++ 숫자 타입 마스터하기: 실전 가이드
  10. C++ 참조(Reference) 핵심 개념과 포인터와의 차이점