목표: IOCP(Windows) 서버를 IOCP + epoll(Linux) 크로스플랫폼으로 전환

결정 사항

항목 선택 이유
리눅스 환경 WSL2 Win10에서 무료·즉시 빌드/실행, 마찰 최소
빌드 시스템 CMake 완전 이전 양 플랫폼 단일 빌드. MSVC .vcxproj는 리눅스 빌드 불가
네트워크 추상화 NetIoModel 컴파일타임 별칭(using) 게임로직이 OS를 모름 · vtable 비용 0 · 플랫폼 선택을 한 곳에 격리
백엔드 선택 방식 CMake가 플랫폼별 소스 컴파일 반대편 코드는 바이너리에 아예 미포함(런타임 분기·비용 0)
모델 가시성 부팅 로그 I/O model: X 실행 시 어느 모델인지 한눈에 확인

진행 방식 (5단계)

A. CMake 이전 → B. 코어/네트워크 분리(탈Windows화) → C. 코어 리눅스 빌드 → D. epoll 백엔드 구현 → E. 수렴·문서화

(Windows IOCP 서버는 전 과정 동작 유지)

진행 현황 (2026-07-20)

<aside> 🌿

아래 ✅/🔵 완료 항목은 브랜치 feat/cmake-netiomodel 산출물이다. main에는 미병합(CMakeLists·Platform.h·CIniFile 부재) — main 대조로는 확인되지 않으니 브랜치 기준으로 볼 것.

단계 상태
A. CMake 이전 ✅ 완료
B. 탈Windows화 (코어/네트워크 분리) 🔵 거의 완료 (LockFree만 남음)
C. 코어 리눅스 빌드 ⬜ 대기
D. epoll 백엔드 구현 ⬜ 대기
E. 수렴·문서화 ⬜ 대기

각 단계마다 Windows Release 빌드로 동작 불변을 검증하며 진행.

B단계 완료 내역 — 비-소켓 Windows 의존 격리

소켓/IOCP층은 이미 CIOCPServer 뒤로 격리돼 있어 epoll이 교체. 진짜 작업은 전 파일에 새어있던 비-소켓 Windows 의존을 걷어내는 것.

항목 방식 핵심
Platform seam (Platform.h) OS 호출을 얇은 함수로 통합, impl 내부 #ifdef 타이머·affinity·시그널·exe경로·스레드CPU
INI 로더 GetPrivateProfile* → 자체 파서 CIniFile 값이 전부 ASCII라 인코딩 무해석
크래시 덤프 원본 SEH+MiniDump를 #ifdef로 보존 + Linux(sigaction+backtrace) 통합 불가 → 둘 다 살림
CPU 측정 GetThreadTimes → Platform::ThreadCpuHandle Win=핸들+GetThreadTimes / Linux=clock_gettime
affinity·종료시그널 SetProcessAffinityMask·SetConsoleCtrlHandler → Platform Linux=sched_setaffinity·sigaction
타이머·로거·DB Sleep→sleep_for / localtime_r / winsock #ifdef 자명 치환
Interlocked→std::atomic 통계=Counter(relaxed) · refcount=atomic(seq_cst) ↓ 아래 T1/T2/T3
모니터·SerialBuffer LONG64→int64_t · WriteCounter by-value · refcount atomic Windows 타입 제거

핵심 기술 결정

통합(포터블 하나) vs #ifdef(원본 보존)

판단 기준: 양 OS에서 도는 포터블 코드 하나로 쓸 수 있나?

크고 검증된 백엔드는 병렬 파일(NetIoModel)로 원본 0-diff 보존. 자잘한 공유코드만 인플레이스 치환.

Interlocked → std::atomic : T1/T2/T3 위험도 분류 (총 ~124곳)

티어 대상 위험 포팅
T1 통계 카운터 (~70) 패킷수·구간시간 등 지표 낮음 (동기화 무관) atomic • relaxed
T2 세션 상태 (~28) _ioCount·refcount·_sending 높음 (동시성 정합) atomic • seq_cst
T3 LockFree DCAS (~19) InterlockedCompareExchange128 최난이도 뮤텍스 폴백(회피)

relaxed vs seq_cst — 왜 T2는 그냥 seq_cst인가

Counter 캡슐화 + 컴파일러 주도 검증

남은 작업

# 작업 비고
B 잔여 T3 LockFree (DCAS) SerialBuffer·TimingWheel의 마지막 Linux 관문. 뮤텍스 폴백
B 잔여 SerialBuffer 타입 (BYTE/WORD/DWORD) T3 후. DWORD→uint32_t 오버로드 주의
C 코어 리눅스 빌드 (WSL2 + CMake) A·B 후 실빌드 검증
D epoll 백엔드 EpollServer 신규. 세션상태 atomics(_ioCount 등) 여기서 해소. byte order도

이어가기 (다음 세션 진입점)

관례(운영): 새 소스는 UTF-8 BOM + LF · 변경 검증은 Release 빌드 먼저 · 커밋 메시지 한글은 -F 파일(셸 -m 잘림) · 통계=Counter(relaxed) / 세션상태=atomic(seq_cst).

</aside>