Benefits of Applying Software Design Patterns to Backend Rust Applications
이 논문은 프로덕션 Rust 백엔드 애플리케이션에 typestate 및 newtype 디자인 패턴을 적용하는 것의 영향을 실증적으로 평가하며, typestate는 가독성을 희생하는 대신 결함 없는 상태와 테스트 가능성을 크게 향나지는 반면, newtype 패턴은 유효하지 않은 런타임 상태를 방지함으로써 적은 노력으로 높은 품질의 이득을 제공한다는 것을 발견하였다.
원본 논문은 CC BY 4.0 (http://creativecommons.org/licenses/by/4.0/) 라이선스로 제공됩니다. 이것은 아래 논문에 대한 AI 생성 설명입니다. 저자가 작성하거나 승인한 것이 아닙니다. 기술적 정확성을 위해서는 원본 논문을 참조하세요. 전체 면책 조항 읽기
당신은 고성능 커피 메이커와 같은 복잡한 기계를 만들고 있다고 상상해 보세요. 당신은 이 기계가 빠르고, 신뢰할 수 있으며, 문제가 생겼을 때 고치기 쉽기를 원합니다. 컴퓨터 소프트웨어의 세계에서 Rust라는 언어는, 나중에 누출되거나 망가질 수 있는 것을 절대 만들지 못하도록 막아서는 매우 엄격하고 안전을 중시하는 엔지니어와 같습니다. 하지만 엄격한 엔지니어가 있더라도, 기계를 이해하기 쉽고 수정하기 쉽게 만들기 위해서는 좋은 설계도(blueprint)가 필요합니다.
이 논문은 특정 "설계도"(디자인 패턴이라 불리는)를 사용하는 것이 Rust 소프트웨어를 더 낫게 만드는지에 대한 연구입니다. 저자인 Leon Heuer는 독일의 소매업체(OTTO)에서 가져온 세 가지 실제 소프트웨어 구성 요소를 대상으로, 두 가지 특정 설계도인 Typestate 패턴과 Newtype 패턴을 사용하여 재구축함으로써 이를 테스트했습니다.
다음은 그가 발견한 내용을 일상적인 비유를 들어 쉽게 풀어서 설명한 것입니다.
1. 문제점: "주방 싱크대" 코드
변경 전의 소프트웨어는 모든 것이 한데 뒤섞여 버려진 거대한 주방 싱크대와 같았습니다.
- 문제점: 하나의 단일 함수가 사용자가 로그인했는지 확인하고, 데이터를 가져오고, 숫자를 검증하고, 결과를 저장하는 등 모든 일을 다 하려고 했습니다. 코드는 길고 혼란스러웠으며, 한 부분을 변경하면 엉뚱하게 멀리 떨어진 다른 부분을 망가뜨릴 수도 있었습니다.
- 위험 요소: 문이 아직 잠금 해제되지 않았는데 문을 열려고 시도하는 것과 같은 실수를 하기 쉬웠습니다. 컴퓨터는 프로그램이 실제로 실행되어 충돌이 발생하기 전까지는 이를 막아주지 않았습니다.
2. 해결책: 두 가지 새로운 설계도
설계도 A: "Newtype" (신분증 배지)
비유: 당신에게 섞여 있는 열쇠 상자가 있다고 상상해 보세요. 어떤 것은 앞문을 열고, 어떤 것은 뒷문을 열며, 어떤 것은 그냥 장식용입니다. 만약 "앞문 열쇠"를 "뒷문" 자물쇠에 건네준다면, 아무 일도 일어나지 않다가 실제로 사용하려고 할 때 갇혀버리게 됩니다.
해결책: Newtype 패턴은 모든 열쇠에 별도의 라벨을 붙이는 것과 같습니다. 당신은 특별한 "앞문 열쇠" 상자를 만듭니다. 당신은 실수로 "뒷문 열키"를 그 안에 넣을 수 없습니다.
- 무슨 일이 일어났나: 저자는 가공되지 않은 텍text(예: 숫자 문자열)를 가져와서 특별한 "검증된(Validated)" 상자로 감쌌습니다. 만약 텍스트가 유효하지 않으면 상자가 닫히지 않습니다.
- 결과: 이는 큰 승리였습니다. 비용이 적게 들었고, 코드를 훨씬 읽기 쉽게 만들었으며, 유효하지 않은 데이터가 시스템에 들어오는 것을 방지했습니다. 이는 마치 문 앞에 서서 누군가 들어오기 전에 신분증을 확인하는 보안 요원이 있는 것과 같습니다.
설계도 B: "Typestate" (조립 라인)
비유: 자동차를 만드는 과정을 상상해 보세요. 프레임을 만들기 전에 차체를 칠할 수 없고, 프레임이 준비되기 전에 엔진을 넣을 수 없습니다. 기존 코드에서는 프로그래머가 프레임이 존재하기도 전에 실수로 도색을 시도할 수 있었으며, 컴퓨터는 도색 작업이 실패할 때까지 이를 막지 못했습니다.
해결책: Typestate 패턴은 코드를 엄격한 조립 라인으로 바꿉니다.
- 1단계: "가공되지 않은 프레임(Raw Frame)" 상태에서 시작합니다.
- 2단계: "가공되지 않은 프레임"이 있어야만 "엔진 구축(Build Engine)" 작업을 수행할 수 있습니다. 일단 이 작업을 수행하면, 프레임은 사라지고 "엔진이 장착된 프레임"이 됩니다.
- 3단계: "엔진이 장착된 프레임"이 있어야만 "도색(Paint)"을 할 수 있습니다.
- 결과: 컴퓨터는 당신이 순서를 틀리게 수행하는 것을 물리적으로 방지합니다. 만약 존재하지 않는 프레임에 도색을 하려고 하면, 코드는 컴파일조차 되지 않습니다(즉, 소프트웨어를 빌드할 수 없습니다).
- 트레이드오프(절충안): 이 방식은 코드를 믿을 수 있고 테스트하기 매우 쉽게 만들지만, 많은 "보일러플레이트(boilerplate, 부수적인 코드 작성)"를 추가합니다. 이는 마치 조립 라인의 매 단계마다 양식을 작성해야 하는 것과 같습니다. 더 안전하지만, 더 많은 서류 작업이 필요합니다.
3. 결과: 효과가 있었는가?
저자는 코드가 얼마나 빠른지 실행하여 확인하고, 자동화된 도구를 사용하여 복잡성을 측정하며, 전문가 인터뷰를 진행하는 세 가지 방법을 통해 이 변화들을 테스트했습니다.
- 속도: 이러한 변화가 소프트웨어를 느리게 만들지 않았습니다. 새로운 설계도의 "추가적인 서류 작업"은 컴퓨터가 눈치채지 못할 정도로 빠르게 처리되었습니다.
- 안전성 (결함 없음): 이 부분이 크게 개선되었습니다. 새로운 설계도는 "유효하지 않은 상태"(예: 바퀴가 없는 자동차)를 만드는 것을 불가능하게 만들었습니다. 예전에는 소프트웨어가 실행되는 동안 발생했던 오류들이 이제는 소프트웨어가 만들어지기도 전에 포착됩니다.
- 테스트: 코드를 테스트하기가 훨씬 쉬워졌습니다. 거대한 주방 싱크대 전체를 테스트하는 대신, 조립 라인의 각 작은 단계를 개별적으로 테스트할 수 있었습니다.
- 가독성: 결과는 엇갈렸습니다.
- Newtype(신분증 배지)은 상황을 더 명확하게 만들었습니다.
- Typestate(조립 라인)는 더 안전하게 만들었지만, 일부 전문가들은 추가된 코드가 처음 보기에는 가독성을 떨어뜨린다고 느꼈습니다. 그러나 일단 패턴을 이해하고 나면, 오히려 로직을 따라가기가 더 쉬워졌습니다.
4. 결론
연구의 결론은 다음과 같습니다:
- Newtype은 "고민할 필요가 없는(no-brainer)" 선택입니다. 이는 안전성과 명확성 측면에서 큰 이득을 주는 작은 변화입니다. 이메일 주소나 가격처럼 데이터가 유효해야 하는 경우라면 언제든 사용해야 합니다.
- Typestate는 강력하지만 무겁습니다. 이는 작업 순서가 매우 중요한 복잡한 규칙이 있을 때(예: 다단계 결제 과정) 사용하는 것이 가장 좋습니다. 만약 과정이 단순하고 직선적이라면, 추가적인 코드를 작성하는 것이 그만한 가치가 없을 수도 있습니다.
요약하자면, Rust에서 이러한 패턴을 사용하는 것은 지저zeta한 작업실에서 안전 가드와 엄격한 조립 라인이 갖춰진 공장으로 업그레이드하는 것과 같습니다. 초기에 더 많은 계획이 필요하지만, 최종 결과물은 훨씬 덜 망가지고 고치기도 훨씬 쉽습니다.
연구 분야의 논문에 파묻히고 계신가요?
연구 키워드에 맞는 최신 논문의 일일 다이제스트를 받아보세요 — 기술 요약 포함, 당신의 언어로.