| doc_id | NET-FEAT-001 |
|---|---|
| doc_title | Network System - 상세 기능 |
| doc_version | 1.0.0 |
| doc_date | 2026-04-04 |
| doc_status | Released |
| project | network_system |
| category | FEAT |
SSOT: This document is the single source of truth for Network System - 상세 기능.
언어: English | 한국어
최종 업데이트: 2026-02-08 버전: 0.2.0
이 문서는 Network System의 모든 기능에 대한 포괄적인 세부 정보를 제공합니다.
Network System은 다음 목표를 달성하도록 설계되었습니다:
| 목표 | 설명 | 상태 |
|---|---|---|
| 고성능 | 서브마이크로초 지연시간, 300K+ msg/s | ✅ |
| 제로 카피 I/O | 네트워크 작업을 위한 직접 메모리 매핑 | ✅ |
| 모듈성 | messaging_system과 독립적 | ✅ |
| 비동기 우선 | 코루틴 기반 비동기 작업 (C++20) | ✅ |
| 통합 친화적 | 스레드, 로거, 컨테이너 시스템과 연결 가능 | ✅ |
| 연결 풀링 | 효율적인 연결 재사용 | 🔄 |
| TLS/SSL 지원 | 보안 통신 | ✅ |
- 305K+ msg/s: 초당 30만 메시지 처리
- 서브마이크로초 지연시간: 평균 0.8μs
- 제로 카피: 불필요한 메모리 복사 제거
- 효율적인 버퍼 관리: 메모리 풀링 활용
구현 상태: HTTP/2 전송 기반의 프로토타입 gRPC 프레임워크로, 4가지 RPC 패턴을 모두 지원합니다.
참고: 헤더에 "프로덕션 사용 시 공식 gRPC 라이브러리 래핑을 고려하세요"라고 명시되어 있습니다. NETWORK_GRPC_OFFICIAL 컴파일 플래그를 통해 공식 gRPC C++ 라이브러리와의 선택적 통합이 가능합니다.
기능:
- RPC 패턴: Unary, Server Streaming, Client Streaming, Bidirectional Streaming
- 클라이언트 (
grpc_client):- 동기/비동기 Unary 호출 (
call_raw,call_raw_async) - 모든 스트리밍 패턴의 리더/라이터
- 채널 설정: TLS, 킵얼라이브, 재시도, 최대 메시지 크기
- 호출별 옵션: 데드라인, 메타데이터, 압축, wait-for-ready
- 동기/비동기 Unary 호출 (
- 서버 (
grpc_server):- 4가지 RPC 타입의 메서드 핸들러 등록
server_context: 클라이언트 메타데이터, 취소, 데드라인, 피어 정보, 인증 컨텍스트- TLS 및 상호 TLS 지원 (
start_tls()) - 동시 스트림, 메시지 크기, 킵얼라이브, 연결 제한, 워커 스레드 설정
- 서비스 레지스트리 (
service_registry):generic_service: protobuf 없이 런타임 메서드 등록protoc_service_adapter: protoc 생성 서비스 어댑터 (NETWORK_GRPC_OFFICIAL필요)- 서비스 조회 및 전체 경로 기반 메서드 라우팅
- 리플렉션 지원 (grpcurl 등 디버깅 도구용)
- 헬스 체크 서비스 (
health_service): 표준 gRPC 헬스 체크 프로토콜 구현
주요 클래스:
| 클래스 | 설명 |
|---|---|
grpc_client |
동기/비동기 Unary 및 스트리밍 호출 |
grpc_server |
핸들러 등록 및 TLS 지원 서버 |
service_registry |
서비스 관리 및 라우팅 중앙 레지스트리 |
generic_service |
런타임 메서드 등록을 위한 동적 서비스 |
protoc_service_adapter |
protoc 생성 서비스 어댑터 |
health_service |
표준 gRPC 헬스 체크 구현 |
사용 예:
using namespace kcenon::network::protocols::grpc;
// 서버 설정
grpc_server server({.max_concurrent_streams = 100, .num_threads = 4});
server.register_unary_method("/mypackage.MyService/Echo",
[](server_context& ctx, const std::vector<uint8_t>& request)
-> std::pair<grpc_status, std::vector<uint8_t>> {
return {grpc_status::ok_status(), request}; // Echo back
});
server.start(50051);
// 클라이언트 설정
grpc_client client("localhost:50051", {.use_tls = false});
client.connect();
auto result = client.call_raw("/mypackage.MyService/Echo", request_data);Facade API는 프로토콜 클라이언트 및 서버 생성을 위한 단순화된 통합 인터페이스를 제공합니다. 지원되는 각 프로토콜(TCP, UDP, HTTP, WebSocket, QUIC)에는 동일한 설계 패턴을 따르는 전용 Facade 클래스가 있습니다.
설계 목표:
| 목표 | 설명 | 이점 |
|---|---|---|
| 단순성 | 템플릿 매개변수나 프로토콜 태그 불필요 | 학습 및 사용 용이 |
| 일관성 | 모든 프로토콜에서 동일한 create_client/create_server 패턴 |
인지 부하 감소 |
| 타입 안전성 | 표준 i_protocol_client/i_protocol_server 인터페이스 반환 |
프로토콜 독립 코드 |
| 제로 비용 | 직접 인스턴스화 대비 성능 오버헤드 없음 | 프로덕션 준비 완료 |
| Facade | 헤더 | 프로토콜 | SSL/TLS | 연결 풀 |
|---|---|---|---|---|
tcp_facade |
<kcenon/network/facade/tcp_facade.h> |
TCP | 지원 | 지원 |
udp_facade |
<kcenon/network/facade/udp_facade.h> |
UDP | 미지원 | 미지원 |
http_facade |
<kcenon/network/facade/http_facade.h> |
HTTP/1.1 | 지원 | 미지원 |
websocket_facade |
<kcenon/network/facade/websocket_facade.h> |
WebSocket | 미지원 | 미지원 |
quic_facade |
<kcenon/network/facade/quic_facade.h> |
QUIC | 내장 (TLS 1.3) | 미지원 |
#include <kcenon/network/facade/tcp_facade.h>
using namespace kcenon::network::facade;
// TCP 클라이언트 생성 (일반 또는 보안)
tcp_facade tcp;
auto client = tcp.create_client({
.host = "127.0.0.1",
.port = 8080,
.client_id = "my-client",
.timeout = std::chrono::seconds(30),
.use_ssl = false
});
// TCP 서버 생성
auto server = tcp.create_server({
.port = 8080,
.server_id = "my-server"
});
// i_protocol_client를 통한 프로토콜 독립 사용
client->set_receive_callback([](const std::vector<uint8_t>& data) {
std::cout << "Received " << data.size() << " bytes\n";
});
client->start("127.0.0.1", 8080);Facade는 일반적인 사용 사례를 다룹니다. 프로토콜 고유 기능이 필요한 경우 직접 클래스를 사용합니다:
- TCP: 고급 TLS 설정, 사용자 정의 암호 모음, 직접 세션 제어
- WebSocket: 텍스트 프레임 처리, 프로토콜 확장, 프래그멘테이션 제어
- HTTP: 라우팅, 쿠키, 멀티파트 폼, 사용자 정의 헤더
- QUIC: 멀티 스트림, 스트림 우선순위, 0-RTT 재개, 연결 마이그레이션
자세한 Facade 문서는 Facade API 레퍼런스를 참조하세요. 마이그레이션 가이드는 Facade 마이그레이션 가이드를 참조하세요.
통합 인터페이스 계층은 네트워크 전송, 연결 및 리스너에 대한 프로토콜 독립 추상화를 제공합니다. kcenon/network/detail/unified/에 위치한 이 인터페이스들은 프로토콜별 세부 사항에 의존하지 않고 어떤 네트워크 프로토콜과도 작동하는 코드를 작성할 수 있게 합니다.
계층은 상속 계층을 형성하는 3개의 핵심 인터페이스로 구성됩니다:
i_transport (기본: 데이터 전송, 상태 조회, 엔드포인트 정보)
|
v
i_connection (i_transport 확장: 연결, 종료, 콜백, 옵션)
i_listener (독립: 수신, 수락, 브로드캐스트, 연결 관리)
헤더: <kcenon/network/detail/unified/i_transport.h>
모든 데이터 전송의 기본 인터페이스입니다. 모든 프로토콜 구현이 공유하는 최소한의 연산 집합을 제공합니다.
주요 연산:
send(std::span<const std::byte>)-- 원격 엔드포인트에 원시 데이터 전송is_connected()-- 연결 상태 확인id()-- 고유 전송 식별자 반환remote_endpoint()/local_endpoint()-- 엔드포인트 정보 반환
헤더: <kcenon/network/detail/unified/i_connection.h>
i_transport를 연결 수명 주기 연산으로 확장합니다. 클라이언트 시작 연결과 서버 수락 연결 모두를 나타냅니다.
주요 연산:
connect(endpoint_info)/connect(url)-- 원격 엔드포인트에 연결close()-- 정상 종료set_callbacks(connection_callbacks)-- 이벤트 핸들러 등록 (on_connected, on_data, on_disconnected, on_error)set_options(connection_options)-- 타임아웃, 킵얼라이브, no-delay 설정is_connecting()/wait_for_stop()-- 상태 조회
헤더: <kcenon/network/detail/unified/i_listener.h>
수신 연결을 대기하는 서버 측 컴포넌트를 나타냅니다.
주요 연산:
start(endpoint_info)/start(port)-- 바인드 및 수신 대기stop()-- 수신 중단 및 모든 활성 연결 종료set_callbacks(listener_callbacks)-- 이벤트 핸들러 등록 (on_accept, on_data, on_disconnect, on_error)send_to(connection_id, data)-- 특정 연결에 전송broadcast(data)-- 모든 연결된 클라이언트에 전송connection_count()-- 활성 연결 수 반환
헤더: <kcenon/network/detail/unified/types.h>
| 타입 | 용도 |
|---|---|
endpoint_info |
네트워크 엔드포인트 (호스트/포트 또는 URL) |
connection_callbacks |
연결 이벤트 콜백 구조체 |
listener_callbacks |
리스너/서버 이벤트 콜백 구조체 |
connection_options |
설정: 타임아웃, 킵얼라이브, no-delay |
#include <kcenon/network/detail/unified/i_connection.h>
using namespace kcenon::network::unified;
// 어떤 프로토콜 구현과도 작동
void send_message(i_transport& transport, std::span<const std::byte> data) {
if (!transport.is_connected()) {
return;
}
auto result = transport.send(data);
if (!result) {
std::cerr << "Send failed\n";
}
}다중 클라이언트를 지원하는 고성능 TCP 서버:
#include <kcenon/network/messaging_server.h>
// 서버 생성
MessagingServer server("0.0.0.0", 8080);
// 콜백 등록
server.on_client_connected([](session_id id) {
std::cout << "클라이언트 연결됨: " << id << std::endl;
});
server.on_client_disconnected([](session_id id) {
std::cout << "클라이언트 연결 해제됨: " << id << std::endl;
});
server.on_message_received([](session_id id, const message& msg) {
std::cout << "메시지 수신: " << msg.to_string() << std::endl;
// 응답 처리
});
// 서버 시작
server.start();
// 특정 클라이언트에 메시지 전송
server.send(client_id, response_message);
// 모든 클라이언트에 브로드캐스트
server.broadcast(broadcast_message);
// 서버 종료
server.stop();// 상세 옵션으로 서버 생성
MessagingServer server("0.0.0.0", 8080, {
.io_threads = 4, // I/O 스레드 수
.max_connections = 10000, // 최대 동시 연결
.connection_timeout = std::chrono::seconds(30),
.keep_alive_interval = std::chrono::seconds(10),
.receive_buffer_size = 64 * 1024, // 64KB
.send_buffer_size = 64 * 1024,
.enable_tcp_nodelay = true, // Nagle 알고리즘 비활성화
.enable_keep_alive = true
});서버에 연결하는 TCP 클라이언트:
#include <kcenon/network/messaging_client.h>
// 클라이언트 생성
MessagingClient client("server.example.com", 8080);
// 콜백 등록
client.on_connected([]() {
std::cout << "서버에 연결됨" << std::endl;
});
client.on_disconnected([]() {
std::cout << "서버와 연결 해제됨" << std::endl;
});
client.on_message_received([](const message& msg) {
std::cout << "메시지 수신: " << msg.to_string() << std::endl;
});
// 연결
auto result = client.connect();
if (!result) {
std::cerr << "연결 실패: " << result.error().message << std::endl;
return;
}
// 메시지 전송
client.send(request_message);
// 동기 요청-응답
auto response = client.request(request_message, std::chrono::seconds(5));
if (response) {
std::cout << "응답: " << response->to_string() << std::endl;
}
// 연결 해제
client.disconnect();// 자동 재연결 활성화
MessagingClient client("server.example.com", 8080, {
.auto_reconnect = true,
.reconnect_interval = std::chrono::seconds(5),
.max_reconnect_attempts = 10,
.reconnect_backoff_multiplier = 2.0 // 지수 백오프
});
// 수동 재연결
if (!client.is_connected()) {
client.reconnect();
}연결 요청 → 세션 생성 → 활성 상태 → 연결 해제 → 세션 정리
│ │ │ │ │
├── 실패 ──►│ │ │ │
│ ├── 타임아웃 ──────────►│ │
│ │ ├── 클라이언트 종료 ──►│
│ │ ├── 서버 종료 ────────►│
│ │ └── 오류 ────────────►│
server.on_client_connected([&server](session_id id) {
// 세션 정보 조회
auto session_info = server.get_session_info(id);
if (session_info) {
std::cout << "원격 주소: " << session_info->remote_address << std::endl;
std::cout << "연결 시간: " << session_info->connected_at << std::endl;
}
});
// 모든 활성 세션 조회
auto sessions = server.get_active_sessions();
for (const auto& session : sessions) {
std::cout << "세션 " << session.id << ": " << session.remote_address << std::endl;
}// 특정 세션 연결 해제
server.disconnect_session(session_id);
// 조건부 연결 해제
server.disconnect_if([](const session_info& info) {
return info.idle_time() > std::chrono::minutes(30);
});
// 세션 속성 설정
server.set_session_attribute(session_id, "user_id", user_id);
auto user_id = server.get_session_attribute<std::string>(session_id, "user_id");#include <kcenon/network/message.h>
// 메시지 생성
message msg;
msg.set_type(message_type::request);
msg.set_id(generate_message_id());
msg.set_payload(container_data);
// 메시지 직렬화
auto bytes = msg.serialize();
// 메시지 역직렬화
auto parsed = message::deserialize(bytes);
if (parsed) {
auto& msg = parsed.value();
std::cout << "타입: " << static_cast<int>(msg.type()) << std::endl;
std::cout << "페이로드: " << msg.payload().to_string() << std::endl;
}enum class message_type : uint8_t {
request = 0, // 요청 메시지
response = 1, // 응답 메시지
notification = 2, // 단방향 알림
heartbeat = 3, // 연결 유지 신호
error = 4 // 오류 메시지
};┌─────────────────────────────────────────────────────┐
│ 메시지 프레임 │
├──────────┬──────────┬──────────┬───────────────────┤
│ 길이 (4) │ 타입 (1) │ ID (8) │ 페이로드 (가변) │
└──────────┴──────────┴──────────┴───────────────────┘
#include <kcenon/network/pipeline.h>
// 제로 카피 버퍼로 수신
server.on_message_received([](session_id id, span<const uint8_t> buffer) {
// 버퍼는 복사 없이 직접 참조
process_data(buffer);
});
// 제로 카피로 전송
auto buffer = acquire_send_buffer();
fill_buffer(buffer);
server.send_zero_copy(client_id, std::move(buffer));#include <kcenon/network/buffer_pool.h>
// 버퍼 풀 생성
buffer_pool pool(1024, 1000); // 1KB 버퍼 1000개
// 버퍼 획득
auto buffer = pool.acquire();
// 사용...
pool.release(std::move(buffer));
// RAII 스타일
{
auto scoped_buffer = pool.acquire_scoped();
// 스코프 종료 시 자동 반환
}// 최적의 I/O 모델 자동 선택
// - Linux: epoll
// - macOS: kqueue
// - Windows: IOCP
MessagingServer server("0.0.0.0", 8080, {
.io_model = io_model::automatic, // 자동 선택
.io_threads = std::thread::hardware_concurrency()
});#include <kcenon/network/tls_config.h>
// TLS 서버 구성
tls_config server_tls {
.certificate_file = "/path/to/server.crt",
.private_key_file = "/path/to/server.key",
.ca_file = "/path/to/ca.crt",
.verify_mode = tls_verify_mode::peer,
.min_protocol_version = tls_version::tls_1_2
};
MessagingServer secure_server("0.0.0.0", 8443, {
.tls = server_tls
});
// TLS 클라이언트 구성
tls_config client_tls {
.ca_file = "/path/to/ca.crt",
.verify_mode = tls_verify_mode::peer,
.verify_hostname = true
};
MessagingClient secure_client("server.example.com", 8443, {
.tls = client_tls
});// 커스텀 인증 핸들러
server.set_auth_handler([](const auth_request& req) -> auth_result {
// API 키 검증
if (validate_api_key(req.api_key)) {
return auth_result::success(user_info);
}
return auth_result::failure("잘못된 API 키");
});
// 클라이언트 인증
client.authenticate({
.api_key = "my-api-key",
.metadata = {{"client_version", "1.0.0"}}
});#include <kcenon/network/rate_limiter.h>
// 속도 제한 설정
server.set_rate_limiter(create_rate_limiter({
.requests_per_second = 1000,
.burst_size = 100,
.per_client = true
}));#include <kcenon/network/integration/thread_integration.h>
// 스레드 풀 공유
auto pool = create_thread_pool(8);
MessagingServer server("0.0.0.0", 8080, {
.thread_pool = pool
});
// 콜백이 스레드 풀에서 실행됨
server.on_message_received([](session_id id, const message& msg) {
// 자동으로 스레드 풀에서 실행
process_message(msg);
});#include <kcenon/network/integration/container_integration.h>
// 컨테이너를 메시지로 직접 전송
container data;
data.set("action", "update");
data.set("value", 42);
server.send_container(client_id, data);
// 컨테이너로 수신
server.on_container_received([](session_id id, const container& data) {
auto action = data.get<std::string>("action");
auto value = data.get<int>("value");
});#include <kcenon/network/integration/logger_integration.h>
// 로거 연결
auto logger = create_logger("network");
server.set_logger(logger);
// 자동 로깅
// - 연결/연결 해제 이벤트
// - 오류 및 경고
// - 성능 메트릭 (옵션)#include <kcenon/network/integration/monitoring_integration.h>
// 메트릭 수집기 연결
auto metrics = create_metrics_collector();
server.set_metrics_collector(metrics);
// 수집되는 메트릭:
// - network_connections_active
// - network_bytes_received_total
// - network_bytes_sent_total
// - network_messages_received_total
// - network_messages_sent_total
// - network_request_duration_seconds| 시나리오 | 처리량 | 지연시간 (p50) | 지연시간 (p99) |
|---|---|---|---|
| 작은 메시지 (64B) | 500K msg/s | 0.5μs | 2μs |
| 중간 메시지 (1KB) | 305K msg/s | 0.8μs | 3μs |
| 큰 메시지 (64KB) | 50K msg/s | 10μs | 50μs |
| 메트릭 | 값 |
|---|---|
| 최대 동시 연결 | 100K+ |
| 연결 설정 시간 | < 1ms |
| 연결 해제 시간 | < 500μs |
| 연결 수 | CPU 사용 | 메모리 사용 |
|---|---|---|
| 1,000 | 5% | 50MB |
| 10,000 | 15% | 200MB |
| 100,000 | 40% | 1.5GB |
- MessagingServer: 스레드 안전 (콜백은 스레드 풀에서 실행)
- MessagingClient: 스레드 안전 (내부 동기화)
- message: 불변 (공유 안전)
- 연결 재사용: 빈번한 연결/해제 피하기
- 배치 처리: 작은 메시지는 배치로 전송
- 버퍼 크기 조정: 워크로드에 맞게 버퍼 크기 조정
- TCP_NODELAY: 저지연이 필요한 경우 활성화
최종 업데이트: 2026-02-08 버전: 0.2.0
Made with ❤️ by 🍀☀🌕🌥 🌊