BRICKSTUDY

[Rust] 파이썬 개발자의 러스트 찍먹하기 본문

Backend

[Rust] 파이썬 개발자의 러스트 찍먹하기

brickstudy 2024. 11. 9. 15:33

 

📌 Intro

안녕하세요. 브릭스터디 김민준입니다. 이번에 공유드릴 내용은 "파이썬 개발자의 러스트 체험기"라는 주제로 전달드릴 예정입니다. 

 

저는 현재 실무에서 파이썬 백엔드 개발자 or 데이터 파이프라인 엔지니어(?)로 일하고 있고, 커리어 내내 파이썬만을 써왔습니다.

이런 제가 왜 러스트를 공부하게 되었는지, 러스트를 약 1달정도 경험해보았을 때, 어떤 점을 경험했는지를 위주로 작성했습니다. 아직 러스트를 많이 써본 것은 아니기 때문에, 잘못 이해하고 작성된 부분이 있을 수 있습니다.

 

러스트에 대해 정확한 정보를 제공하는 글이 아니기 때문에 경험담 정도로만 봐주세요 :)

 

 

🗂️ Table of Contents

1. Rust는 무엇인가?

2. Rust는 안전하다? - 메모리 안정성

3. Rust는 빠르다? - 성능과 효율성
4. Rust 찍먹 프로젝트 - (진행중)

5. 결론 - Rust 추천? 

 

 

💡 Background

실무에서는 계속 파이썬을 써왔지만, 퇴근하거나 주말에 저는 다른 개발 언어를 공부하고 간단한 프로젝트를 하는 것을 좋아합니다.

그러다보니 지금까지 취미삼아 찍먹했던 언어들이 많은 편입니다.

  • java : 데이터 인프라 엔지니어 인턴 시절 데이터 기술 대부분이 java로 작성되어 있어 직접 공식문서를 읽고 싶어서 찍먹....
  • kotlin : 애는 왜 한건지 기억은 안나지만... 그냥 궁금해서 찍먹했던거 같음....
  • Go : 고루틴 동시성 처리 +  캐릭터가 귀여워서 공부
    (가장 최근까지 취미로 진행한 프로젝트에서 사용한 언어!! 찍먹했던 언어들 중에 가장 재밌었음)

많은 언어들을 찍먹하며, 여러 프로젝트를 진행했었지만 실무에서 사용할 수 있을 정도로 깊게 공부하고 싶었던 언어는 지금까지 없었습니다. 왜 그랬을까를 고민해보니... 현재 제가 하고 있는 일과 앞으로 제가 하려는 커리어 방향성에서 "파이썬"이라는 언어에 비해 찍먹 했던 언어에 큰 이점이 없다 생각했던거 같습니다.

 

저는 백엔드 엔지니어지만, 사용자의 트래픽을 처리하는 엔지니어가 아닌 데이터를 주로 담당하며 저의 일 중 대부분은 대용량 데이터의 파이프라인을 구축하거나 데이터 관련 백엔드 개발을 해왔습니다. 그러다보니 언어 자체가 얼마나 빠른가보단 데이터 처리를 얼마나 용이하게 할 수 있는가 또는 데이터 처리하는 솔루션을 잘 지원해주는 언어인가가 더 중요했습니다. "파이썬"은 Spark, Airflow, ML 등 데이터 처리에 강점이 있는 언어이며, 제가 지금까지 찍먹한 언어들이 "파이썬" 언어 자체의 성능이 더 빠르겠지만 그 장점이 저에게는 크게 영향을 주지 못했습니다. (찍먹한 언어를 실무에서 쓸 수 있을 정도로 공부하더라도 일은 파이썬으로 할거 같은데...?)

 

이러한 고민을 하던 중 이번에는 아예 파이썬이랑 아예 다른 특징을 가진 언어, 좀 더 low level를 찍먹해보자는 도전 정신(?)이 생겼습니다.

