처리중입니다. 잠시만 기다려주세요.
TTJ 코딩클래스
정규반 단과 자료실 테크 뉴스 코딩 퀴즈
테크 뉴스
Hacker News 2026.08.04 31

Rust에 '움직일 수 없는 타입'이 온다 — Move 트레이트와 소멸자 보장 이야기

Hacker News 원문 보기

Rust 언어 팀이 2026년 프로젝트 목표 중 하나로 꽤 근본적인 변화를 내걸었어요. 바로 '이동할 수 없는 타입(immobile types)'과 '소멸자 실행 보장(guaranteed destructors)'인데요. Rust를 써보신 분이라면 Pin 때문에 머리를 싸매본 기억이 있으실 텐데, 바로 그 고통을 언어 차원에서 해결하겠다는 계획이에요.

지금 Rust의 대전제: 모든 값은 이동할 수 있다

Rust에는 암묵적인 대전제가 하나 있어요. 모든 값은 언제든 메모리의 다른 위치로 이동(move)할 수 있고, 그 이동은 단순한 메모리 복사(memcpy)로 이뤄진다는 거예요. 변수를 함수에 넘기거나, Vec이 커지면서 내부 데이터를 재배치하거나, 이 모든 게 '값을 통째로 복사해서 옮기고 원본은 무효화'하는 방식으로 동작하거든요.

대부분의 경우 이건 아무 문제가 없어요. 그런데 딱 하나, 자기 자신의 내부를 가리키는 포인터를 가진 타입, 이른바 자기 참조(self-referential) 구조체가 문제예요. 값이 주소 1000번지에 있고 내부 포인터가 1008번지(자기 자신의 일부)를 가리키고 있다고 해볼게요. 이 값이 2000번지로 이동하면? 포인터는 여전히 옛날 주소인 1008번지를 가리키고 있으니 그대로 미아가 되는 거죠.

그래서 나온 게 Pin인데, 이게 악명이 높거든요

이 문제가 폭발한 건 async/await 때문이었어요. async 함수를 컴파일하면 내부적으로 상태 머신이 만들어지는데, 이 상태 머신이 자기 참조 구조를 갖기 쉽거든요. await 지점을 넘나들며 살아남는 지역 변수의 참조를 내부에 보관해야 하니까요. 그래서 2018년에 도입된 게 Pin이에요. 이게 뭐냐면, '이 값은 이제 이 자리에 고정됐으니 다시는 이동시키지 않겠다'는 약속을 타입으로 표현한 장치예요.

문제는 Pin이 언어에 내장된 개념이 아니라 라이브러리 수준의 우회책이라는 거예요. 그래서 쓰기가 정말 어려워요. Pin<Box<T>>와 Pin<&mut T>의 차이, unsafe가 필요한 Pin::new_unchecked, 구조체 필드에 접근하려면 pin-project 같은 별도 매크로가 필요한 상황까지. Rust에서 가장 배우기 어려운 개념을 꼽으면 항상 상위권에 드는 게 Pin이거든요.

제안: Move 트레이트로 '이동 가능'을 선택사항으로

이번 프로젝트 목표의 핵심은 Move라는 트레이트를 도입하는 거예요. 지금은 '모든 타입은 이동 가능'이 무조건이지만, 앞으로는 이동 가능함 자체를 Move 트레이트로 표현하고, 이걸 구현하지 않는 타입은 한번 자리를 잡으면 이동할 수 없게 만들자는 거죠. Sized가 모든 타입에 기본으로 붙지만 ?Sized로 풀 수 있는 것과 비슷한 구조라고 생각하시면 돼요.

이렇게 되면 뭐가 좋냐면, '이동 불가'가 언어의 일급 개념이 되니까 Pin이라는 우회 장치 없이도 자기 참조 타입을 자연스럽게 다룰 수 있게 돼요. async 코드가 단순해지는 건 물론이고요.

소멸자 보장: 사실 Rust는 Drop을 약속한 적이 없어요

의외로 많은 분들이 모르는 사실인데, Rust는 소멸자(Drop)가 반드시 실행된다고 보장하지 않아요. mem::forget은 안전한(safe) 함수고, Rc 순환 참조로도 Drop을 건너뛸 수 있거든요. 이게 실제로 사고로 이어진 유명한 사례가 1.0 이전의 'leakpocalypse'예요. 당시 thread::scoped라는 API가 소멸자 실행을 전제로 안전성을 설계했다가, 소멸자를 건너뛸 방법이 발견되면서 통째로 제거됐죠.

소멸자 실행이 보장되면 새로운 문이 열려요. 대표적인 게 io_uring 같은 API예요. 커널이 내 버퍼에 비동기로 계속 쓰고 있는데 소멸자가 안 돌고 버퍼가 사라지면 대참사거든요. 그 외에도 async Drop, 노드가 서로를 직접 가리키는 intrusive 자료구조, 그리고 이동할 때 move 생성자를 호출해야 해서 memcpy 이동이 불가능한 C++ 타입과의 상호운용까지, 지금은 unsafe 없이는 어려운 것들이 안전하게 가능해져요.

한국 개발자에게 주는 시사점

당장 문법이 바뀌는 건 아니에요. 어디까지나 설계와 실험을 진행하겠다는 연간 목표 단계고, 기존 코드와의 호환성 등 풀어야 할 난제가 많아요. 다만 방향은 분명해요. async Rust의 최대 진입장벽인 Pin이 언젠가 훨씬 단순해질 수 있다는 것, 그리고 Rust가 C++ 상호운용과 저수준 비동기 I/O 쪽으로 표현력을 계속 넓히고 있다는 것. Rust를 학습 중이라면 Pin이 '왜' 존재하는지 원리를 이해해두는 게 좋아요. 해결책이 바뀌어도 문제 자체는 그대로니까요.

정리하면

'모든 값은 이동 가능하다'는 Rust 10년의 대전제를 깨고, 이동 불가능한 타입과 소멸자 보장을 언어에 넣겠다는 큰 그림이에요. Pin 때문에 고생해보신 분들, 이 변화가 반가우신가요? 아니면 언어가 더 복잡해질 뿐이라고 보시나요?


🔗 출처: Hacker News

이 뉴스가 유용했나요?

이 기술을 직접 배워보세요

AI 도구, 직접 활용해보세요

AI 시대, 코딩으로 수익을 만드는 방법을 배울 수 있습니다.

AI 활용 강의 보기

"비전공 직장인인데 반년 만에 수익 파이프라인을 여러 개 만들었습니다"

실제 수강생 후기
  • 비전공자도 6개월이면 첫 수익
  • 20년 경력 개발자 직강
  • 자동화 프로그램 + 소스코드 제공

매일 AI·개발 뉴스를 받아보세요

주요 테크 뉴스를 매일 아침 이메일로 전해드립니다.

스팸 없이, 언제든 구독 취소 가능합니다.