본문 바로가기

CPlusPlus

c++로 Restful API 서버 만들기

개요

C++ Native Deamon 소프트웨어들은 전통적으로 TCP/IP소켓을 통해 서로 통신하는게 일반적이었습니다. 하지만 최근 Restful API가 대세로 자리 잡으면서 일반적인 데이터 통신시 HTTP방식으로의 연동을 많이 사용합니다.

최근 프로젝트에서  기존에 C++로 개발된 서버에 연동규격을 Restful API로 변경하는 작업을 진행하였는데 그 떄 사용했던 프레임워크에 대해서 간략히 소개합니다. 

 

RestBed

Restbed는 RESTful API Server 애플리케이션을 구축하기 위한 C++11 라이브러리입니다. HTTP 요청 및 응답 처리, JSON 구문 분석 및 직렬화, 비동기 처리 등을 포함하여 RESTful API를 구축하기 위한 포괄적인 기능이 제공합니다. Restbed는 유연하고 효율적이며 사용하기 쉽도록 설계되어 C++로 RESTful API를 구축하는 데  사용될 수 있습니다. Restbed를 사용하면 HTTP 요청을 처리하고 동적 콘텐츠를 제공하기 위한  코드를 작성할 수 있으며 인증, 속도 제한 및 로깅과 같은 기능을 사용하여 API에 기능을 추가할 수도 있습니다.

 

장점

1.심플함

Restbed는 RESTful API를 구축하기 위한 유연한 프레임워크를 제공하여 들어오는 요청에 대한 사용자 지정 엔드포인트 및 핸들러를 간단하고 직관적으로 정의할 수 있습니다.


2.효율적인 처리

Restbed는 들어오는 HTTP 요청을 효율적으로 처리하도록 설계되어 비동기 처리, 연결 풀링 등을 위한 기능을 제공합니다.


3.JSON 지원

Restbed에는 JSON 데이터 구문 분석 및 직렬화 지원이 포함되어 있어 API에서 JSON을 쉽게 사용할 수 있습니다.


4.다큐먼트

문서화가 비교적 잘되어 있고 예제도 다양하게 지원합니다.


5.Cross Flatform

Restbed는 Windows, macOS 및 Linux를 포함한 여러 운영 체제를 지원합니다. 개인적으로 가장 큰 장점이라 생각합니다.

단점

1.제한된 커뮤니티

Restbed는 다른 RESTful API 프레임워크만큼 널리 사용되지 않아 입맛에 맞는 도움말과 리소스를 찾기가 더 어려울 수 있습니다.

2.복잡한 API

Restbed는 많은 기능과 옵션을 제공하므로 이를 사용하고 API를 구성하는 방법을 이해하기 어려울 수 있습니다.

3.성능 오버헤드

Restbed는 트래픽이 많은 API의 성능에 영향을 줄 수 있는 API에 약간의 오버헤드를 추가할 수 있습니다.

4.디버깅

복잡한 API에서 문제의 원인을 추적하는 것이 어려울 수 있으므로 Restbed 문제를 디버깅하는 것은 어려울 수 있습니다.

전반적으로 Restbed는 C++에서 RESTful API를 구축하기 위한 좋은 선택이지만 사용 가능한 유일한 옵션은 아니며 프레임워크 선택은 특정 요구 사항과 요구 사항에 따라 달라집니다. JSON 및 크로스 플랫폼 개발을 잘 지원하는 유연하고 효율적인 API 프레임워크를 찾고 있다면 Restbed가 좋은 선택일 수 있습니다.

Install

Windows, Linux 또는 macOS 컴퓨터에 Restbed API를 설치하려면 다음 단계가 필요합니다.

