C++์˜ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค. ํ—ˆ๊ตฌ์ธ๊ฐ€ ํ˜„์‹ค์ธ๊ฐ€?

C++์˜ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค. ํ—ˆ๊ตฌ์ธ๊ฐ€ ํ˜„์‹ค์ธ๊ฐ€?

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ํ…œํ”Œ๋ฆฟ(cookiecutter)์„ ์ƒ์„ฑํ•˜๊ณ  docker/docker-compose ๋ฐ conan ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ C++์—์„œ REST API ์„œ๋น„์Šค๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ™˜๊ฒฝ์„ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ œ๊ฐ€ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์ž๋กœ ์ฐธ๊ฐ€ํ•œ ๋‹ค์Œ ํ•ด์ปคํ†ค์—์„œ๋Š” ๋‹ค์Œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๋ฌด์—‡์„ ์‚ฌ์šฉํ•ด์•ผ ํ• ์ง€์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ์“ด ๋ชจ๋“  ๋‚ด์šฉ์€ ์ €์™€ ์ œ๊ฐ€ ์“ด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์นœ๊ตฌ ๋‚ด ๋™๋ฃŒ๋Š” ์ด ๋ถ„์•ผ์˜ ์ „๋ฌธ๊ฐ€์ด๊ณ  ๋ฐฑ์—”๋“œ๋ฅผ ์ „๋ฌธ์ ์œผ๋กœ ๊ฐœ๋ฐœํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ ๊ฐœ๋ฐœ์ž์˜€์œผ๋ฉฐ โ€‹โ€‹์œ„๋Œ€ํ•˜๊ณ  ๋”์ฐํ•œ C++๋กœ ๊ธ€์„ ์ผ๊ณ  ๋Œ€ํ•™์—์„œ Python์„ ๋ง‰ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ๋กœ๋“œ๊ฐ€ ๋งŽ์€ ์„œ๋น„์Šค๋ฅผ ์ž‘์„ฑํ•˜๋Š” ์ž‘์—…์— ์ง๋ฉดํ•˜๊ฒŒ ๋˜์—ˆ๋Š”๋ฐ, ๊ทธ ์ฃผ์š” ์ž‘์—…์€ ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ „์ฒ˜๋ฆฌํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์“ฐ๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋˜ ๋‹ค๋ฅธ ์—ฐ๊ธฐ๊ฐ€ ๋๋‚œ ํ›„ ์นœ๊ตฌ๊ฐ€ C++ ๊ฐœ๋ฐœ์ž์ธ ๋‚˜์—๊ฒŒ ์ „๋ฌธ๊ฐ€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ์„œ๋น„์Šค๋ฅผ ์ž‘์„ฑํ•˜๋ผ๊ณ  ์ œ์•ˆํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋” ๋น ๋ฅด๊ณ  ์ƒ์‚ฐ์ ์ผ ๊ฒƒ์ด๋ผ๊ณ  ์ฃผ์žฅํ•˜๋ฉฐ ์ผ๋ฐ˜์ ์œผ๋กœ ์‹ฌ์‚ฌ์œ„์›๋‹จ์€ ์šฐ๋ฆฌ๊ฐ€ ํŒ€์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๊ณ  ์žˆ๋Š” ๋ฐฉ๋ฒ•์— ๊ธฐ๋ปํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์— ๋‚˜๋Š” C++์—์„œ ๊ทธ๋Ÿฐ ์ผ์„ ํ•ด๋ณธ ์ ์ด ์—†์œผ๋ฉฐ ๋‚จ์€ 20์‹œ๊ฐ„ ์ด์ƒ์„ ์ ์ ˆํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์ปดํŒŒ์ผํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ์‰ฝ๊ฒŒ ํˆฌ์žํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋Œ€๋‹ตํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ„๋‹จํžˆ ๋งํ•ด์„œ, ๋‚˜๋Š” ๊ฒ์„ ๋จน์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ๊ฒฐ์‹ฌํ•˜๊ณ  ์ฐจ๋ถ„ํ•˜๊ฒŒ ๋ชจ๋“  ๊ฒƒ์„ ํŒŒ์ด์ฌ์œผ๋กœ ์™„์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด์ œ ๊ฐ•์ œ ์ž๊ฐ€ ๊ฒฉ๋ฆฌ ์ค‘์— C++๋กœ ์„œ๋น„์Šค๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋จผ์ € ํ•ด์•ผ ํ•  ์ผ์€ ์ ํ•ฉํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚ด ์„ ํƒ์ด ๋–จ์–ด์กŒ์–ด ์กฐ๊ธˆ, ๊ฐ์ฒด ์ง€ํ–ฅ ์Šคํƒ€์ผ๋กœ ์ž‘์„ฑ๋˜์—ˆ์œผ๋ฉฐ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์„œ๋„ ์ž๋ž‘ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ ์กฐ๋ฆฝ ์‹œ์Šคํ…œ ์„ ํƒ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ด ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ๊นŒ์ง€ ์ €๋Š” Visual Studio, IAR ๋ฐ ๊ธฐ๋ณธ makefile๋กœ๋งŒ ์ž‘์—…ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ „์ฒด ์„œ๋น„์Šค๋ฅผ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ์—์„œ ์‹คํ–‰ํ•  ๊ณ„ํš์ด์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ์‹œ์Šคํ…œ ์ค‘ ์–ด๋Š ๊ฒƒ๋„ ๋‚˜์—๊ฒŒ ๋งค๋ ฅ์ ์ด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ cmake์™€ ํฅ๋ฏธ๋กœ์šด ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž๋ฅผ ์•Œ์•„๋ณด๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฝ”๋‚œ. ์ด ํŒจํ‚ค์ง€ ๊ด€๋ฆฌ์ž๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•˜๋‚˜์˜ ํŒŒ์ผ์— ๋ชจ๋“  ์ข…์†์„ฑ์„ ๋“ฑ๋กํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ”๋‚œํŒŒ์ผ.txt
[ํ•„์š”]poco/1.9.3
libpq/11.5

