마이크로소프트, C# 메모리 안전성 러스트급으로 높인다
마이크로소프트가 C# 언어의 메모리 안전성을 높여 러스트에 준하도록 개선하겠다는 계획을 밝혔다.
마이크로소프트의 닷넷 제품 관리자 리처드 랜더는 지난 21일 개발자 블로그에서 “C#의 메모리 안전성을 대폭 개선하는 작업을 진행중”이라며 “언세이프(unsafe) 키워드를 재설계해 호출자에게 안전성 유지를 위해 이행해야 할 의무를 알리고, 새로운 안전성 주석 스타일을 통해 이를 문서화할 예정”이라고 발표했다.
그는 “이 키워드는 포인터 표시에서 더 나아가 컴파일러가 안전하다고 검증할 수 없는 방식으로 메모리와 상호작용하는 모든 코드에 적용될 것”이라며 “컴파일러는 언세이프 키워드가 안전하지 않은 연산을 캡슐화하는 데 사용되게 강제할 것”이라고 설명했다.
그는 “결과적으로 안전성 계약과 가정이 관례에 따라 암묵적으로 이뤄지는 대신 명확하게 드러나고 검토 가능해진다”고 덧붙였다.
C#의 새로운 모델과 구문은 내년말 출시될 닷넷11의 C# 16에서 미리보기 버전으로 적용되고, 장기지원(LTS) 버전인 닷넷12에서 정식 출시될 예정이다. 변경사항은 초기에 선택 사항으로 도입됐다가 추후 기본값으로 변경될 것으로 전망된다. 널(null) 허용 참조 형식처럼 템플릿을 업데이트해 새 모델을 활성화하며, 초기 컴파일러 구현은 메인 브랜치에 병합돼 개발중이라고 그는 설명했다.
언세이프 구문은 C# 1.0부터 존재한 기능이지만, 많이 사용되지는 않았다. C# 코드에서 직접 메모리를 다루는 로레벨 작업을 허용하는 기능이다. 언세이프 키워드를 이용하면 포인터를 사용할 수 있고, 메모리 주소에 직접 접근하며, 배열 경계 검사를 우회할 수 있다. C/C++ 코드와도 로레벨로 연동가능하다. 현재의 언세이프는 위험성을 표시하는 수준이지만, 앞으로 안전성 계약(safety contract)을 코드 차원에 명시해 메모리 안전성을 더 강화한다는 것이다.
리처드 랜더는 “C# 1.0에서 타입, 메서드, 내부 메서드 블록 등에 안전하지 않은 컨텍스트를 설정하는 방법으로 언세이프 키워드를 도입해 개발자가 가장 편리한 범위를 설정할 수 있도록 했다”며 “이후 언세이프 키워드는 러스트와 스위프트에서 재사용 및 재구성됐으며, 해당 언어 개발팀은 이 키워드에 더욱 엄격하고 전파(Propagation) 지향적인 의미론을 부여했다”고 적었다.
그는 “C# 16도 같은 경로를 따라, 닷넷 런타임 라이브러리에서 ‘Unsafe’와 ‘Marshal’ 멤버를 포함해 언세이프를 일관되게 적용하고, 이는 러스트 구현과 가장 유사하다”며 “결과적으로 언세이프 키워드는 더 이상 구문의 종류를 나타내는 게 아니라, 컴파일러가 검증할 수 없는 숙련 개발자가 읽고 준수해야 하는 일종의 계약을 나타내게 됐다”고 설명했다.
C#은 기본적으로 메모리 안전 안어를 지향해, 안전하지 않은 코드를 차단한다. 하지만 러스트처럼 컴파일 단계부터 메모리 안전성을 더 강하게 검증하는 방향으로 시스템 언어의 흐름이 이어지면서 C#도 메모리 안전을 더 강화하는 것이다.
미국 정부는 공공 시스템의 보안을 강화할 목적으로 메모리 안전성을 높인 프로그래밍 언어를 사용할 것을 강력하게 권고하고 있다. 이에 기존 C 언어 대신 러스트가 더 주목받았다. 미국 국가안보국(NSA)과 CISA는 작년 ‘메모리 안전 언어: 최신 소프트웨어 개발의 취약점 감소’란 가이드를 발표하고 중요 인프라의 구현 권장 사항을 안내하고 있다.
C# 16의 새로운 모델에서 포인터 역참조 같이 컴파일러에서 검증할 수 없는 모든 안전하지 않은 연산은 반드시 unsafe {} 블록 안에 있어야 한다. 메서드 시그니처에 언세이프 한정자를 붙이면, 내부 블록의 의무를 해제하지 않는 한 위험성이 상위 호출자에게 그대로 전파된다. 호출자도 이를 호출하려면 unsafe {} 블록으로 감싸야 한다. 모든 언세이프 멤버는 호출자가 이행해야 할 의무를 XML 주석 블록으로 공식 문서화해야 한다. 누락하면 분석기가 오류를 표시할 수 있다. 경계에서의 억제(isolation)는 내부에 언세이프 블록을 포함하지만 메서드 시그니처에 언세이프를 표시하지 않는 메서드다. 런타임 가드를 통해 호출자의 의무를 완전히 해제해 안전한 로출자가 제약없이 호출할 수 있는 ‘안전하지 않은 경계 메서드’ 역할을 한다.
리처드 랜더는 새로운 메모리 안전 모델이 AI 기반 코드 생성 에이전트의 안전한 코드 생성을 강제하고 검증하는 툴을 제공한다고 설명했다. 그는 AI 기반 코딩 어시스턴트를 사용하는 개발자가 그렇지 않은 개발자보다 더 안전하지 않은 코드를 작성하면서도 자신의 코드를 안전하다고 착각하는 경향을 보인다고 했다.
이를 위해 새 모델은 AI 에이전트가 마음대로 위험한 코드를 작성하지 못하도록 두가지 요소를 추가한다. 세이프, 언세이프, 경계 메서드 등을 나누는 호출 그래프와 언세이프 블록 없는 안전하지 않은 콜을 거부하는 컴파일러다.
C# 16의 전파 및 억제 모델은 AI 에이전트의 코드 생성에 무시할 수 없는 규칙을 제시한다. AI가 실수로 작성한 가드 없는 코드는 코드 리뷰 전 컴파일 단계에서 차단된다. AI는 호출자에게 경고를 전파하거나 경계에서 런타임 가드를 사용해 위험을 억제하도록 유도된다. 세이프티 문서는 API별 지침 역할을 한다.
이를 통해 AI 에이전트가 메모리 안전 모델을 우회해 위험한 코드를 작성하려고 시도하더라도 변경사항이 깃 히스토리나 사람의 코드 리뷰에서 쉽게 포착 가능해진다.
랜더는 “우리는 C#이 타입 안전성과 메모리 안전성을 엄격하게 준수하는 언어로 인정받는 미래를 꿈꾼다”며 “이러한 모델 변화를 통해 C#, 러스트, 스위프트는 더욱 공통된 안전성 용어와 워크플로우를 갖게 될 것”이라고 밝혔다.
그는 “새로운 모델은 C#의 기본 구조를 대부분 유지하면서 대부분의 개발자가 건드리지 않는 언세이프 패턴을 개선하는 동시에 언어의 전반적인 안전성과 안정성을 크게 향상시킨다”며 “이 기능이 새로운 코딩 시대에 개발자의 신뢰도를 높이는 데 가장 효과적인 변화 중 하나라고 생각한다”고 강조했다.
글. 바이라인네트워크
<김우용 기자>yong2@byline.network



