시리즈: AI와 함께 코딩 배우기

Visual Studio 2026이 우리 코드를 싫어했던 주말

이백 개의 MSVC 2026 오류에서 첫 그린 x64 빌드까지.

200개 오류에서 그린 빌드까지 첫 성공한 x64 빌드, PR 열두 개, 이틀 Windows 매크로 충돌 UTF-8 BOM 소스 파일 더 이상 사용되지 않는 CRT API DLL export 매크로 C2491 / 누락된 include PR 12개 build: first successful x64 build Linux + macOS + Windows MSVC 2026 commit f35f78bd
여섯 개의 오류 클래스, 열두 번의 에이전트 주도 스윕, 세 개의 플랫폼 그린.

크로스플랫폼은 모든 플랫폼에서 빌드가 그린이 되고 나서야 할 수 있는 약속이다. 이번 주말 RakuAI는 Windows에서 그것을 실현시켰다. 그리고 당신의 C++ 코드베이스도 부딪히게 될 여섯 가지 오류에 대한 플레이북이다.

시니어 엔지니어와 주니어 엔지니어의 차이는, 시니어 엔지니어는 시작하기도 전에 컴파일러와 한판 붙을 거라는 걸 안다는 것이라는 오래된 농담이 있다. 이번 주말은 컴파일러와의 한판이었다. 그 컴파일러는 Visual Studio 2026 Insiders에 실려 나오는 Microsoft Visual C++이었다. 코드베이스는 Raku였다. 그 싸움은 주말 이틀 내내, 그리고 평일의 몇 번의 늦은 밤 세션에까지 이어졌다. 코드베이스가 이겼지만, 아슬아슬했다.

이것을 기록해두고 싶은데, 공개 엔지니어링 로그에는 일이 잘 풀리지 않은 날들도 포함되어야 하기 때문이고, 또 에이전트들과 내가 이것을 헤쳐나간 방식이 다른 사람들의 의견이 진심으로 궁금한 워크플로의 부분이기 때문이다.

배경

이번 주말까지 이 런타임은 Linux에서 GCC로, macOS에서 Clang으로 깔끔하게 빌드되었다. 이 둘이 내 주된 주말 개발 환경이었다. 10월 초기 착수 이후로는 실제로 Windows MSVC 빌드를 시도해본 적이 없었다. 이 런타임은 크로스플랫폼이어야 한다. 크로스플랫폼은 Windows를 뜻한다. 그래서 토요일 아침 나는 Visual Studio 2026 Insiders가 설치된 Windows 머신에서 레포를 체크아웃하고 빌드를 실행했다.

빌드되지 않았다. 거의 근처도 못 갔다. 첫 컴파일 패스는 이백 개가 넘는 오류와 그에 상응하는 수의 경고를 만들어냈다. 오류들은 대략 여섯 개의 카테고리로 나뉘었고, 각각이 자체 PR이 되었다.

그 카테고리들이 무엇이었나

각각을 설명할 가치가 있는데, 각각이 새로운 MSVC 버전을 처음 만난 어떤 C++ 코드베이스든 부딪히게 되는 종류의 것이기 때문이다. 다른 팀들도 이것들에 부딪힐 것이다. 일부는 이미 부딪히고 있을 수도 있다.

하나: 우리의 네임스페이스를 오염시키는 Windows 매크로들. Windows 헤더는 합리적인 열거형 이름, 함수 이름, 템플릿 특수화와 충돌하는 여러 일반적인 이름(min, max, DOMAIN, HULL, ERROR, OK, NEAR, FAR)을 #define한다. 우리의 로깅 C API에는 ERROR라는 열거형 값이 있었다. Windows도 ERROR를 매크로로 정의해두었다. 컴파일러는 스펙이 하라는 대로 정확히 했는데, 그것은 매크로를 확장해서 알아볼 수 없는 코드를 만드는 것이었다. 해결책은 우리 헤더 전에 촘촘히 범위를 좁혀서 #undef ERROR를 하는 것이었다. 다른 것들도 마찬가지였다.

둘: MSVC가 컴파일을 거부한 BOM 표시 소스 파일들. 우리의 일부 소스 파일 맨 위에 UTF-8 바이트 순서 표시(BOM)가 있었는데, 대부분의 컴파일러는 이것을 눈감아주지만 MSVC 2026은 그러지 않는다. 에이전트는 레포의 모든 C/C++ 소스 파일에서 BOM을 제거하는 스윕을 착지시켰다.