[์ƒ์„ฑ๊ธฐ] cmake

๊ฐ„๋‹จํ•œ ๋ช…๋ น "conan install"์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜์‹ญ์‹œ์˜ค. ๋‹น์—ฐํžˆ ๋ณ€๊ฒฝ ์‚ฌํ•ญ๋„ ํ•„์š”ํ–ˆ์Šต๋‹ˆ๋‹ค.

CMakeLists.txt

include(build/conanbuildinfo.cmake)
conan_basic_setup()
target_link_libraries(<target_name> ${CONAN_LIBS})

๊ทธ ํ›„ ์ €๋Š” PostgreSQL๊ณผ ํ•จ๊ป˜ ์ž‘์—…ํ•  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ๊ธฐ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์ œ๊ฐ€ ์ž‘์—…ํ•œ ๊ฒฝํ—˜์ด ๊ฑฐ์˜ ์—†์—ˆ๊ณ  ์šฐ๋ฆฌ Python ์„œ๋น„์Šค์™€ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ธฐ๋„ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚ด๊ฐ€ ๋ญ˜ ๋ฐฐ์› ๋Š”์ง€ ์•„์„ธ์š”? ํฌ์ฝ”์— ์žˆ์–ด์š”! ๊ทธ๋Ÿฌ๋‚˜ Conan์€ ๊ทธ๊ฒƒ์ด POCO์— ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค๊ณผ ๊ทธ๊ฒƒ์„ ๋นŒ๋“œํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค; ์ €์žฅ์†Œ์— ์˜ค๋ž˜๋œ ๊ตฌ์„ฑ ํŒŒ์ผ์ด ์žˆ์Šต๋‹ˆ๋‹ค(๋‚˜๋Š” ์ด๋ฏธ POCO ์ž‘์„ฑ์ž์—๊ฒŒ ์ด ์˜ค๋ฅ˜์— ๋Œ€ํ•ด ์ผ์Šต๋‹ˆ๋‹ค). ์ด๋Š” ๋‹ค๋ฅธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ฐพ์•„์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋‚ด ์„ ํƒ์€ ๋œ ์ธ๊ธฐ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ๋–จ์–ด์กŒ์Šต๋‹ˆ๋‹ค. libpg. ๊ทธ๋ฆฌ๊ณ  ์ €๋Š” ์ •๋ง ์šด์ด ์ข‹์•˜์Šต๋‹ˆ๋‹ค. ์ด๋ฏธ ์ฝ”๋‚œ์— ์žˆ์—ˆ๊ณ  ์‹ฌ์ง€์–ด ์กฐ๋ฆฝ๋˜๊ณ  ์กฐ๋ฆฝ๋˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ๋‹จ๊ณ„๋Š” ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์„œ๋น„์Šค ํ…œํ”Œ๋ฆฟ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
Poco::Util::ServerApplication์—์„œ TemplateServerApp ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๊ณ  ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํ…œํ”Œ๋ฆฟ์„œ๋ฒ„์•ฑ