소스코드 다운로드: Restbed용 소스코드는 github에서  (https://github.com/Corvusoft/restbed) 다운로드할 수 있습니다.

라이브러리 빌드: 소스 코드를 다운로드한 후 다음 명령을 실행하여 라이브러리를 빌드해야 합니다.

git clone https://github.com/corvusoft/restbed.git
mkdir restbed/build
cd restbed/build
cmake [-DBUILD_SSL=NO] [-DBUILD_TESTS=NO] ..
make install
make test

Windows환경에서는 직접 빌드보다 vpckg로 설치하는 편을 추천합니다.(보다 간단합니다.)

git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install restbed

 

사용하기

#include <memory>
#include <cstdlib>
#include <restbed>

using namespace std;
using namespace restbed;

// resource handler함수
void post_method_handler( const shared_ptr< Session > session )
{
    const auto request = session->get_request( );

    int content_length = request->get_header( "Content-Length", 0 );

    session->fetch( content_length, [ ]( const shared_ptr< Session > session, const Bytes & body )
    {
        fprintf( stdout, "%.*s\n", ( int ) body.size( ), body.data( ) );
        session->close( OK, "Hello, World!", { { "Content-Length", "13" } } );
    } );
}

// resource2 handler함수, 파라메터는 동일합니다.
void post_method_handler2( const shared_ptr< Session > session )
{
    const auto request = session->get_request( );

    int content_length = request->get_header( "Content-Length", 0 );

    session->fetch( content_length, [ ]( const shared_ptr< Session > session, const Bytes & body )
    {
        fprintf( stdout, "%.*s\n", ( int ) body.size( ), body.data( ) );
        session->close( OK, "Hello, World!", { { "Content-Length", "13" } } );
    } );
}

int main( const int, const char** )
{
	// URL별로 resource객체를 생성합니다.
    auto resource = make_shared< Resource >( );
    resource->set_path( "/post/v1/resource" );
    resource->set_method_handler( "POST", post_method_handler );
    
    auto resource2 = make_shared< Resource >( );
    resource2->set_path( "/post/v1/about" );
    resource2->set_method_handler( "POST", post_method_handler2 );

    auto settings = make_shared< Settings >( );
    settings->set_port( 1984 );
    settings->set_default_header( "Connection", "close" );

    Service service;
    // 생성된 모든 resource는 반드시 publish해야 동작합니다.
    service.publish( resource );
    service.publish( resource2 );
    service.start( settings );

    return EXIT_SUCCESS;
}

 

각 path별로 Handler함수를 등록해야 합니다. 예제와는 다르게 실제 서비스 구현시 Handler함수는 별도의 소스파일에 작성하는게 향후 유지보수에 좋을 것 같습니다.

 

두번째 예제입니다.

#include <restbed>

using namespace restbed;

void wildcard_handler(const shared_ptr<Session> session)
{
    const auto request = session->get_request();
    const auto path = request->get_path();
    const auto method = request->get_method();

    string response = "Hello from the wildcard handler!\n";
    response += "Method: " + method + "\n";
    response += "Path: " + path + "\n";

    session->close(OK, response, { { "Content-Length", to_string(response.length()) } });
}

int main(const int, const char**)
{
    auto resource = make_shared<Resource>();
    resource->set_path("/.*");
    resource->set_method_handler("GET", wildcard_handler);

    auto settings = make_shared<Settings>();
    settings->set_port(8080);

    Service service;
    service.publish(resource);
    service.start(settings);

    return 0;
}

 

WildCard(/.*)를 등록하면 지정되지 않는 모든 URL 요청을 처리합니다.

 

다음은 로깅기능을 추가합니다. Tomcat에서 제공되는 access log와 비슷하게 모든 접속기록을 기록합니다. 로깅을 활성화 해두면 나중에 유지보수중에 문제가 발생할 경우 해결의 실마리를 제공할 수 있습니다.

 

https://github.com/Corvusoft/restbed/blob/master/documentation/example/LOGGING.md

 

GitHub - Corvusoft/restbed: Corvusoft's Restbed framework brings asynchronous RESTful functionality to C++14 applications.

Corvusoft's Restbed framework brings asynchronous RESTful functionality to C++14 applications. - GitHub - Corvusoft/restbed: Corvusoft's Restbed framework brings asynchronous RESTful functi...

github.com

 

마지막으로 RedtBed에 대한 주관적인 견해입니다. Redtbed은 복잡한 Restful API 서버 구현으로는 적합하진 않으나 C++로 Windows, Linux에서 Portable하게 사용할 수 있는 간단한 API구현으로 좋은 선택이 될 수 있습니다.

 

읽어주셔서 감사합니다.