디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

업뎃) 동일 안전성 목표 하의 코드 비교 - Rust vs. Ada/..

루비갤로그로 이동합니다. 2025.07.03 20:05:00
조회 59 추천 0 댓글 0

부록 B: 동일 안전성 목표 하의 코드 비교 - Rust vs. Ada/SPARK


이 부록은 본문 5장에서 철학적 차원으로 다룬 ‘의도 중심’과 ‘규칙 중심’의 설계 방식이, 실제 코드에서는 어떻게 구현되는지 구체적으로 비교 분석합니다.


이를 위해, 컴퓨터 과학의 가장 기본적인 자료구조 중 하나를 구현하는 것을 목표로 설정하고, 각 언어가 이 문제를 해결하는 접근 방식과 그 과정에서 개발자가 겪는 경험이 어떻게 다른지 독자 여러분께서 직접 판단하실 수 있도록 구성했습니다.


비교 과제: ‘부모-자식 관계’를 가진 노드(Node) 구조 표현하기


우리의 목표는 간단한 트리(Tree) 구조를 만드는 것입니다. 이 구조에서 각 노드는 여러 자식 노드를 가질 수 있으며, 동시에 각 자식 노드는 자신의 부모 노드를 가리키는 참조를 가질 수 있어야 합니다.


접근법 1: 러스트 (Rust) - ‘규칙’이 ‘의도’를 가로막는 경우


1. 직관적이지만 ‘실패’하는 코드


다른 언어에 익숙한 개발자라면 누구나 떠올릴 법한, 가장 직관적인 코드입니다. 하지만 이 코드는 러스트의 빌림 검사기(Borrow Checker) 규칙 때문에 절대로 컴파일되지 않습니다.


// 이 코드는 컴파일되지 않습니다!

struct Node<'a> {

    parent: Option<&'a Node<'a>>, // 부모를 가리키는 참조

    // ... 다른 필드들

}


fn main() {

    let mut root = Node { parent: None, /* ... */ };


    // 컴파일 에러: `root`의 소유권과 빌림 규칙이 충돌합니다.

    // 빌림 검사기는 이처럼 데이터가 순환 참조 구조를 갖는 것을 허용하지 않습니다.

    let child = Node { parent: Some(&root), /* ... */ };

}

‘자식이 부모를 가리킨다’는 개발자의 단순하고 명확한 의도가, ‘데이터는 단 한 명의 소유자만 가져야 하며, 빌림 규칙은 순환을 만들 수 없다’는 컴파일러의 엄격한 규칙과 정면으로 충돌하는 상황입니다.


2. ‘성공’하지만 복잡한 우회로


이 문제를 ‘안전한(safe)’ 러스트로 해결하려면, 개발자는 자신의 단순한 의도를 포기하고, 컴파일러의 규칙을 통과하기 위해 Rc, RefCell, Weak라는 복잡한 개념들을 동원한 ‘우회로’를 설계해야 합니다.


use std::rc::{Rc, Weak};

use std::cell::RefCell;


// 부모를 가리키는 참조는 '소유권 없는' 약한 참조(Weak)를 사용해야 합니다.

// 내부의 값을 변경하기 위해 RefCell을 사용합니다.

struct Node {

    parent: RefCell<Weak<Node>>,

    children: RefCell<Vec<Rc<Node>>>,

}


fn main() {

    let root = Rc::new(Node {

        parent: RefCell::new(Weak::new()),

        children: RefCell::new(vec![]),

    });


    let child = Rc::new(Node {

        parent: RefCell::new(Rc::downgrade(&root)), // 부모를 '약한 참조'로 저장

        children: RefCell::new(vec![]),

    });


    // 자식 노드를 추가하기 위해 .borrow_mut()를 호출해야 합니다.

    root.children.borrow_mut().push(Rc::clone(&child));


    println!("트리 구조 생성 완료!");

}


러스트 방식 분석


단순한 부모-자식 관계를 표현하기 위해, 개발자는 Rc(참조 카운팅 포인터), RefCell(내부 가변성), Weak(약한 참조), borrow_mut()(가변 빌림), downgrade()(약한 참조로 변환) 등 수많은 난해한 개념과 마주해야 합니다. 개발자의 초점은 ‘트리 구조’라는 원래 문제에서 벗어나, ‘어떻게 하면 빌림 검사기를 통과할까’라는 러스트의 규칙 자체를 해결하는 문제로 변질됩니다. 안전성은 컴파일러가 강제하지만, 그 대가로 개발자는 비직관적인 코드와 씨름해야 합니다.