#pragma once

#include <string>
#include <vector>
#include <Poco/Util/ServerApplication.h>

class TemplateServerApp : public Poco::Util::ServerApplication
{
    protected:
        int main(const std::vector<std::string> &);
};

int TemplateServerApp::main(const vector<string> &)
{
    HTTPServerParams* pParams = new HTTPServerParams;

    pParams->setMaxQueued(100);
    pParams->setMaxThreads(16);

    HTTPServer s(new TemplateRequestHandlerFactory, ServerSocket(8000), pParams);

    s.start();
    cerr << "Server started" << endl;

    waitForTerminationRequest();  // wait for CTRL-C or kill

    cerr << "Shutting down..." << endl;
    s.stop();

    return Application::EXIT_OK;
}

๊ธฐ๋ณธ ๋ฉ”์†Œ๋“œ์—์„œ๋Š” ํฌํŠธ, ์Šค๋ ˆ๋“œ ์ˆ˜ ๋ฐ ๋Œ€๊ธฐ์—ด ํฌ๊ธฐ์™€ ๊ฐ™์€ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ๋“ค์–ด์˜ค๋Š” ์š”์ฒญ์— ๋Œ€ํ•œ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ณต์žฅ์„ ๋งŒ๋“ค๋ฉด ์ด๋ ‡๊ฒŒ ๋ฉ๋‹ˆ๋‹ค

TemplateRequestHandlerFactory

class TemplateRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
    virtual HTTPRequestHandler* createRequestHandler(const HTTPServerRequest & request)
    {
        return new TemplateServerAppHandler;
    }
};

์ œ ๊ฒฝ์šฐ์—๋Š” ๋งค๋ฒˆ ๋™์ผํ•œ ํ•ธ๋“ค๋Ÿฌ์ธ TemplateServerAppHandler๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์— ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋ฐฐ์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

TemplateServerAppHandler

class TemplateServerAppHandler : public HTTPRequestHandler
{
public:
    void handleRequest(HTTPServerRequest &req, HTTPServerResponse &resp)
    {
        URI uri(req.getURI());
        string method = req.getMethod();

        cerr << "URI: " << uri.toString() << endl;
        cerr << "Method: " << req.getMethod() << endl;

        StringTokenizer tokenizer(uri.getPath(), "/", StringTokenizer::TOK_TRIM);
        HTMLForm form(req,req.stream());

        if(!method.compare("POST"))
        {
            cerr << "POST" << endl;
        }
        else if(!method.compare("PUT"))
        {
            cerr << "PUT" << endl;
        }
        else if(!method.compare("DELETE"))
        {
            cerr << "DELETE" << endl;
        }

        resp.setStatus(HTTPResponse::HTTP_OK);
        resp.setContentType("application/json");
        ostream& out = resp.send();

        out << "{"hello":"heh"}" << endl;
        out.flush();
    }
};

๋˜ํ•œ PostgreSQL์—์„œ ์ž‘๋™ํ•˜๋Š” ํด๋ž˜์Šค ํ…œํ”Œ๋ฆฟ๋„ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ด๋ธ” ์ƒ์„ฑ๊ณผ ๊ฐ™์€ ๊ฐ„๋‹จํ•œ SQL์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. SQL() ์‹คํ–‰. ๋” ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋‚˜ ๋ฐ์ดํ„ฐ ๊ฒ€์ƒ‰์„ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ์„ ํ†ตํ•ด ์—ฐ๊ฒฐ์„ ์–ป์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. GetConnection() libpg API๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. (์•„๋งˆ๋„ ๋‚˜์ค‘์— ์ด ๋ถˆ์˜๋ฅผ ๋ฐ”๋กœ์žก์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค).

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

#pragma once

#include <memory>
#include <mutex>
#include <libpq-fe.h>

class Database
{
public:
    Database();
    std::shared_ptr<PGconn> GetConnection() const;
    bool ExecuteSQL(const std::string& sql);

private:
    void establish_connection();
    void LoadEnvVariables();