위에 길게 고민을 적었지만, 엄청 큰 뜻이 있었다기 보단 그냥 해보고싶다가 사실 가장 큰 이유이고 여러 C나 C++ 등 low level의 언어 중 rust를 선택해서 공부하게 되었습니다.

 

아직은 찍먹 단계이지만 과연 rust는 제가 좀 더 깊게 공부하고 싶은 언어 일지 찾아가보는 과정을 블로그를 통해 조금씩 공유해볼 예정입니다 :) 

 

 

1. Rust는 무엇인가?

A. Rust?

  • 모질라에서 개발되어 현재 러스트 재단과 오픈소스 커뮤니티에 의해 개발된 언어
  • 성능과 안전성에 중점을 둔 현대적인 프로그래밍 언어
  • 사용 사례
    • 고성능 동시성 시스템
    • 임베디드 프로그래밍
    • 레거시 C, C++ 교체
    • 웹 어셈블리 등등

 

B. Rust 특징(with. GPT)

1. 메모리 안전성 (Memory Safety without Garbage Collection)
Rust는 메모리 안전성을 보장하기 위해 소유권(Ownership)이라는 독특한 메커니즘을 사용합니다. 소유권, 대여(Borrowing), 그리고 라이프타임(Lifetime)이라는 시스템을 통해 프로그램이 명시적으로 메모리를 관리하면서도 안전하게 동작할 수 있도록 설계되었습니다. 이 방식은 잠재적인 데이터 경합, 널 포인터 참조, 더블 프리와 같은 메모리 관련 오류를 컴파일 단계에서 방지합니다. 동시에 Rust는 가비지 컬렉터(Garbage Collector)를 사용하지 않아, 성능이 중요한 시스템 프로그래밍에 적합합니다.


2. 성능과 효율성 (Performance and Efficiency)
Rust는 C나 C++처럼 시스템 수준의 언어로 설계되어 매우 빠르고 효율적인 성능을 제공합니다. 저수준의 메모리 제어를 허용하면서도, 고수준 언어의 안전성을 지키려는 철학을 지니고 있습니다. Rust의 컴파일러는 런타임 오버헤드를 최소화하고, 개발자가 메모리와 CPU 자원을 최대한 효율적으로 사용할 수 있도록 돕습니다.


3. 동시성 안전성 (Concurrency without Data Races)
Rust는 안전한 병행 프로그래밍을 강조하며, 데이터 경합(Data Race)을 방지하는 병행성 모델을 지원합니다. Rust에서는 소유권과 대여 시스템을 통해 여러 스레드가 동시에 같은 데이터를 수정하는 경우를 방지합니다. 이를 통해 개발자가 동시성 오류를 방지하며 안전하게 병행 프로그램을 작성할 수 있게 합니다.


4. 개발자 경험 (Developer Experience)
Rust는 개발자 친화적인 언어를 지향합니다. 뛰어난 컴파일러 오류 메시지, 편리한 패키지 관리자(Cargo), 그리고 잘 정리된 문서화 등으로 개발자들이 언어를 더 쉽게 배우고 사용할 수 있도록 합니다. 이는 C나 C++에 비해 더 직관적이고 현대적인 개발 환경을 제공합니다.


5. 커뮤니티 중심 철학 (Community-Oriented Philosophy)
Rust는 커뮤니티 주도형 언어로, 개발자 커뮤니티와의 소통을 중시하고, 오픈 소스 프로젝트로서 커뮤니티의 피드백과 요구사항을 적극 반영합니다. 이로 인해 언어의 발전이 사용자 중심으로 이루어지며, 사용자와 함께 언어를 성장시키려는 철학이 강합니다.


6. 무비용 추상화 (Zero-Cost Abstractions)
Rust는 추상화가 성능에 영향을 미치지 않도록, 고수준의 추상화를 제공하면서도 런타임 비용을 최소화하는 것을 목표로 합니다. "무비용 추상화"란, 고수준의 기능을 사용해도 성능 손실이 없도록 설계하는 철학을 의미하며, 이는 Rust의 성능 효율성을 유지하는 중요한 요소입니다.

 

