{"id":5569,"date":"2026-05-02T11:15:51","date_gmt":"2026-05-02T02:15:51","guid":{"rendered":"https:\/\/www.freelifemakers.org\/wordpress\/?p=5569"},"modified":"2026-05-02T11:18:08","modified_gmt":"2026-05-02T02:18:08","slug":"webserver-miniwebserver-routing-4","status":"publish","type":"post","link":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/2026\/05\/02\/webserver-miniwebserver-routing-4\/","title":{"rendered":"[Webserver]miniWebserver + routing (4)"},"content":{"rendered":"\n<p>\ud83d\udc49\ud83c\udffb \uc6f9\uc11c\ubc84 \ub77c\uc6b0\ud2b8 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\uc2b5\ub2c8\ub2e4.<br>Added web server routing functionality.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uae30\uc874 \ucf54\ub4dc\uc5d0\uc11c \ucd94\uac00\ud558\uac70\ub098 \ubcc0\uacbd\ub41c \ubd80\ubd84\uc740 \u2757\ufe0f\ub85c \ud45c\uc2dc\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.<br>Parts added or changed from the existing code are marked with \u2757\ufe0f.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc124\uba85\uc740 \ucf54\ub4dc \uc8fc\uc11d\uc744 \ucc38\uace0\ud558\uc138\uc694<br>Please refer to the code comments for the explanation.<\/p>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \ucf54\ub4dc \/ Code<\/p>\n\n\n\n<p>\u2714\ufe0f Main.cpp<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"Server.h\"\n#include &lt;iostream&gt;\n#include &lt;thread&gt;\n#include &lt;chrono&gt;\n#include &lt;atomic&gt;\n#include &lt;string&gt;\n#include &lt;map&gt;\n\n\/\/ -- mini_webserver_4 -- \/\/\n\/\/\n\/\/ URL \uacbd\ub85c\uc5d0 \ub530\ub77c HTML\uc744 \ub9ac\ud134\ud558\ub294 \uac04\ub2e8\ud55c \ub77c\uc6b0\ud130 \ud568\uc218\u2757\ufe0f\n\/\/ \ub9c8\uc784\ud0c0\uc785\uc774 \uc5c6\uc73c\ub098 \uc815\uc0c1 \uc791\ub3d9\ud568. \ucd94\ud6c4 \ub9c8\uc784\ud0c0\uc785\ucd94\uac00 \uc608\uc815\n\/\/ A simple router function that returns HTML based on the URL path\u2757\ufe0f\n\/\/ Works correctly even without MIME types. MIME types will be added later.\n\/\/\nstd::string router(const std::string&amp; request) {\n    \/\/ \uc694\uccad \ubb38\uc790\uc5f4\uc5d0\uc11c \uacbd\ub85c(Path) \ucd94\ucd9c \/ Extract path from request string\n    \/\/ \"GET \/login HTTP\/1.1\" -&gt; \"\/login\"\ub9cc \uc798\ub77c\ub0c4 \/ Extract \"\/login\" from \"GET \/login HTTP\/1.1\"\n    size_t start = request.find(\" \") + 1;\n    size_t end = request.find(\" \", start);\n    if (start == std::string::npos || end == std::string::npos) return \"&lt;h1&gt;Error&lt;\/h1&gt;\";\n\n    std::string path = request.substr(start, end - start);\n    std::cout &lt;&lt; \"&#91;Router] Client requested path: \" &lt;&lt; path &lt;&lt; std::endl;\n\n    \/\/ \ub77c\uc6b0\ud305\n    if (path == \"\/\" || path == \"\/index\") {\n        return \"&lt;h1&gt;\ud83c\udfe0 \uba54\uc778 \ud398\uc774\uc9c0\/Main Page&lt;\/h1&gt;&lt;p&gt;\ud658\uc601\ud569\ub2c8\ub2e4! \uc5ec\uae30\ub294 \ud648\uc785\ub2c8\ub2e4.\/ Welcome! This is Home.&lt;\/p&gt;\"\n               \"&lt;h1&gt;\ud83d\udc4bHello~~~!&lt;\/h1&gt;\"\n               \"&lt;a href='\/login'&gt;\ub85c\uadf8\uc778\ud558\ub7ec \uac00\uae30 \/ Go to log in&lt;\/a&gt;\";\n    }\n    else if (path == \"\/login\") {\n        return \"&lt;h1&gt;\ud83d\udd11 \ub85c\uadf8\uc778 \ud398\uc774\uc9c0\/Login Page&lt;\/h1&gt;&lt;p&gt;\uc544\uc774\ub514\uc640 \ube44\ubc88\uc744 \uc785\ub825\ud558\uc138\uc694.\/Please enter your ID and password.&lt;\/p&gt;\"\n               \"&lt;button onclick='location.href=\\\"\/\\\"'&gt;\ud648\uc73c\ub85c\/Home&lt;\/button&gt;\";\n    }\n    else if (path == \"\/data\") {\n        return \"&lt;h1&gt;\ud83d\udcca \ub370\uc774\ud130 \ud604\ud669\/Data Status&lt;\/h1&gt;&lt;p&gt;\ud604\uc7ac \uc11c\ubc84\ub294 \uc815\uc0c1 \uc791\ub3d9 \uc911\uc785\ub2c8\ub2e4.\/The server is currently running.&lt;\/p&gt;\";\n    }\n    else {\n        \/\/ 404 Not Found\n        return \"&lt;h1 style='color:red;'&gt;404 Not Found&lt;\/h1&gt;\";\n    }\n}\n\nint main() {\n\n    \/\/ \uc11c\ubc84 \uc778\uc2a4\ud134\uc2a4 \uc0dd\uc131 \/ Create server instance\n    Server my_server(\"127.0.0.1\", 5080);\n\n    \/\/ main\uc5d0\uc11c \ube0c\ub77c\uc6b0\uc800\uc5d0 \ucd9c\ub825\ub420 \ub0b4\uc6a9\uc744 \uacb0\uc815,\ub78c\ub2e4\ub85c \ube0c\ub77c\uc6b0\uc800\uc5d0 \ub744\uc6b8 \ub0b4\uc6a9\uc744 \uc804\ub2ec\u2757\ufe0f\n    \/\/ \uc11c\ubc84 \uc2dc\uc791\uc804\uc5d0 \uba54\uc138\uc9c0 \ub77c\uc6b0\ud130 \uc14b\ud305,set_handler\uc5d0 router(req)\ub97c \ub9ac\ud134\ud558\ub294 \uc775\uba85\ud568\uc218 \uc2e4\ud589\n    \/\/ Determine the content to be displayed in the browser in main, pass the content to be displayed in the browser to Lambda\u2757\ufe0f\n    \/\/ Set up the message router before starting the server, execute the anonymous function that returns router(req) in set_handler\n    \/\/\n    my_server.set_handler(&#91;&amp;](const std::string&amp; req) {\n        return router(req);\n    });\n\n    \/\/ \uc11c\ubc84\uc2dc\uc791 \/ Start server\n    std::thread server_thread(&amp;Server::start, &amp;my_server); \/\/ \uc11c\ubc84 \uc2dc\uc791 \/ Start server\n    std::cout &lt;&lt; \"--- Starting Server Application ---\" &lt;&lt; std::endl;\n\n\n    std::cout &lt;&lt; \"==============================================\\n\";\n\n\n    \/\/ -----------------------------------------------------------------------\n    \/\/  \uc11c\ubc84 \uc885\ub8cc\n    \/\/ -----------------------------------------------------------------------\n\n\n    \/\/ 2. \uba54\uc778 \uc2a4\ub808\ub4dc\ub294 \uc0ac\uc6a9\uc790 \uc785\ub825 \ub300\uae30 \/ The main thread waits for user input\u2757\ufe0f\n    \/\/ 1)\uc5d4\ud130\uc785\ub825\uc2dc \uc11c\ubc84\uc885\ub8cc\ud558\uae30 \/ Shut down the server when Enter is pressed\n    \/\/ std::cin.get();\n    \/\/\n    \/\/ 2)\/exit\uc785\ub825\uc2dc \uc11c\ubc84 \uc885\ub8cc\ud558\uae30 \/ Shut down the server by entering \/exit\n    std::string command;\n    while (true) {\n        std::cout &lt;&lt; \"CMD&gt; \"; \/\/ \uba85\ub839\uc5b4 \ud504\ub86c\ud504\ud2b8 \ud45c\uc2dc \/ Show command prompt\n\n        \/\/ std::getline\uc744 \uc0ac\uc6a9\ud558\uc5ec \uacf5\ubc31\uc744 \ud3ec\ud568\ud55c \uc804\uccb4 \ubb38\uc790\uc5f4\uc744 \ud55c \ubc88\uc5d0 \ubc1b\uc2b5\ub2c8\ub2e4.\n        \/\/ Use std::getline to get the entire string including spaces at once.\n        if (!std::getline(std::cin, command)) {\n            \/\/ EOF (Ctrl+D \ub4f1)\ub85c \uc785\ub825\uc744 \ubc1b\uc744 \uc218 \uc5c6\ub294 \uc0c1\ud669\uc774 \ubc1c\uc0dd\ud558\uba74 \uc885\ub8cc\n            break;\n        }\n\n        \/\/ \uc785\ub825\ub41c \uba85\ub839\uc5b4\ub97c \ud655\uc778\ud569\ub2c8\ub2e4. \/ Check the input command\n        if (command.empty()) {\n            \/\/ \uc544\ubb34\uac83\ub3c4 \uc785\ub825\ud558\uc9c0 \uc54a\uc558\uc73c\uba74 \uadf8\ub0e5 \ub118\uc5b4\uac11\ub2c8\ub2e4.\/ If you don't enter anything, it will just skip.\n            continue;\n        } else if (command == \"\/exit\" || command == \"exit\") {\n\n            std::cout &lt;&lt; \"&#91;INFO] \uc885\ub8cc \uba85\ub839\uc744 \ubc1b\uc558\uc2b5\ub2c8\ub2e4. \uc11c\ube44\uc2a4 \uc885\ub8cc\ub97c \uc2dc\uc791\ud569\ub2c8\ub2e4.\\n\";\n            std::cout &lt;&lt; \"&#91;INFO] Received a shutdown command. Starting service shutdown.\\n\";\n            break; \/\/ \ub8e8\ud504 \uc885\ub8cc \/ Loop End\n\n        } else if (command == \"\/status\") {\n            std::cout &lt;&lt; \"&#91;STATUS] \uc11c\ube44\uc2a4\ub294 \uc815\uc0c1\uc801\uc73c\ub85c \uc791\ub3d9 \uc911\uc785\ub2c8\ub2e4.\\n\";\n            std::cout &lt;&lt; \"&#91;STATUS] The service is running normally.\\n\";\n        } else {\n            std::cout &lt;&lt; \"&#91;ERROR] \uc54c \uc218 \uc5c6\ub294 \uba85\ub839\uc5b4\uc785\ub2c8\ub2e4. (\/exit, \/status)\\n\";\n            std::cout &lt;&lt; \"&#91;ERROR] Unknown command. (\/exit, \/status)\\n\";\n        }\n    }\n\n    \/\/ 3. \uc0ac\uc6a9\uc790 \uc694\uccad\uc5d0 \uc758\ud574 \uc11c\ubc84\ub97c \uc548\uc804\ud558\uac8c \uc885\ub8cc \u2757\ufe0f\n    \/\/ 3. Safely shut down the server at the user's request \u2757\ufe0f\n    my_server.stop();\n\n    \/\/ 4. \uc885\ub8cc \ub85c\uc9c1 (\uc11c\ubc84\uac00 \uc885\ub8cc\ub418\uc9c0 \uc54a\uae30 \ub584\ubb38\uc5d0 \uc2e4\ud589\ub418\uc9c0 \uc54a\uc74c,\ub098\uc911\uc744 \uc704\ud55c \uc885\ub8cc \ub85c\uc9c1)\n    \/\/ Termination logic (not executed because the server has not terminated, termination logic for later)\n    server_thread.join();\n    my_server.stop();\n\n    return 0;\n}\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Server.cpp<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"Server.h\"\n#include &lt;iostream&gt;\n#include &lt;cstring&gt;\n#include &lt;unistd.h&gt;\n#include &lt;sys\/socket.h&gt;\n#include &lt;netinet\/in.h&gt;\n#include &lt;thread&gt;\n#include &lt;vector&gt;\n#include &lt;functional&gt; \/\/ \ucd94\uac00 \/ Add\n\n#define BACKLOG 10 \/\/ \ub300\uae30 \ud050 \ud06c\uae30 \/ wait queue size\n\nServer::Server(const std::string&amp; ip, int port)\n    : ip_address(ip), port_number(port) {}\n\nvoid Server::run_listener() {\n\n    \/\/std::cout &lt;&lt; \"&#91;INFO] Server listening on \" &lt;&lt; ip_address &lt;&lt; \":\" &lt;&lt; port_number &lt;&lt; std::endl;\n\n    \/\/ --- 1. \uc18c\ucf13 \uc0dd\uc131 \/ Socket Creation --- \/\/\n    server_fd = socket(AF_INET, SOCK_STREAM, 0);\n\n    if (server_fd == -1) {\n        perror(\"socket failed\");\n        exit(EXIT_FAILURE);\n    }\n\n    int opt = 1;\n    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &amp;opt, sizeof(opt)) &lt; 0) {\n        perror(\"setsockopt\");\n        exit(EXIT_FAILURE);\n    }\n\n    \/\/ --- 2. \ubc14\uc778\ub529 \/ Binding --- \/\/\n    struct sockaddr_in address;\n    address.sin_family = AF_INET;         \/\/ IPv4\n    address.sin_addr.s_addr = INADDR_ANY; \/\/ \ubaa8\ub4e0 \uc778\ud130\ud398\uc774\uc2a4 IP \uc0ac\uc6a9 \/ Use all interface IPs\n    address.sin_port = htons(port_number);       \/\/ \ud3ec\ud2b8\ub97c \ub124\ud2b8\uc6cc\ud06c \ubc14\uc774\ud2b8 \uc21c\uc11c\ub85c \ubcc0\ud658 \/ Convert ports to network byte order\n\n    if (bind(server_fd, (struct sockaddr *)&amp;address, sizeof(address)) &lt; 0) {\n        perror(\"bind failed\");\n        close(server_fd);\n        exit(EXIT_FAILURE);\n    }\n\n    \/\/ --- 3. \ub9ac\uc2a4\ub2dd \uc2dc\uc791 \/ setsockopt: listen_socket(socket) --- \/\/\n    if (listen(server_fd, BACKLOG) &lt; 0) {\n        perror(\"listen failed\");\n        close(server_fd);\n        exit(EXIT_FAILURE);\n    }\n    std::cout &lt;&lt; \"Server listening on port \" &lt;&lt; port_number &lt;&lt; \"...\" &lt;&lt; std::endl;\n\n    \/\/ --- 4. \uba54\uc778 \ub8e8\ud504 (Accept loop): \ud074\ub77c\uc774\uc5b8\ud2b8 \uc5f0\uacb0\uc744 \ubb34\ud55c\ud788 \uae30\ub2e4\ub9bc \/ Infinitely waiting for client connections --- \/\/\n    \/\/while (true) { \/\/\u2757\ufe0f\n    \/\/ \ubb34\ud55c\ub8e8\ud504\uc5d0\uc11c \uc885\ub8cc\uc2e0\ud638\ub97c \ubc1b\uc73c\uba74 \ub8e8\ud504\ub97c \uc885\ub8cc \/ Exit the loop when the termination signal is received\n    while (running.load()) {\n\n        \/\/ \uc885\ub8cc\uc2e0\ud638 \uc5ec\ubd80\ub97c \ud655\uc778\ud558\uae30 \uc704\ud574 0.1\ucd08 \ub300\uae30 \/ Wait for 0.1 seconds to check the termination signal\n        std::this_thread::sleep_for(std::chrono::milliseconds(100)); \/\/ \ubd80\ud558 \ubc29\uc9c0\ub97c \uc704\ud574 \ub300\uae30\u2757\ufe0f\n\n        \/\/ IPv4\uad6c\uc870\uccb4 \/ Structure for IPv4 address\n        struct sockaddr_in client_address;\n        socklen_t addrlen = sizeof(client_address);\n\n        \/\/ accept() \ud568\uc218\uac00 \ube14\ub85c\ud0b9(Blocking) \uc0c1\ud0dc\uc5d0\uc11c \ud074\ub77c\uc774\uc5b8\ud2b8 \uc5f0\uacb0\uc744 \uae30\ub2e4\ub9bc\n        \/\/ The accept() function waits for client connections in a blocking state.\n        int client_socket = accept(server_fd, (struct sockaddr *)&amp;client_address, &amp;addrlen);\n        if (running.load() &amp;&amp; client_socket &lt; 0) { \/\/ \u2757\ufe0f\n            perror(\"accept failed\");\n            continue; \/\/ \uc2e4\ud328\ud588\uc73c\uba74 \ub2e4\uc74c \ub8e8\ud504\ub97c \ub3cc\uba70 \uc7ac\uc2dc\ub3c4 \/ Retry in the next loop if it fails\n        }\n        \/\/ \ud074\ub77c\uc774\uc5b8\ud2b8 \uc811\uc18d \/ Client connected\n        std::thread client_thread(&#91;this, client_socket]() {\n            this-&gt;handle_client(client_socket); \/\/\uc678\ubd80\uc5d0\uc11c \uba54\uc138\uc9c0 \ubc14\uafb8\uae30 \/ Change message externally\u2757\ufe0f\n        });\n\n        client_thread.detach();\n    }\n}\n\n\/\/ \ub78c\ub2e4\uc2dd\uc73c\ub85c \uc678\ubd80\uc5d0\uc11c \ub0b4\uc6a9 \ubc14\uafb8\uae30\u2757\ufe0f\n\/\/ Changing content externally using a lambda expression\nvoid Server::handle_client(int client_socket) {\n    char buffer&#91;1024];\n    std::cout &lt;&lt; \"&#91;Connection] New client connected.\" &lt;&lt; std::endl;\n\n    \/\/ \ub370\uc774\ud130 \uc218\uc2e0 \/ Receive data\n    ssize_t bytes_read = read(client_socket, buffer, sizeof(buffer) - 1);\n    if (bytes_read &gt; 0) {\n        buffer&#91;bytes_read] = '\\0';\n        std::string request = buffer;\n        std::cout &lt;&lt; \"&#91;Received] \" &lt;&lt; request.substr(0, 30) &lt;&lt; \"...\" &lt;&lt; std::endl;\n\n        std::string html_content;\n        if (logic_handler) {\n\n            \/\/ main\uc5d0\uc11c \ubcf4\ub0b8 \ub78c\ub2e4\uc2dd \uc2e4\ud589\u2757\ufe0f\n            \/\/ Execute the lambda expression sent from main\n            \/\/ request\ub294 \ubc84\ud37c\uc758 \uac12... \/\n            html_content = logic_handler(request);\n\n        } else {\n            html_content = \"&lt;h1&gt;No Logic Handler set!&lt;\/h1&gt;\";\n        }\n\n        \/\/ HTTP \ud3ec\ub9f7 \uc751\ub2f5 \/ Send HTTP response\n        std::string response = \"HTTP\/1.1 200 OK\\r\\n\"\n                               \"Content-Type: text\/html; charset=utf-8\\r\\n\"\n                               \"Content-Length: \" + std::to_string(html_content.size()) + \"\\r\\n\"\n                               \"\\r\\n\" + html_content;\n\n        write(client_socket, response.c_str(), response.size());\n    }\n\n    \/\/ \uc5f0\uacb0 \uc885\ub8cc \/ Close Connection \u2757\n    close(client_socket);\n    std::cout &lt;&lt; \"&#91;Connection] Client disconnected.\" &lt;&lt; std::endl;\n} \/\/\u2757\n\n\nbool Server::start() {\n    \/\/ \uc11c\ubc84\uac00 \uc2e4\uc81c\ub85c \uc791\ub3d9\ud558\ub294 \uba54\uc778 \ud568\uc218 \/ Main function that actually runs the server\n    try {\n        if (!running.load()) {\n            running.store(true);\n            run_listener();\n            return false;\n        }\n\n    } catch (const std::exception&amp; e) {\n        std::cerr &lt;&lt; \"&#91;ERROR] Server failed to start: \" &lt;&lt; e.what() &lt;&lt; std::endl;\n        return false;\n    }\n    return true;\n}\n\nvoid Server::stop() {\n\n    if (running.load() &amp;&amp; server_fd != -1) { \/\/ \u2757\ufe0f\n\n        \/\/ \ud50c\ub798\uadf8\ub97c false\ub85c \uc124\uc815\ud558\uc5ec \ub8e8\ud504 \uc885\ub8cc \uc2e0\ud638 \uc804\uc1a1\n        \/\/ Set flag to false to send loop termination signal\n        running.store(false);\n        close(server_fd);\n\n        \/\/ \uc2e4\uc81c\ub85c\ub294 \uc5ec\uae30\uc11c \uc18c\ucf13\uc744 \ub2eb\uac70\ub098 \ub9ac\uc18c\uc2a4 \ud574\uc81c\ub97c \uc218\ud589\ud569\ub2c8\ub2e4.\n        \/\/ In practice, close the socket or release resources here.\n        server_fd = -1; \/\/ \ub2eb\uc558\uc73c\ubbc0\ub85c \ucd08\uae30\ud654 \/ Initialize to -1 after closing\n        std::cout &lt;&lt; \"&#91;Server] Shutdown initiated.\" &lt;&lt; std::endl;\n    }\n}\n<\/code><\/pre>\n\n\n\n<p>\u2714\ufe0f Server.h<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;string&gt;\n#include &lt;atomic&gt; \/\/ Atomic Flag \uc0ac\uc6a9\uc744 \uc704\ud574 \ucd94\uac00 \/ Added for using Atomic Flag\u2757\ufe0f\n#include &lt;functional&gt; \/\/ \ucd94\uac00 \/ Add\u2757\ufe0f\n\nclass Server {\npublic:\n    \/\/ \uc0dd\uc131\uc790: \uc11c\ubc84 \ucd08\uae30\ud654 (IP, Port)\n    \/\/ Constructor: Initialize server (IP, Port)\n    Server(const std::string&amp; ip, int port);\n\n    \/\/ \uc18c\uba78\uc790: \uac1d\uccb4\uac00 \ud30c\uad34\ub420 \ub54c \uc11c\ubc84\ub97c \uc548\uc804\ud558\uac8c \uc885\ub8cc\ud569\ub2c8\ub2e4.\u2757\ufe0f\n    \/\/ Destructor: Safely shuts down the server when the object is destroyed.\n    ~Server() {\n        stop();\n    }\n\n    \/\/ \uc11c\ubc84 \uc18c\ucf13 \ud30c\uc77c \ub514\uc2a4\ud06c\ub9bd\ud130\ub97c \uc800\uc7a5\ud560 \uba64\ubc84 \ubcc0\uc218\n    \/\/ Member variable to store server socket file descriptors\n    int server_fd = -1;\n\n    \/\/ \uc11c\ubc84 \uc2e4\ud589 \ud568\uc218: \ub9ac\uc2a4\ub2dd\uc744 \uc2dc\uc791\ud558\uace0 \uba54\uc778 \ub8e8\ud504\ub97c \ub3cc\ub9bc\n    \/\/ Server execution function: Starts listening and runs the main loop\n    bool start();\n\n    \/\/ \uc11c\ubc84 \uc885\ub8cc (\ud544\uc694\ud558\ub2e4\uba74)\n    \/\/ Shut down the server (if necessary)\n    void stop();\n\n    \/\/ -- \ube0c\ub77c\uc6b0\uc800 \uba54\uc138\uc9c0 \ubc14\uafb8\uae30\u2757\ufe0f --\n    \/\/ string(\uc694\uccad)\uc744 \ubc1b\uc544\uc11c string(\uc751\ub2f5\ub0b4\uc6a9)\uc744 \ubc49\ub294 \ud568\uc218\ub97c \ub2f4\ub294 \uadf8\ub987\n    std::function&lt;std::string(const std::string&amp;)&gt; logic_handler;\n\n    \/\/ main\uc5d0\uc11c \ub78c\ub2e4\ub97c \ub123\uc5b4\uc904 \ud568\uc218(Main.cpp\uc5d0\uc11c\uc0ac\uc6a9)\n    void set_handler(std::function&lt;std::string(const std::string&amp;)&gt; handler) {\n        logic_handler = handler;\n    }\n\n    void handle_client_test(int client_socket);\n    \/\/\n\nprivate:\n    std::string ip_address;\n    int port_number;\n\n    \/\/ \uc11c\ubc84\uac00 \uc2e4\ud589 \uc0c1\ud0dc\uc778\uc9c0 \ud655\uc778\ud558\ub294 \ud50c\ub798\uadf8\n    \/\/ Flag to check if the server is running\n    std::atomic&lt;bool&gt; running{false};\/\/ \u2757\ufe0f\n\n    \/\/ \uc2e4\uc81c \ub9ac\uc2a4\ub2dd \ubc0f \uc5f0\uacb0 \uc218\uc2e0 \ub85c\uc9c1 (\ub0b4\ubd80 \uad6c\ud604)\n    \/\/ Actual listening and connection reception logic (internal implementation)\n    void run_listener();\n\n    \/\/ \uc5f0\uacb0 \ucc98\ub9ac \ub85c\uc9c1 (\uc2a4\ub808\ub4dc \ud480 \ub610\ub294 \ubcc4\ub3c4 \ud578\ub4e4\ub7ec\uc5d0\uac8c \uc704\uc784)\n    \/\/ Connection handling logic (delegated to thread pool or separate handler)\n    void handle_client(int client_socket);\n\n};\n<\/code><\/pre>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \ucef4\ud30c\uc77c \/ Compiling<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>g++ Main.cpp Server.cpp -o sersver -std=c++17 -pthread<\/code><\/pre>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb \uc2e4\ud589 \/ Run<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.\/server<\/code><\/pre>\n\n\n\n<p>\ud83d\udc49\ud83c\udffb\ube0c\ub77c\uc6b0\uc800 \uc811\uc18d \/ Access Browser<\/p>\n\n\n\n<p>\u2714\ufe0f \ube0c\ub77c\uc6b0\uc800\uc5d0\uc11c localhot:5080\uc73c\ub85c \uc811\uc18d\ud569\ub2c8\ub2e4.<\/p>\n\n\n\n<p>\u2714\ufe0f localhost:5080, localhost:5080\/love, localhost:5080\/8<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\ud83d\udc49\ud83c\udffb \uc6f9\uc11c\ubc84 \ub77c\uc6b0\ud2b8 \uae30\ub2a5\uc744 \ucd94\uac00\ud588\uc2b5\ub2c8\ub2e4.Added web server routing functionality. \ud83d\udc49\ud83c\udffb \uae30\uc874 \ucf54\ub4dc\uc5d0\uc11c \ucd94\uac00\ud558\uac70\ub098 \ubcc0\uacbd\ub41c \ubd80\ubd84\uc740 \u2757\ufe0f\ub85c \ud45c\uc2dc\ub418\uc5b4 \uc788\uc2b5\ub2c8\ub2e4.Parts added or changed from the existing code are marked with \u2757\ufe0f. \ud83d\udc49\ud83c\udffb \uc124\uba85\uc740 \ucf54\ub4dc \uc8fc\uc11d\uc744 \ucc38\uace0\ud558\uc138\uc694Please refer to the code comments for the explanation. \ud83d\udc49\ud83c\udffb \ucf54\ub4dc \/ Code \u2714\ufe0f Main.cpp \u2714\ufe0f Server.cpp \u2714\ufe0f Server.h \ud83d\udc49\ud83c\udffb \ucef4\ud30c\uc77c \/ [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[],"class_list":["post-5569","post","type-post","status-publish","format-standard","hentry","category-cpp","missing-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/5569","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=5569"}],"version-history":[{"count":3,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/5569\/revisions"}],"predecessor-version":[{"id":5572,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/5569\/revisions\/5572"}],"wp:attachment":[{"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=5569"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=5569"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.freelifemakers.org\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=5569"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}