[c++] C++ 웹 서버에서의 정적 파일과 동적 콘텐츠 제공

웹 서버 개발은 웹 기술의 기본이 되며, C++로 작성된 웹 서버 역시 성능과 안정성을 고려한 솔루션으로 많이 사용됩니다. 이 글에서는 C++로 웹 서버를 구축하고 정적 파일과 동적 콘텐츠를 제공하는 방법을 다루도록 하겠습니다.

1. C++으로 간단한 웹 서버 만들기

가장 먼저 필요한 것은 네트워크 통신을 다루는 라이브러리입니다. C++에서는 Boost.Asio나 cpprestsdk 등을 사용하여 이를 구현할 수 있습니다. 본 예시에서는 Boost.Asio를 사용하여 웹 서버를 만들어 보겠습니다.

아래는 Boost.Asio를 사용한 간단한 HTTP 웹 서버의 예시입니다.

#include <boost/asio.hpp>
#include <iostream>

int main() {
    boost::asio::io_service io_service;

    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 8080);
    boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);

    while (true) {
        boost::asio::ip::tcp::socket socket(io_service);
        acceptor.accept(socket);

        std::string response = "HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\nHello";
        boost::asio::write(socket, boost::asio::buffer(response));
    }

    return 0;
}

위 예시는 요청이 오면 항상 “Hello”라는 내용을 반환하는 간단한 웹 서버를 보여줍니다.

2. 정적 파일 제공하기

정적 파일은 미리 저장된 파일로, HTML, CSS, JavaScript, 이미지 파일 등을 포함합니다. 웹 서버는 요청에 따라 이러한 정적 파일을 클라이언트에 제공해야 합니다.

아래는 HTML 파일을 읽어와 클라이언트에 제공하는 예시입니다.

#include <iostream>
#include <fstream>
#include <streambuf>
#include <boost/asio.hpp>

std::string readStaticFile(const std::string& filename) {
    std::ifstream t(filename);
    return std::string((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
}

int main() {
    boost::asio::io_service io_service;

    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 8080);
    boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);

    while (true) {
        boost::asio::ip::tcp::socket socket(io_service);
        acceptor.accept(socket);

        std::string htmlContent = readStaticFile("index.html");
        std::string response = "HTTP/1.1 200 OK\r\nContent-Length: " + std::to_string(htmlContent.size()) + "\r\n\r\n" + htmlContent;
        boost::asio::write(socket, boost::asio::buffer(response));
    }

    return 0;
}

위 예시는 간단히 index.html 파일을 읽어와 클라이언트에 제공하는 과정을 보여줍니다.

3. 동적 콘텐츠 제공하기

동적 콘텐츠는 요청에 따라 생성되는 콘텐츠로, CGI(Common Gateway Interface) 스크립트나 서버 측 프레임워크를 사용하여 생성됩니다. C++에서 원시 소켓을 사용하여 동적 콘텐츠를 생성할 수 있지만, 보다 편리하게는 서버 측 프레임워크를 활용하는 것이 좋습니다.

Boost.Beast와 같은 라이브러리를 활용하여 동적 콘텐츠를 쉽게 생성하고 클라이언트에 제공할 수 있습니다.

#include <boost/beast.hpp>
#include <iostream>

int main() {
    boost::asio::io_service io_service;

    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), 8080);
    boost::asio::ip::tcp::acceptor acceptor(io_service, endpoint);

    while (true) {
        boost::asio::ip::tcp::socket socket(io_service);
        acceptor.accept(socket);

        boost::beast::http::response<boost::beast::http::string_body> res{boost::beast::http::status::ok, 11};
        res.set(boost::beast::http::field::server, "MyServer");
        res.keep_alive(true);
        res.body() = "This is a dynamic content";
        res.prepare_payload();
        boost::beast::http::write(socket, res);
    }

    return 0;
}

위 예시는 요청이 오면 항상 “This is a dynamic content”라는 내용을 반환하는 간단한 방법을 보여줍니다.

마치며

C++를 사용하여 웹 서버를 구현하고 정적 파일 및 동적 콘텐츠를 제공하는 방법에 대해 살펴보았습니다. Boost.Asio, Boost.Beast, 그리고 웹 서버 프레임워크를 사용하여 더 복잡한 웹 서버를 구현할 수 있습니다. 웹 개발에 대한 보다 자세한 내용은 관련 문서와 참조 자료를 참고하시기 바랍니다.

참고 문헌:

이상으로 C++ 웹 서버에서의 정적 파일과 동적 콘텐츠 제공에 대해 알아보았습니다.