WONMOCK LEE / GRAPHICS ENGINEER
01 / PROFILE

구조 짜는 걸
좋아하는 엔지니어

회사에서는 그래픽스 엔진을 만들고, 퇴근 후엔 몇 년째 C++ 엔진을 혼자 만드는 중. Entity-Component, Memory Pool, Reflection, Container — 전부 라이브러리 없이 밑바닥부터 직접 짰고, 저장소와 이슈도 다 공개해둠. 남이 만든 걸 갖다 쓰기만 해서는 왜 그렇게 동작하는지 절반밖에 못 배운다고 생각함.

서울, KR 그래픽스 / 렌더링 새 도전 환영
4만줄
C++ 코드 — 엔진 3.0만 · 라이브러리 6개 0.95만 (공백 줄 제외)
424커밋
저장소 7개 · PR 146개 · 2023.03부터
22FPS
100만 Instance(Release) — 병목 추적으로 5.4 → 22
25/ 26건
2026.08 전체 코드 리뷰로 찾은 버그 — 6일 만에 수정
02 / WORK

엔진 하나, 라이브러리 여섯

Game-Engine개발 중 2023.03 시작 · 2025.12 재시작 · 커밋 138 · C++ 3.0만 줄
THREAD  Main(Win32) · World · Render · RHI · Asset(+Task ×4)
git submodule로 조립 · 아래 계층으로만 의존
  1. Entity는 ID, 데이터는 Component, System이 쓸 Component 조합은 Node가 묶는 구조. 실행 순서는 사람이 짠 목록이 아니라 의존성 Graph의 위상정렬이 정함.

    • Sparse Set · Archetype 대신 Node데이터 이동 · 복제 없이 System별 Component 조합 선언
    • Registry<Base> 하나로 통합Manager 5개 + Interface 6개를 걷어내고 생성 · 조회 · 삭제를 범용 Registry로
    • 엔진 RenderGraph의 기반RenderGraph가 ECS::Graph를 상속해서 Pass 순서를 정함
    의존
    Memory · Reflection · Container · Log · CMake
    사용처
    Game-Engine
  2. Unreal GC를 참고한 Mark-and-Sweep. 상태 하나(Idle → Marking → Sweeping → Purging)로 Cycle을 돌리고, 객체 단위 편차가 큰 Purge만 시간 예산을 둬서 여러 프레임에 나눠 실행함.

    • 시간 예산 기반 Purge한 번에 못 끝내면 다음 Collect()가 그 지점부터 이어감 — Frame-time Spike 방지
    • Compaction 대신 버킷 점유율 할당Accessor가 인스턴스 헤더에 붙어 있어 이동 불가 — 가장 꽉 찬 버킷부터 채워 단편화 관리
    • ObjectPtr · RootPtr · RefPtr비활성 Handle · GC Root · 참조 카운트, 용도별 Pointer 3종
    의존
    Reflection · Container · Log · CMake
    사용처
    ECS · Game-Engine
  3. GENERATE · PROPERTY · METHOD 매크로로 타입 · 멤버 · Method를 컴파일 타임에 등록. Unreal의 UHT 같은 코드 생성기 없이 Macro와 Template만 사용함.

    • dynamic_cast 없는 Cast<T>단일 상속 체인만 지원 — 체인을 따라 올라가는 것으로 다운캐스트 판정
    • 힙 할당 없는 Container 순회64바이트 SBO Iterator + 함수 Pointer 6개로 만든 수동 vtable
    • GC 도달 가능성 판정의 근거Memory의 GC가 PropertyInfo 목록을 따라가며 마킹
    의존
    Container · Log · CMake
    사용처
    Memory · ECS · Game-Engine
  4. STL 없이 만든 DynamicArray · HashMap/HashSet · List · RTree와 그 아래 할당기(Arena · LinearArena · TLSFArena). Allocator를 Template 인자로 분리해서 자료구조와 메모리 전략을 따로 바꿀 수 있음.

    • Robin Hood HashMap100만 개 기준 std::unordered_map 대비 삽입 1.72배 · 조회 1.26배
    • TLSFArena — O(1) 할당 · 해제 · 병합FL/SL Bitmap 탐색, 엔진의 VulkanMemory가 그대로 상속
    • tombstone 없는 삭제backward-shift로 빈 칸을 물리적으로 없애서 조기 종료 규칙 유지
    의존
    Log · CMake
    사용처
    Reflection · Memory · ECS · Game-Engine
  5. printf식 C 스타일 로그를 LOGINFO() << ... 스트림 스타일로 바꾼 로거. CMake를 뺀 나머지 저장소 전부와 엔진이 이 로거를 씀.

    • C++ 스트림 스타일 매크로2025.01 C 스타일에서 전환 — 태그 v1.0 → v3.0
    • LogType별 저장 · 개수 제한2024.12 — 레벨별로 따로 쌓고 보관 개수를 제한
    • 플랫폼별 콘솔 분리Windows · Linux를 LogPlatform으로 분리(2025.03)
    의존
    CMake
    사용처
    Container · Reflection · Memory · ECS · Game-Engine
  6. 6개 저장소가 같은 규칙으로 빌드되도록 뽑아낸 공통 CMake 함수 모음. 각 저장소가 git submodule로 포함해서 씀.

    • project_optionsC++17 + 컴파일러별 옵션(MSVC /Zi /MP, GCC · Clang -Wall -Wextra) 통일
    • create_library · install_librarySTATIC · SHARED · MODULE · INTERFACE 라이브러리 생성과 헤더 설치
    • add_external_librarygit 저장소를 ExternalProject로 받아 플랫폼별 라이브러리 이름 · 확장자로 연결
    의존
    없음
    사용처
    Log · Container · Reflection · Memory · ECS · Game-Engine