셋: 더 이상 사용되지 않는 CRT API들. C 표준이 문제없다고 여기는 여러 표준 C 함수들이 MSVC에서는 “더 이상 사용되지 않음, 보안 변형을 사용하라”고 표시된다. sscanfsscanf_s가 된다. strncpystrncpy_s가 된다. 에이전트는 이를 훑어서 호출을 보안 변형으로 교체하거나, 보안 변형이 우리가 원하지 않는 방식으로 시맨틱을 바꿔버릴 곳에서는 적절한 _CRT_SECURE_NO_WARNINGS 프래그마로 감쌌다.

넷: DLL export 매크로. 가장 큰 것이었다. 모든 DLL의 모든 공개 심볼은 DLL을 빌드할 때는 __declspec(dllexport)로, 다른 DLL에서 그것을 소비할 때는 __declspec(dllimport)로 표시되어야 한다. Linux GCC와 macOS Clang은 이것이 필요 없다. MSVC는 필요하고, 우리 코드베이스에는 매크로가 누락되거나, 일관성 없이 적용되거나, 컴파일러가 실제로 export하기를 원하지 않는 템플릿 특수화에 우발적으로 적용된 경우가 많았다. 해결책은 모든 공개 API 헤더에 걸쳐 export 매크로를 정규화하고 누락된 곳에 추가하는 스윕이었다.

다섯: RAKU_API와 통합된 DLL들. 조금 더 이상한 것이었다. 우리 내부 CMake 설정 중 일부가 export해서는 안 되는 정적 라이브러리에까지 컴파일 시점에 -DRAKU_API=__declspec(dllexport)를 주입하고 있었다. 곳곳에서 MSVC C2491 오류가 났다. 해결책은 정적 타깃에 대해서는 RAKU_API를 명시적으로 정의 해제하고 동적 타깃에 대해서만 설정하는 CMake 세니타이저였다.

여섯: OpenXR 헤더와 <array>. 소수의 MSVC 컴파일이 실패했는데, <array>가 명시적으로 include되지 않은 채 사용되고 있었기 때문이다. GCC와 Clang은 다른 STL 헤더를 통해 전이적으로 그것을 include하는 경향이 있다. MSVC는 그러지 않으며, “사용하는 것을 include하라”가 어쨌든 옳은 답이다. 에이전트는 누락된 include를 추가했다.

주말이 어떻게 흘러갔나

토요일 아침은 대부분 각 오류 클래스를 재현하고 진단 노트를 작성하는 데 썼다. 에이전트들 앞에는 Windows VM이 없다. 나는 빌드 출력을 캡처하고, 정리하고, 명확한 요청과 함께 에이전트에게 다시 넘겨야 했다. “여기 오류 클래스가 있다, 여기 하나의 대표적인 예시가 있다, 여기 그것이 사는 파일이 있다, 이 클래스의 모든 인스턴스를 고치는 스윕을 제안하라.”

에이전트들은 이 스윕들을 깔끔하게 처리했다. PR #408은 logging.cpp의 Windows 매크로 충돌을 고쳤다. PR #406은 MSVC 열거형 재정의를 고쳤다. PR #404는 RAKU_API 매크로를 위한 CMake 세니타이저를 추가했다. PR #408(arvr_demo_telemetry의 또 다른 것)은 Windows DLL export 오류를 고쳤다. PR #411은 MSVC 2026 DLL 링키지 오류와 더 이상 사용되지 않음 경고를 고쳤다. PR #413은 BOM을 제거하고 더 이상 사용되지 않는 API를 교체했다. PR #415는 정적 라이브러리에 RAKU_RUNTIME_EXPORTS를 추가해서 C2491 오류를 고쳤다. PR #416은 헤더 전용 OpenXR fetch로 CMake 빌드를 고치고 누락된 런타임 소스를 추가했다. PR #401은 Windows DLL export 매크로를 고치고 이제는 낡은 MSVC 우회책을 제거했다.

이틀 동안 대략 열두 개의 PR. 각각은 런타임 레포의 #404–#416 아래에 문서화되어 있다.

토요일 오후가 가장 긴 구간이었다. DLL export 정규화는 엔진의 모든 공개 API 헤더를 읽고 어떤 심볼이 진짜 공개 표면의 일부인지 결정해야 했다. 그중 일부는 그렇지 않은 것으로 드러났다. 이 작업의 일환으로 몇 개는 내부용으로 강등되었는데, 범위가 늘어나기는 했지만 순전히 좋은 일이었다.

