본문으로 건너뛰기
0
r/jeffnews HN 약 4분

Unity를 보고 드디어 C++ 코루틴이 왜 필요한지 이해했다

backend

요약

C++ 코루틴의 실용적 유스케이스를 Unity의 이펙트 시스템에서 발견. 복잡한 상태 머신을 단순한 함수로 변환하는 것이 코루틴의 핵심 가치이며, Unity 스타일 co_yield 핵으로 100줄 미만의 코루틴 실행기를 C++에서 구현하는 방법을 소개.

기사 전체 정리

"드디어 C++ 코루틴이 왜 필요한지 알겠다"

  • C++ 코루틴이 나온 지 6년인데, 프로덕션 코드에서 본 적이 있는 사람이 거의 없음. 이유가 두 가지: 저수준 보일러플레이트가 너무 많고, 피보나치 제너레이터 말고는 쓸만한 예제가 없었기 때문
  • 글쓴이가 Unity의 C# 코루틴을 보고 드디어 감이 옴. Unity에서는 코루틴으로 **이펙트나 일시적 동작(ephemeral behaviour)**을 구현하는데, 이게 진짜 실용적인 유스케이스임

코루틴이 빛나는 순간

  • 간단한 페이드아웃이야 람다로도 되지만, 여러 단계의 순차적 동작이 필요하면 얘기가 달라짐. 예: TimeWarp 이펙트처럼 이동 → 대기 → 이동 → 대기를 반복하는 경우
  • 이걸 코루틴 없이 C++로 짜면 수동 상태 머신이 됨. 상태 변수, 분기, 전환 로직... 코드 리뷰에서 통과시키고 싶지 않은 수준의 코드가 나옴
  • 코루틴을 쓰면? 상태 머신이 그냥 평범한 함수로 변환됨. "읽기 어려운 상태 머신을 매우 단순한 함수로 바꾸는 것", 이게 코루틴의 핵심 가치라는 거

Unity 스타일 핵으로 C++에서 구현하기

  • co_yield는 C++23의 <generator>로 비교적 쉬운데, co_await가 어려움. 뭘 기다리는지, 누가 깨워주는지, 어떤 실행 큐를 쓰는지... 답이 정해져 있지 않은 질문이 너무 많음
  • 글쓴이의 해결책: Unity가 10여 년 전에 쓴 것과 같은 핵을 씀. co_yield로 "다음 프레임까지 양보"를 표현하는 거. 의미론적으로는 맞지 않지만, 실용적으로는 완벽하게 동작함
  • 전체 코루틴 실행기 구현이 100줄도 안 됨. effects.add(TimeWarp(object))로 이펙트를 추가하고, 메인 루프에서 effects.run() 호출하면 끝

보너스: 사이드 이펙트 제거 → 병렬화

  • 한 발 더 나가면, co_yield로 렌더링 객체를 반환하게 만들어서 사이드 이펙트를 없앨 수 있음
  • 사이드 이펙트가 없으니 루프를 병렬로 돌릴 수도 있음. 게임 이펙트 시스템이 100줄 미만의 코드로 완성되는 거

ℹ️참고

> C++26에서 execution이 표준화되면 co_await를 제대로 쓸 수 있겠지만, 대부분의 프로젝트는 이미 자체 스케줄러와 스레드 풀이 있어서 통합이 쉽지 않을 전망. 당장 코루틴의 가치를 체감하고 싶다면 이 "Unity 핵"이 가장 현실적인 진입점임.

핵심 포인트

  • C++ 코루틴 6년차인데 프로덕션에서 본 사람이 거의 없음
  • Unity의 이펙트 코루틴이 실용적 유스케이스의 좋은 예시
  • co_await는 어렵지만 co_yield로 '다음 프레임까지 양보' 패턴은 쉽게 구현 가능
  • 전체 코루틴 실행기가 100줄 미만, 사이드 이펙트 제거 시 병렬화도 가능

인사이트

코루틴의 가치를 이론이 아니라 실무 관점에서 설명하는 좋은 글. co_await의 복잡함을 피하면서 co_yield로 바로 생산성을 얻는 접근이 현실적.

댓글

댓글

댓글을 불러오는 중...

backend

Redis 8.0 출시 — I/O 스레딩 갈아엎고 처리량 3배, 2.1M ops/sec 달성

Redis 8.0이 I/O 스레딩 모델을 완전히 재설계해서 16코어 기준 2.1M ops/sec를 달성함 (7.4 대비 3배). Hash field expiration, Vector search HNSW, Client-side caching v2, Redis Functions 2.0 async 실행 등 굵직한 기능이 추가되고, jemalloc 통합으로 메모리 fragmentation도 25% 줄어듦.

backend

Go 1.26의 타입 생성(Type Construction)과 순환 감지(Cycle Detection) 개선

Go 1.26에서 타입 체커의 타입 생성 알고리즘을 개선해 재귀 타입과 배열 크기 계산 시 발생하던 순환 감지 문제를 체계적으로 해결했다. 불완전한 값이 다운스트림으로 퍼지기 전에 업스트림에서 차단하는 새로운 접근법으로 여러 컴파일러 패닉을 수정.

backend

Cloudflare Gen 13 서버: 캐시를 코어로 바꿔 성능 2배 달성한 이야기

Cloudflare가 AMD Turin 9965(192코어) 기반 Gen 13 서버를 배포함. 코어당 L3 캐시가 6배 줄어 레거시 NGINX 스택(FL1)으로는 레이턴시 50% 악화가 불가피했으나, Rust로 전면 재작성한 FL2로 전환해 Gen 12 대비 처리량 2배, 성능/와트 50% 개선을 달성함.

backend

칩셋 레이턴시를 측정해봤더니 — 쓸모는 없지만 재밌는 실험

Vulkan GPU 벤치마크로 여러 세대 마더보드 칩셋의 PCIe 레이턴시를 측정한 실험. CPU 직결 대비 칩셋 경유 시 수백 ns 레이턴시가 추가되며, 의외로 2012년 Skylake Z170이 가장 낮은 추가 레이턴시를 보임.

backend

ForgeKV — Rust로 만든 멀티코어 Redis 대체제

Rust로 만든 Redis 드롭인 대체제. 64-샤드 잠금 아키텍처로 멀티코어 스케일링 지원. 2코어 환경에서 Redis 7 대비 41% 빠른 SET 처리량(158K ops/s). 고동시성에서는 약점 있음. Source-available 라이선스.