Rust의 특징을 GPT에 검색했을 때, 다음과 같은 특징이 실제 코드 베이스에서 어떻게 사용되어있는지 예시를 통해 좀 더 작성해보겠습니다!!

 

 

2. Rust는 안전하다? - 메모리 안정성

아마 많은 분들이 Rust라는 언어를 처음 들었을 때, 안전하다라는 말을 들어보신 적 있으실 겁니다. 과연 러스트는 어떻게 안전함이란 특징을 보장하는지 간단한 예시를 통해 설명드리겠습니다.

 

 

A. Rust 코드 예시

  • 아래 코드는 실행이 될까요??
fn move_example() {
    let s1 = String::from("Hello, Rust!");
    let s2 = s1;

    println!("{}", s1);
    println!("{}", s2);
}

 

.

.

.

.

.

 

  • 정답은 s1은 "Hello Rust"의 소유권을 잃어버렸기 때문에 에러를 발생합니다.
fn move_example() {
    let s1 = String::from("Hello, Rust!"); // `s1`이 문자열의 소유권을 가짐
    let s2 = s1; // 소유권이 `s2`로 이동됨, `s1`은 더 이상 사용 불가

    // println!("{}", s1); // 오류: s1은 더 이상 유효하지 않음
    println!("{}", s2); // s2는 정상적으로 사용 가능
}

 

 

B. 소유권(Ownership) 이란?

  • Rust의 소유권은 메모리 관리 방식을 명확하고 안전하게 만드는 고유한 개념입니다.
  • 일반적으로 C, C++ 언어는 메모리 관리를 수동적인 절차로 개발자가 직접 관리해야하며, 자바, 파이썬 등의 언어는 런타임 시 가비지컬랙터를 통해 자동으로 메모리 관리를 수행하게 됩니다.
  • 러스트는 소유권을 바탕으로 대여 검사기(borrow checker)를 통해 컴파일 시 참조를 검증하는 방식으로 메모리를 관리하게 됩니다.

C. 소유권(Ownership)의 주요 규칙

  • 각 값은 하나의 소유자(Owner)만 가질 수 있다.
  • 소유자가 스코프를 벗어나면 그 값은 자동으로 해제된다.
  • 하나의 값은 여러 참조(Borrow)를 통해 대여될 수 있지만, 가변 참조는 동시에 하나만 허용된다.

D. 소유권(Ownership) 개념 예제

  • 소유권의 이동(Move)
    • 하나의 값에 대한 소유권이 다른 변수에 할당되면 기존 변수는 더 이상 사용할 수 없음.
fn main() {
    let s1 = String::from("hello"); // s1이 문자열 "hello"의 소유권을 가짐
    let s2 = s1; // s1의 소유권이 s2로 이동, s1은 더 이상 유효하지 않음

    // println!("{}", s1); // 오류 발생: s1은 더 이상 유효하지 않음
    println!("{}", s2); // s2는 정상적으로 사용 가능
}
  • 소유권 복사(Copy)
    • 정수형, 부동소수점 숫자 등 크기가 고정된 값들은 이동이 아닌 복사가 일어남
    • 이 경우에 값이 복사가 되기 때문에 원래 변수도 여전히 사용 가능
    • rust의 경우 소유권 이동과 복사를 자동으로 구분하여 값의 타입에 따라 적절한 방식으로 사용됨.
fn main() {
    let x = 5;
    let y = x; // `x`의 값이 `y`로 복사됨, `x`는 여전히 유효
    println!("x: {}, y: {}", x, y); // 둘 다 사용 가능
}
  • 참조와 대여(Borrowing)
    • Rust는 값에 대한 참조를 다른 변수에 대여할 수 있음.
    • 대여에는 불변 참조와 가변참조가 있으며 대여 규칙을 통해 메모리 안정성을 보장함
    • 불변참조 : 여러 개의 참조를 동시에 허용할 수 있지만, 참조된 값을 수정할 수는 없음 
    • 가변 참조 : 한 번에 하나만 허용되며, 이를 통해 데이터 경합과 같은 병행성 문제를 방지