일요일은 vcpkg와 OpenXR SDK 통합을 갖춘 Windows MSVC CI 워크플로에 들어가서, 이런 일이 다시는 조용히 일어나지 않도록 했다. 이제 모든 푸시가 MSVC 빌드를 트리거한다. 빌드는 누군가가 CI에서 그것을 보지 않고서는 퇴행할 수 없다.

일요일 끝자락은 축하의 시간이었다. 밤에 노트북을 닫을 즈음, 빌드는 Windows에서 그린이 되었다. 이 런타임 역사상 첫 성공한 x64 빌드였다. 커밋 메시지는 정확히 그렇게 적혀 있다. build: first successful x64 build with OpenXR handle fixes. 커밋 해시는 f35f78bd이고, 지금까지 이 프로젝트에서 내가 가장 좋아하는 커밋 중 하나다.

무엇이 잘 되었나, 무엇을 다르게 했을 것인가

몇 가지 솔직한 노트다.

새 플랫폼을 늦게 온라인에 올리는 것은 비용이 크다. 코드베이스가 더 작았을 때 몇 주 전에 MSVC 빌드를 실행해봤어야 했다. 그 규모에서의 오류는 이백 개가 아니라 스무 개였을 것이다. 스무 개의 오류를 고치는 비용은 이백 개의 오류를 고치는 비용보다 의미 있게 작다. 교훈은 타깃 플랫폼이 두어 번의 주말 이상 빌드되지 않은 채로 방치되게 두지 말라는 것이다.

고치는 작업이 기계적일 때는 에이전트 주도 스윕이 옳은 답이다. DLL export 스윕, BOM 제거, 더 이상 사용되지 않는 CRT 교체, 이 모두는 정확히 에이전트가 사람보다 더 빠르고 더 일관되게 하는 종류의 작업이었다. 나는 각각을 “패턴 X의 모든 인스턴스를 찾아서 변환 Y를 적용하고, 나머지는 건드리지 마라”로 프레이밍했고, 에이전트는 정확히 그렇게 했다.

고치는 작업이 판단을 요구할 때는 에이전트 주도 스윕이 틀린 답이다. RAKU_API 매크로 문제는 어떤 CMake 타깃이 실제로 export를 원하고 어떤 것이 원하지 않는지 결정해야 했다. 그것은 스윕이 아니었다. 그것은 신중한, 타깃별 리뷰였다. 나는 그것을 손수 처리했고, 에이전트는 각 결정에 대한 두 번째 시선 역할을 했지, 실행자 역할을 하지 않았다.

한 모델이 다른 모델이 작성한 버그를 잡아냈다. 더 이상 사용되지 않는 CRT 교체 스윕 도중, 한 에이전트가 sprintfsprintf_s로 교체했는데, 버퍼 크기 시맨틱이 호출 지점이 예상했던 것과 미묘하게 달랐던 곳이었다. 그 PR은 착지되었다. 다른 모델의 리뷰 패스가 그것이 출시되기 전에 그 불일치를 잡아냈다. 멀티 벤더 리뷰 워크플로가 이번 주말 특히 제 몫을 했다.

파트너와 빌더들이 이 글에서 가져갈 것

이 엔진이 Windows에 출시되는지 궁금한 파트너라면, 일요일 밤 기준으로 답은 그렇다이다. MSVC 빌드는 그린이다. CI는 앞으로 그것을 그린으로 유지한다.

자신의 크로스플랫폼 C++ 코드베이스에서 작업 중이고 Visual Studio 2026 Insiders를 처음 시도해보려는 개발자라면, 위의 여섯 카테고리가 당신에게 닥칠 것들이다. 대부분을 미리 막을 수 있다. 이제 당신도 안다.

이 글을 읽는 MSVC 팀 관계자라면, 그 팀은 2026 Insiders에서 좋은 작업을 했다. 경고들은 정말로 유용하고 새 툴링은 2022보다 낫다. 호환성 손상은 대부분 타당한 이유가 있다. 시간이 더 있었다면 버그 리포트를 몇 개 냈을 것이다. 곧 낼 것이다.

일요일 밤, 이 엔진은 세 개의 플랫폼에서 깔끔하게 빌드된다. 월요일을 그것과 함께 맞이하는 것이 옳은 일이다.

하나의 런타임, 당신의 글래스가 출시되는 모든 플랫폼

RakuAI는 Linux, macOS, Windows MSVC 2026에서 깔끔하게 빌드된다. 스마트 글래스 제조사가 진짜 공간 경험을 출시하는 데 필요한 크로스플랫폼 토대다. 이 엔진이 당신의 하드웨어를 어떻게 타깃하는지 확인해 보라.

← 전체 글