접근법 2: Ada/SPARK - ‘의도’를 코드로 직접 표현하는 경우


Ada/SPARK 생태계는 개발자의 의도를 존중하고, 안전성을 다층적으로 확보하는 길을 제시합니다.


1. Ada: 직관적인 구조 표현과 런타임 안전성


먼저, Ada 언어 자체는 access라는 ‘포인터’ 타입을 사용하여 개발자의 의도를 직접적으로 표현하도록 돕습니다.


-- `Node` 타입을 미리 선언하여 자기 참조 구조가 가능하게 합니다.

type Node;

-- `Node` 타입을 가리킬 수 있는 '포인터' 타입을 정의합니다.

type Node_Access is access all Node;


-- 실제 `Node` 타입을 정의합니다.

type Node is record

   -- 부모를 가리키는 포인터를 필드로 가집니다. (자연스러운 표현)

   Parent   : Node_Access;

   -- 자식들을 담는 자료구조...

end record;


-- 사용 예시

procedure Create_Tree is

   Root  : Node_Access := new Node;

   Child : Node_Access := new Node;

begin

   Root.Parent := null; -- 루트 노드의 부모는 없음


   -- 자식 노드의 Parent 필드가 부모 노드(Root)를 직접 가리킵니다.

   Child.Parent := Root;


   -- ... 자식 노드를 Root의 Children 리스트에 추가하는 로직 ...

end Create_Tree;

이처럼 개발자의 의도(“노드는 다른 노드를 가리킬 수 있다”)가 매우 간결하게 표현됩니다. 이때 Ada는 러스트와 다른 방식으로 안전성을 확보합니다. 만약 개발자가 Parent가 null인 상태에서 Parent.all과 같이 역참조를 시도하면, 컴파일러는 이 코드를 막는 대신 런타임에 Constraint_Error라는 예외를 발생시키는 코드를 기본적으로 삽입합니다. 즉, 런타임에서 안전장치가 작동하는 것입니다.


이처럼 Ada의 런타임 안전망은 훌륭하지만, 일부 고신뢰성 시스템에서는 이마저도 부족할 수 있습니다. 바로 이 지점에서 SPARK가 등장하여 안전성을 한 차원 더 끌어올립니다.


2. SPARK: 명시적 계약을 통한 ‘증명된’ 컴파일 타임 안전성


SPARK는 개발자가 자신의 ‘의도’를 ‘계약(Contract)’으로 명시하면, 정적 분석 도구(Prover)가 “이 코드는 런타임 에러가 절대 발생하지 않는다”는 것을 수학적으로 증명합니다.


-- 부모의 정보를 사용하는 프로시저

procedure Process_Parent (Item : in Node_Access)

  with

    -- 사전 조건(Pre-condition)으로 "Item의 부모는 null이 아니다"라고 명시합니다.

    -- 이것이 개발자의 '의도'이자, Prover에게 증명을 요청하는 '계약'입니다.

    Pre => Item.Parent /= null

is

begin

   -- 이 계약 덕분에, SPARK Prover는 아래 코드가 런타임 에러 없이

   -- 안전함을 100% 증명할 수 있습니다.

   Put_Line ("My Parent is: " & Image (Item.Parent.all));

end Process_Parent;


이처럼 SPARK는 개발자에게 자신의 코드가 안전하다는 것을 ‘스스로 증명’하도록 요구합니다. 도구는 개발자의 이 선언이 타당한지를 수학적으로 검증해 줄 뿐입니다.


결론: 두 방식의 비교



구분러스트 (Rust)Ada/SPARK
핵심 철학‘규칙’이 ‘의도’를 제약‘도구’가 ‘의도’를 지원하고 검증
안전성 확보컴파일러가 암묵적 규칙을 자동으로 강제개발자가 명시적 계약을 작성하고 도구가 증명
개발자 경험컴파일러의 규칙을 통과하기 위한 싸움자신의 의도를 코드로 표현하고, 그 안전성을 계약으로 증명
주요 어려움언어의 고유한 패러다임(소유권)에 대한 적응문제에 대한 형식적이고 논리적인 사전 분석 및 ‘계약’ 작성
안전성의 기본값성능 우선 (안전은 Opt-in)안전 우선 (런타임 체크가 기본, 증명은 Opt-in)