외부 — glad · glm · stb · imgui · yaml-cpp · Vulkan SDK(shaderc · SPIRV-Reflect)

라이브러리가 엔진 안에서 실제로 쓰이는 지점

RenderGraph : ECS::Graph ECS가 System 실행 순서를 정할 때 쓰는 위상정렬(Kahn)을 그대로 상속해서, Transform → Shadow → Geometry → Lighting → Debug Pass 순서를 정함.
VulkanArena : TLSFArena Container의 TLSF 할당기를 상속 — 4MB VkDeviceMemory 블록 안을 O(1)로 서브 할당함. 리소스마다 vkAllocateMemory를 부르지 않음.
RenderCommandList World Thread가 기록하는 람다를 Container의 LinearArena 두 개에 번갈아 placement-new — 프레임마다 Reset만 해서 힙 할당이 거의 없음.
PROPERTY → GC World의 Registry/Container 멤버를 Reflection의 PROPERTY로 등록 — Memory의 GC가 그 Property 목록을 따라가며 Entity · Component · Node의 도달 가능성을 마킹함.

각 상세 페이지 앞부분엔 구조와 설계 이유, 실제 커밋 기준 개발 히스토리를 정리해둠. 2026.08 전체 코드 리뷰에서 찾은 버그는 GitHub 이슈로 올린 뒤 대부분 바로 고쳤고, 페이지 안 "버그" 섹션에 원인과 함께 남겨둠.

03 / HISTORY

3년 반의 개발 히스토리