/* 불변참조 */
fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1); // s1을 불변 참조로 대여
    println!("The length of '{}' is {}.", s1, len); // s1은 여전히 유효
}

fn calculate_length(s: &String) -> usize { // 불변 참조를 받음
    s.len()
}

/* 가변참조 */
fn main() {
    let mut s = String::from("hello");
    change(&mut s); // 가변 참조를 대여
    println!("{}", s); // "hello, world!"
}

fn change(s: &mut String) {
    s.push_str(", world!"); // 참조된 값을 수정
}

 

  • 라이프라인(Lifetime)
    • Rust는 소유권과 대여를 더 안전하게 관리하기 위해 라이프타임을 도입하여 각 참조의 유효 기간을 컴파일러가 추적
    • 라이프타임 시스템을 통해 참조가 유효한 기간을 지정함으로써 메모리 오류를 사전에 방지

 

Rust는 소유권 개념을 활용해 가비지컬렉터가 없어도 메모리 안전성을 보장하며, 안전하고 효율적인 메모리 관리를 가능하게 함.

 

3. Rust는 빠르다? - 성능과 효율성

A. C언어와 유사한 성능

 

 

B. 파이썬, 러스트 비교

 

카카오 테크 블로그 : https://tech.kakao.com/posts/571

 

 

4. Rust 찍먹 프로젝트 - (진행중)

A. 프로젝트 주제

  • Rust를 활용하여 간단한 회원가입, 로그인 기능 구현
    • Rust 언어 자체가 어느정도 난이도가 있는 언어라서, 간단한 구현 프로젝트부터 진행
    • CLI, API를 단계적으로 구현해보며 언어에 적응하는 것을 중점으로 프로젝트를 정했습니다.

B. 프로젝트 목표

  1. CLI를 활용하여 사용자의 입력값을 받아 회원가입하는 기능 구현
  2. API를 통해 사용자의 입력값을 받아 로그인하는 기능 구현

C. 프로젝트 진행 단계

D. 프로젝트 진행 중간 후기

  • 기존 언어와 다른 특징을 가지고 있어 적응하기 낯설다...!!(어렵다는 말이 이해됨)
  • rust 컴파일러가 언어의 어려움을 많이 낮춰준다. (다른 언어와는 다르게 러스트 컴파일러는 어떻게 고쳐야하는지 제안까지 해줌)
  • 개발하는 과정에 좀 더 많은 생각을 하게 됨.(메모리 관리 등등)

 

아직 Rust를 공부한지 한 달정도라, 아는 것이 많이 없지만 지금까지 느낀 점은 꽤 재밌는 언어라 생각합니다. 지금까지 당연하게 고민하지 않았던 메모리에 대해서도 생각하게 되며, 다른 언어의 예외처리와는 달리 결과 타입을 활용한 오류 처리 등 공부할수록 어렵고 재밌는 요소가 많은거 같습니다.(어떤 글에 취미로 러스트 개발하시는 분들이 많다는 글 본거 같은데 이해가 조금씩 되어가고 있음 ㅎㅎ) 

 

 

5.  결론 - Rust 추천? 

A. 추천까지는 아직 잘....?

  • Rust를 물론 재밌게 공부하고 있고 앞으로도 더 많이 해볼 계획입니다.
  • 하지만, 해당 언어를 다른 분들에게 추천할만한지는 아직은 잘 모르겠습니다.
    (언어가 가진 장점이 강력한 것은 맞지만, 어려운 난이도와 아직 시장에서 필요한 장점인지는....)
  • 제가 좀 더 Rust를 공부하고 여러 프로젝트를 직접 경험하고 나면 생각이 바뀔 수 있겠지만.... 아직은 누군가에게 추천하기보단 저의 취미 생활로 남겨놓겠습니다.

 

 

 

다음 발표 때, Rust 찍먹 프로젝트 완성하면서 새롭게 알게된 Rust에 대해 공유드리겠습니다. 긴 글 읽어주셔서 감사합니다