실전 백엔드 러스트 Axum 프로그래밍

Erdos·2025년 7월 8일

감상

목록 보기
36/36
post-thumbnail

luvit 스터디 중간 중간의 기록

Programming language design is often thought of in terms of which features you include, but the features you exclude are important too. Rust doesn’t have the null feature that many other languages have. Null is a value that means there is no value there. In languages with null, variables can always be in one of two states: null or not-null.

In his 2009 presentation “Null References: The Billion Dollar Mistake,” Tony Hoare, the inventor of null, has this to say:

I call it my billion-dollar mistake. At that time, I was designing the first comprehensive type system for references in an object-oriented language. My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.


the rust programming language

https://doc.rust-lang.org/book/


axum

이 패키지는 2025.2월에 시행된 웹 서버 프레임워크에 대한 성능 벤치마킹 테스트에서 7위, Fullstack을 지원하는 프레임워크로 한정하면 2위를 차지한, 현존하는 최고의 성능과 안정성 있는 웹 서버 프레임워크라 할 수 있습니다.

https://docs.rs/axum/latest/axum/index.html#example


tokio

https://tokio.rs/tokio/tutorial/async


실전 백엔드 러스트 Axum 프로그래밍

1.5 러스트 핵심 개념 복습

1.5.1 소유권

  • 메모리 안정성: 하나의 값에 단 하나의 코드만 접근할 수 있기 때문에 예상치 못한 값 변경이 발생하지 않는다.
  • 스레드 안정성: 여러 스레드가 동시에 값에 접근할 때 발생하는 경합 조건이나 deadlock문제를 컴파일 타임에 탐지하여 안정적인 프로그램 실행 보장

소유권 요약

  1. 모든 값은 해당 값을 소유하고 있는 owner가 존재한다
  2. 한 번에 하나의 소유자만 존재할 수 있다
  3. 소유자가 현재 코드의 스코프에서 벗어나면 값은 메모리에서 할당해제 된다.

1.5.4 레퍼런스와 소유권 빌리기

  • borrow: 값의 소유권을 잠시 빌려주는 개념
  • reference: 소유권을 가져가지 않고 해당 값을 참조
fn main() {
    let x = String::from("Hello!");
    let y = &x;
    
    println!("{} {}", x, y);
}

가변 레퍼런스

어떤 변수의 레퍼런스를 사용해 원래 변수의 값을 바꾸려면 원래 변수를 가변으로 선언해야 한다.

fn dummy(y: &mut String) {
    y.push_str(" world!");
    println!("{}", y);
}

fn main() {
    let mut x = String::from("Hello");
    dummy(&mut x);
    println!("{}", x);
}

주의) 한 번에 하나의 소유자만 존재할 수 있다. 하나의 소유권을 한 번 이상 대여할 수 없음.

크레이트, 모듈, 패키지

crate

  • 러스트 코드를 묶을 수 있는 가장 작은 단위
  • binary crate: 컴파일 되어 바이너리 파일을 생성하는 크레이트
  • library crate; 컴파일 되지 않는 크레이트
  • crate root: 컴파일이 시작되는 엔트리 포인트

모듈

  • 구조체, 함수 등의 집합체

패키지

  • 여러 크레이트를 모아 놓은 것
  • 하나의 패키지에는 단 하나의 라이브러리 크레이트만 포함할 수 있다.(바이너리 크레이트는 여러 개 포함 가능)

트레이트(trait)

  • 구조체를 상속하는 방법이 없어서, 서로 다른 구조체들이 함수를 공유할 수 있는 하나의 속성을 정의할 수 있다.
trait Greet {
    fn say_hello(&self) {}
}

2.1 HTTP 기초

  • HTTP(Hypertext Transfer Protocol): API를 사용하고자 하는 클라이언트와 API를 제공하는 서버 간의 통신을 위한 표준화된 통신 규약.

  • 요청 메서드(request method): 클라이언트가 서버에 API를 사용하기 위한 요청을 보낼 때, 어떤 종류의 작업을 요청하는지를 나타내는 방법

    • GET: 서버에서 데이터를 가져온다
    • POST: 서버에서 새 리소스를 생성한다
    • PUT: 기존 리소스를 업데이트한다
    • PATCH: 기존 리소스의 일부분만 수정한다(PUT과 달리 부분 업데이트)
    • DELETE: 서버에서 리소스를 제거한다
  • 요청 본문(request body): 실제 데이터가 담기는 영역

  • 응답 코드(Response code): 서버가 수신한 요청에 대한 처리 결과를 나타내는 미리 약속된 값

    • 200 OK
    • 3xx 리다이렉션
    • 400 Bad Request
    • 404 Not Found
    • 500 Internal Server Error