커밋 히트맵을 불러오는 중…

  1. 01DX11 엔진 → 라이브러리 분리2023.03 — 2023.10
  2. 02라이브러리 단발 개선2023.11 — 2025.09
  3. 03라이브러리 재작성 → 엔진 재시작2025.10 — 2025.12
  4. 04엔진 뼈대 — RHI · Proxy · 멀티스레드2026.01 — 2026.03
  5. 05렌더링 — Deferred · 100만 Instance · Shadow2026.04 — 2026.06
  6. 06Vulkan · RHI 재설계 · 전체 코드 리뷰2026.07 — 현재
  1. 01DX11 엔진 → 라이브러리 분리2023.03 — 2023.10
    엔진 안에서 막힌 문제를 독립 저장소로 분리
  2. 2023.03.23
    EngineDirectX 11 엔진 첫 커밋
    ImGui 에디터 레이어(파일 · 프로퍼티 브라우저)와 프로젝트 저장/불러오기까지 구현.
  3. 2023.05.13
    EngineComponentManager 재할당→ Pointer 무효화 문제
    vector가 재할당될 때마다 Component Pointer가 전부 무효화됨 — 6일 뒤 "memory pool" 아이디어 커밋으로 이어지고, 이게 라이브러리 분리의 출발점이 됨.
  4. 2023.05.20
    Memory · Log · ECS엔진에서 라이브러리 3개를 독립 저장소로 분리
    MemoryPool(05.20) → Log(05.31) → ECS(06.21) 순서. ECS는 SystemManager에 위상정렬을 넣는 데까지(09.02), Memory는 v4.x까지 진행.
  5. 02라이브러리 단발 개선2023.11 — 2025.09
    뜸한 커밋, 라이브러리 단위로 지속
  6. 2024.01.14
    ReflectionReflection 저장소 시작
    TypeCast부터 완성(2024.04) — 프로퍼티 등록보다 안전한 다운캐스트를 먼저 풂.
  7. 2025.01.27
    LogC 스타일 → C++ 스트림 스타일 Log로 전환
  8. 2025.03.31
    ContainerVariant 하나로 Container 저장소 시작
  9. 03라이브러리 재작성 → 엔진 재시작2025.10 — 2025.12
    커밋이 가장 몰린 구간 · 라이브러리 재작성 후 엔진 조립
  10. 2025.10.09
    CMake공통 CMake 저장소 분리
    Project · Library · ExternalProject 규칙을 한 곳에 모아 라이브러리 6개의 빌드 방식을 통일함.
  11. 2025.11.30
    MemoryMark-and-Sweep GC로 재작성
    옛 MemoryManager · MemoryPtr 구조를 걷어내고 Accessor · Collector · Pointer · Storage로 다시 짬. 순환 참조가 마킹을 무한 루프에 빠뜨리는 문제를 직접 겪고 IsMarked 가드로 수정(12.15).
  12. 2025.12.17
    ECSManager 5개 + Interface 6개 → Object · Registry · Graph
    전용 Manager를 전부 걷어내고 범용 Registry와 의존성 Graph로 교체한 통짜 재작성.
  13. 2025.12.18
    EngineDX11 코드 전부 제거OpenGL 기반으로 재시작
    라이브러리 6개를 git submodule로 조립하는 지금의 구조가 여기서 시작됨 (PR #1).
  14. 04엔진 뼈대RHI · Proxy · 멀티스레드2026.01 — 2026.03
  15. 2026.01.27
    EngineRHI / Proxy 기반 아키텍처
    파일 45개가 한 번에 바뀐 커밋 — World가 렌더 타입을 모르는 지금의 경계가 여기서 확립됨.
  16. 2026.02.21
    EngineWGL Context 소유권을 RHI Thread로 이전→ 멀티스레드 렌더링 첫 성공
  17. 2026.02.22
    EngineRHIFrameExecutor(프레임 링) / RHITaskExecutor(업로드) 분리
  18. 05렌더링Deferred · 100만 Instance · Shadow2026.04 — 2026.06
    엔진 커밋이 가장 많았던 석 달
  19. 2026.04.04
    EngineFrameGate 도입Thread 동기화와 프레임 데이터 보관의 분리
  20. 2026.04.17
    EngineMeshBatch Instancing + Normal Mapping
  21. 2026.05.21
    EngineRenderPass 아키텍처 + Deferred Rendering 완성
    임시방편이던 PipeLine 체계를 걷어내고 Pass 단위 구조로 전면 교체 (PR #28).
  22. 2026.05.24
    Engine100만 Instance 5.4 → 22 FPS
    이슈 #25 한 달 추적 — 스칼라 GLM 행렬 곱은 GPU Compute TRS(TransformPass)로, 프레임당 200만 번 돌던 HashSet 삽입은 Dirty 가드 하나로 정리. Release 기준.
  23. 2026.06.02
    EnginePoint · Spot LightPhong, GBuffer UInt 비트 패킹
  24. 2026.06.27
    EngineDirectional Shadow 안정화
    텍셀 스냅으로 시머링 제거(06.25), RPDB + Normal Offset + NaN-safe 분모로 acne · 깜빡임 해결(06.27).
  25. 06Vulkan · RHI 재설계 · 전체 코드 리뷰2026.07 — 현재
  26. 2026.07.09
    EngineVulkan 백엔드 착수
    06.30 Instance · Device 선택부터 시작해 Surface · Swapchain(07.09), Semaphore/Fence 프레임 루프(07.15), GLSL → SPIR-V + SPIRV-Reflect까지. 07.22부터 VulkanMemory가 Container의 TLSFArena(07.21 추가)로 4MB 블록을 서브 할당.
  27. 2026.08.02
    전체전체 저장소 코드 리뷰버그 26건 등록, 6일 만에 25건 수정
    엔진 9 · ECS 5 · Memory 4 · Container 6 · Reflection 2건을 이슈로 올리고 PR 9개로 병합. 남은 1건은 LightingPass Blending(#52).
  28. 2026.09.03
    EngineVulkan Buffer · Texture 경로 완성
    생성 · 초기화 · 갱신 · 리사이즈 책임 분리, Staging Buffer 풀, Buffer → Image 복사, Barrier.
  29. 2026.10.18
    EngineRHI 공용 계층 재설계
    RHISystem 파사드 + RHIContext(GL / Vulkan) 분리, 리소스별 Transition 상태 모델, 상수용 UBO Ring Buffer, GLSL 단일 소스(GL 4.6 · Vulkan 1.1). update/vulkan-rhi 브랜치에서 진행 중.
04 / CAREER

커리어

2024.01 —
현재
현대오토에버
그래픽스 엔진 개발팀 · Android (C++)
MVT Rendering Architecture 설계Paint/Layout 로직 분리
지도 벡터 타일(MVT)은 Layer 타입이 제각각이라 단일 Pipeline으로 다 받아내기가 어려웠음. Paint(스타일)와 Layout(지오메트리)을 분리하고 Layer 타입별(Fill·Line·Fill-Extrusion·Symbol) Pipeline을 따로 세운 다음, MVT Parser는 그 위에서 계속 재사용 가능하도록 만듦.
Style 타입별 VBO 통합→ Draw Call 90%+ 감소
레이어마다 VBO를 따로 그리다 보니 Style 종류가 늘 때마다 Draw Call도 같이 늘어났음. 같은 Style Type끼리는 VBO를 하나로 합쳐서 한 배치로 그리도록 바꿈.
Ear Clipping 동적 할당 제거Static Memory Pool로 Frame-time Spike 해결
Ear Clipping이 매 프레임 동적 할당을 일으켜서 스파이크가 났음. 정적 Memory Pool로 할당 방식 자체를 바꿔서 원인을 없앰.
glTF·KTX Pipeline 구축, KTX·ASTC 전환→ 로딩 성능 70~80%↑
기존 텍스처 포맷은 로딩 시간과 용량 둘 다 아까웠음. KTX·ASTC 압축 포맷으로 바꾸고, 그 김에 GPU 기반 Skinning Shader도 같이 붙임.
실시간 내비게이션용 Kotlin–C++ JNI Bridge · gRPC 통신 Layer 구현
Android 앱(Kotlin)과 엔진(C++)이 내비게이션 데이터를 실시간으로 주고받아야 해서, 그 사이를 JNI Bridge와 gRPC로 연결함.
커스텀 디버깅 툴 제작glTF·KTX Pipeline 사내 세미나 진행
2022.07 —
2023.03
LG전자
VS 사업부 · 인턴 → 정규직
Cinemo API·DLNA 기반 스마트폰-차량 콘텐츠 스트리밍 구현
차량 인포테인먼트에 스마트폰 화면을 미러링하는 기능을, Cinemo API와 DLNA 프로토콜로 붙임.
2021.08 —
2022.03
한양대학교 — CGR 연구실
학부 연구생
탄성 입자 기반 고무줄 시뮬레이션관절 참조 Animation 구현
물리 기반 캐릭터 Animation을 연구하면서, 탄성 입자 역학으로 고무줄을 시뮬레이션하고 관절 참조 데이터로 인체 움직임을 만듦.
05 / STACK

기술 스택

엔진 아키텍처 Multi-thread 렌더링(4-thread) · RHI 추상화 · Descriptor 기반 API · RenderPass + Proxy / MeshDrawCommand · ECS(Node · System · Graph) · Vulkan Barrier/Transition 모델
C++ 시스템 C++17/20 · 커스텀 Allocator(Pool · Array · LinearArena · TLSF) · Mark-and-Sweep GC · 런타임 Reflection (TMP/SFINAE) · STL-free Container(Robin Hood HashMap)
그래픽스 API OpenGL 4.6 / ES · Vulkan 1.1(백엔드 진행 중) · GLSL → SPIR-V(shaderc · SPIRV-Reflect) · RenderDoc · NSight Graphics
06 / RESUME

이력서

이원목 · Lee, Wonmock tot4766@gmail.com

학력

2019.02 – 2023.02한양대학교 — 기계공학 학사(주전공) · 전기·생체공학 학사(부전공) · 학점 3.75/4.5

수상

2021.07혁신상 — 멘토링 기반 AI 프로젝트 경진대회, 고려대학교
2022.05장려상 — 졸업작품 발표회, 한양대학교

병역

2017.01 – 2018.10육군 만기 전역

경력

2024.01 – 현재현대오토에버 — 그래픽스 엔진 개발팀, Android(C++)
2022.07 – 2023.03LG전자 — VS 사업부, 인턴 → 정규직
2021.08 – 2022.03한양대학교 — 학부 연구생, CGR 연구실