    std::string m_dbhost;
    int         m_dbport;
    std::string m_dbname;
    std::string m_dbuser;
    std::string m_dbpass;

    std::shared_ptr<PGconn>  m_connection;
};

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์„ ์œ„ํ•œ ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ™˜๊ฒฝ์—์„œ ๊ฐ€์ ธ์˜ค๋ฏ€๋กœ .env ํŒŒ์ผ๋„ ์ƒ์„ฑํ•˜๊ณ  ๊ตฌ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

.env

DATABASE_NAME=template
DATABASE_USER=user
DATABASE_PASSWORD=password
DATABASE_HOST=postgres
DATABASE_PORT=5432

๋ชจ๋“  ์ฝ”๋“œ๋Š” ๋‹ค์Œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. github.

C++์˜ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค. ํ—ˆ๊ตฌ์ธ๊ฐ€ ํ˜„์‹ค์ธ๊ฐ€?

์ด์ œ dockerfile๊ณผ docker-compose.yml์„ ์ž‘์„ฑํ•˜๋Š” ๋งˆ์ง€๋ง‰ ๋‹จ๊ณ„๊ฐ€ ์™”์Šต๋‹ˆ๋‹ค. ์†”์งํžˆ ๋งํ•ด์„œ ์ด ์ž‘์—…์— ๋Œ€๋ถ€๋ถ„์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ ธ์Šต๋‹ˆ๋‹ค. ์ œ๊ฐ€ ๋ฉ์ฒญํ•ด์„œ, ๋งค๋ฒˆ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค์‹œ ๋นŒ๋“œํ•ด์•ผ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๊ธฐ๋„ ํ–ˆ์ง€๋งŒ, ์ฝ”๋‚œ์˜ ํ•จ์ • ๋•Œ๋ฌธ์ด๊ธฐ๋„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, conan์ด ํ•„์š”ํ•œ ์ข…์†์„ฑ์„ ๋‹ค์šด๋กœ๋“œ, ์„ค์น˜ ๋ฐ ๋นŒ๋“œํ•˜๋ ค๋ฉด "conan install ."์„ ๋‹ค์šด๋กœ๋“œํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์œผ๋ฉฐ -scompiler.libcxx=libstdc++11 ๋งค๊ฐœ๋ณ€์ˆ˜๋„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋‹จ๊ณ„์—์„œ ๋งŽ์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ์ด ์˜ค๋ฅ˜๋กœ ์ธํ•ด ๋ช‡ ์‹œ๊ฐ„ ๋™์•ˆ ๊ฐ‡ํ˜€ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ๋” ์งง์€ ์‹œ๊ฐ„์— ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ, ์นœ๊ตฌ์˜ ์กฐ์–ธ์— ๋”ฐ๋ผ docker-compose.yml์„ ์ž‘์„ฑํ•œ ํ›„ ์ง€์›์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ฟ ํ‚ค ์ปคํ„ฐ ์ด์ œ ์ฝ˜์†”์— "cookiecutter"๋ฅผ ์ž…๋ ฅํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋งž์ถคํ˜• ํ™˜๊ฒฝ๊ณผ PostgreSQL์ด ์„ค์น˜๋œ C++์˜ REST API ์„œ๋น„์Šค์— ๋Œ€ํ•œ ์™„์ „ํ•œ ํ…œํ”Œ๋ฆฟ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/KovalevVasiliy/cpp_rest_api_template.git" ๊ทธ๋Ÿฐ ๋‹ค์Œ "docker-compose up โ€”build"๋ฅผ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ด ํ…œํ”Œ๋ฆฟ์ด ํ›Œ๋ฅญํ•˜๊ณ  ๊ฐ•๋ ฅํ•˜์ง€๋งŒ C++์™€ ๊ฐ™์€ ์„œํˆฌ๋ฅธ ์–ธ์–ด๋กœ REST API ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•˜๋Š” ์–ด๋ ค์šด ๊ธธ์— ์žˆ๋Š” ์ดˆ๋ณด์ž์—๊ฒŒ ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.
๋˜ํ•œ ์—ฌ๊ธฐ์—์„œ ์ฝ์–ด ๋ณด๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ์‚ฌ. POCO๋กœ ์ž‘์—…ํ•˜๊ณ  ์ž์‹ ๋งŒ์˜ REST API ์„œ๋น„์Šค๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž์„ธํžˆ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€