JSON(JavaScript Object Notation): 자바스크립트 프로그래밍 언어에서 객체를 표현하는 방식에서 아이디어를 차용한 데이터 표현 방식. 사람이 읽고 쓰기 편리하며, 데이터가 계층화되어 있어 API를 사용할 때 데이터를 주고받는 데 많이 사용한다.

  • 키-값 쌍으로 이루어져 있음
  • 값: 불리언, 숫자, 문자열, 배열, 다른 JSON

HTTPS(HyperText Transfer Protocol Secure)

HTTP에 SSL/TSL 암호화 계층이 추가된 것으로, 데이터 보안성이 높다.

2.3 라우터와 핸들러

2.3.4 상태 코드와 헤더

  • 상태 코드(status code, 응답 코드기도 함): 서버가 클라이언트에게 응답을 보낼 때 응답의 성공 여부를 함께 전송하는 방법
  • Axum에서의 StatusCode 열거형. 러스트 웹 개발의 표준적인 관행이다.
    • 200 OK StatusCode::OK
    • 201 Created StatusCode::CREATED
    • 204 No Content StatusCode::NO_CONTENT
    • 400 Bad Request StatusCode::BAD_REQUEST
    • 401 Unauthorized StatusCode::UNAUTHORIZED
    • 403 Forbidden StatusCode::FORBIDDEN
    • 404 Not Found StatusCode::NOT_FOUND
    • 500 Internal Server Error StatusCode::INTERNAL_SERVER_ERROR

2.4 상태 관리

  • 정리 추후에 지금은 목차만

2.4.1 State

Arc< Mutex >

3.1 ORM이란?

소스 코드와 데이터베이스 간의 불일치를 해결하기 위해 사용하는 방법

코드 마이그레이션을 왜 쓰나?

SQL을 직접 치는 게 아니라, 코드로 작성해서 실행함.

1) 여러 개발자/서버에서 동일하게 적용
2) 변경 내역이 명확하게 기록됨
3) 롤백이 쉬움(migrate down)
4) 코드와 DB의 연결이 자연스럽다

단점: 문법 공부, SQL의 일부 복잡한 기능은 코드로 표현하기 어려움.

SeaORM

https://www.sea-ql.org/SeaORM/


실습 중 어려움

현재 실습하고 있는 내용들을 github에 업로드 하고 있다.

발생한 문제

그냥 디렉토리 작업한 것을 모두 push했더니 챕터 3에 해당하는 것은 업로드가 되지 않는다.

이유

rust는 빌드할 때마다 모든 바이너리/라이브러리/테스트/디버깅 정보를 target 폴더에 생성. 즉, 대규모 의존성 + 빌드 캐시가 모두 저장되고 있는데 이 용량이 만만치 않은 것.
현재 디렉토리가 6개정도 있는데, 모두 각각의 프로젝트인 상황.

github에 정상적으로 올리려면

.gitignore로 target관리를 해야 한다.

git 명령어

1) 모든 커밋 히스토리에서 /target/폴더 완전 제거

git filter-branch --force --index-filter \
  "git rm -r --cached --ignore-unmatch target migration/target */target" \
  --prune-empty --tag-name-filter cat -- --all

2) 불필요한 데이터 정리

git reflog expire --expire=now --all
git gc --prune=now --aggressive

3) 강제 푸시

git push --force --all
git push --force --tags

특정 디렉토리 용량 확인

du -sh <디렉토리명>
  • -s: 총합 summary
  • -h: human-readable

현재 작업중인 rust 폴더의 용량이 2.4GB이다..
와 C언어랑은 차원이 다르구나! 허허

profile
수학을 사랑하는 애독자📚 Stop dreaming. Start living. - 'The Secret Life of Walter Mitty'

0개의 댓글