이 ‘그래프/트리’ 예시는 ‘개발자의 단순한 의도’(자식이 부모를 가리킨다)와 ‘컴파일러의 엄격한 규칙’(데이터는 단 한 명의 소유자만 가져야 한다)이 정면으로 충돌하는 상황을 극명하게 보여줍니다. 러스트의 방식이 왜 어떤 이들에게는 ‘불필요한 장벽’이자 ‘비정석적인 설계’로 평가받는지, 이 예시만큼 명확하게 보여주는 것은 없습니다.


이 비교를 통해, 우리는 두 언어가 ‘안전성’에 도달하는 길이 근본적으로 다름을 알 수 있습니다. 러스트는 개발자의 실수를 원천적으로 막는 엄격한 ‘자동화된 규칙’을 선택했고, Ada/SPARK는 개발자의 ‘명시적인 의도와 증명’을 통해 안전성을 확보하는 길을 선택했습니다. 어느 쪽이 더 합리적인지는, 결국 개발자의 철학에 달려있을 것입니다.

추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 현역으로 군대 안 간게 의아한 스타는? 운영자 25/06/30 - -
AD 휴대폰 바꿀까? 특가 구매 찬스! 운영자 25/07/02 - -
2869451 시간이 빠르다에요 조루디(110.35) 07.03 28 0
2869449 요즘은 정신과약 먹고있음 [7] 조루디(110.35) 07.03 78 2
2869448 딱국 잘사냐 조루디(110.35) 07.03 46 3
2869447 "집값 안정시켜야 한다, 어떻게 세운 이재명 정부인데..." 발명도둑잡기(118.216) 07.03 54 0
2869446 하 그놈의 대용량 조루디(110.35) 07.03 39 0
2869445 나 2년차 실화냐 [2] 조루디(110.35) 07.03 52 0
2869444 오히려 자바충들이 싸지른 똥라이브러리들을 보면 러스트는 축복이다. 프갤러(27.172) 07.03 46 0
2869443 와일드샤크 패킷/C++ 혹은 C# 잘아시는교수님있으실까요? 프갤러(183.107) 07.03 37 0
2869442 러스트 라이브러리가 부족한건 사실이다. 프갤러(27.172) 07.03 41 1
업뎃) 동일 안전성 목표 하의 코드 비교 - Rust vs. Ada/.. 루비갤로그로 이동합니다. 07.03 59 0
2869437 7 ㅇㅇ(106.101) 07.03 38 0
2869435 나님 리짜이밍 덕분에 집값 폭등즁 ㅎㅅㅎ ♥냥덩이♥갤로그로 이동합니다. 07.03 33 0
2869431 냉정하게 23살이면 아직 기회있다고 보는게 맞는 나이임?? [2] ㅇㅇ(223.38) 07.03 51 0
2869429 미국 스타일 여성분 마주쳤다 [1] 헬마스터갤로그로 이동합니다. 07.03 56 0
2869427 ㅁㅌ겠네.. 러빠들 파닥파닥 날뛰면서 개난리칠거 예상된다. 루비갤로그로 이동합니다. 07.03 38 0
2869424 그러니까 무조건 러스트만을 찬양/옹호할게 아니라 루비갤로그로 이동합니다. 07.03 32 1
2869423 ❤✨☀⭐나님 시작합니당⭐☀✨❤ ♥냥덩이♥갤로그로 이동합니다. 07.03 26 0
2869422 부록 B: 동일 안전성 목표 하의 코드 비교 - Rust vs. Ada/ [2] 루비갤로그로 이동합니다. 07.03 38 0
2869420 러스트 빠 주장 분석: C언어도 stdio를 못 쓰는가? 루비갤로그로 이동합니다. 07.03 45 2
2869418 c++ 집에있는 책 펴봤느데 c++11기반 이네 [2] 프갤러(114.205) 07.03 57 0
2869417 새끼길냥덩 주울깡? ♥냥덩이♥갤로그로 이동합니다. 07.03 39 0
2869416 CPP 배울거면 그나마 스콧 메이어 책 이펙티브 모던C++봐야하는데 [22] ㅆㅇㅆ(124.216) 07.03 89 1
2869415 c는 임베디드에서 stdio쓸 수 있는줄 아나봄 프갤러(42.22) 07.03 47 0
2869414 백악관이 rust ada 등 메모리안전 언어를 추천하는 가운데 kyle이 [1] 발명도둑잡기(118.216) 07.03 48 0
2869413 c와 런타임라니브러리 합친 크기와 동일 기능하는 러스트 프로그램 실행파일 발명도둑잡기(118.216) 07.03 30 0
2869412 임베디드 시스템 및 리눅스 커널 적용의 실제적 제약 (바이너리, ABI 루비갤로그로 이동합니다. 07.03 50 0
2869411 내일 내가 만든 임베디드 시연하러 가야함 [1] 프갤러(211.234) 07.03 51 0
2869410 CPP는 책으로 배우면 잘못 입문한다. [6] ㅆㅇㅆ(124.216) 07.03 91 1
2869409 임베디드에서 동적링킹 쓰나 [6] 발명도둑잡기(118.216) 07.03 72 0
2869408 부록 A: ‘합리적 비판’에 대한 ‘비이성적 반응’ 사례 연구 루비갤로그로 이동합니다. 07.03 36 0
2869407 안되겠다. 자짤을 톡시한 크랩랭으로 복귀해야겠다. 프갤러(42.27) 07.03 26 0
2869406 나님 왤케 특별하실깡? ♥냥덩이♥갤로그로 이동합니다. 07.03 29 0
2869405 동적 링크는 시스템에 미리 그 라이브러리가 통째로 설치되어 있어야돼 프갤러(42.27) 07.03 39 0
2869404 행님들 C++입문할라는데 입문서 + 코딩문제집 동시에 보는거어 [2] 프갤러(123.142) 07.03 37 0
2869403 러빠하는 얘기보면 '동정 링킹'의 개념을 아예 모르는거 같음. ㅎㅎ 루비갤로그로 이동합니다. 07.03 45 0
2869402 전공자 LG 유플러스 부트캠프 어떨까요?? [3] 프갤러(218.50) 07.03 132 0
2869401 보석아. 너는 지금 동적 링크가 어떻게 동작하는지도 모르고 있는거야. [1] 프갤러(27.177) 07.03 59 0
2869400 내가 llm 조련하는거 보고가~~[위 러빠 얘기도 넣어 업뎃함] 루비갤로그로 이동합니다. 07.03 33 1
2869399 그 보석새끼 또 임베디드 바이너리 크기 타령하네 ㅋㅋ 프갤러(223.33) 07.03 34 0
2869398 냥덩너무조와? [2] ♥냥덩이♥갤로그로 이동합니다. 07.03 47 0
2869397 네이버 카페가 안들어가짐 프갤을 잘 되는데, 넥도리아(121.139) 07.03 28 0
2869396 ㅆㅇㅆ아 그건 너 말이 맞다. [2] 루비갤로그로 이동합니다. 07.03 75 1
2869395 지금 netstat, tasklist 결과 [2] 발명도둑잡기(118.216) 07.03 58 0
2869394 커뮤니티 사이트 회원가입 빡세게 해놓는 이유...txt ㅇㅇ갤로그로 이동합니다. 07.03 48 0
2869393 나는 근데 루비보면서 LLM의 무서운점을 느낌. [4] ㅆㅇㅆ(124.216) 07.03 67 2
2869392 ㅆㅇㅆ 고맙다. 어제 마니 까줘서 보강했어 [2] 루비갤로그로 이동합니다. 07.03 68 1
2869391 애들아 메모리쪽 공부해 [6] 프갤러(106.101) 07.03 110 1
2869390 갤에 러까 글 진지하게 읽는 사람 있음? [2] 프갤러(218.154) 07.03 50 0
2869389 추억의 만찐두빵⭐+ ♥냥덩이♥갤로그로 이동합니다. 07.03 30 0
2869388 러스트 혹세무민 = 곡학아세 + 오만 + 기만 루비갤로그로 이동합니다. 07.03 25 1
뉴스 탑현, 오늘(3일) 신곡 ‘올해는 유난히 덥다던데’ 발매! 디시트렌드 07.04
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2