Skip to content
Beside the Wheel
Search
Ctrl
K
Cancel
Email
GitHub
Select theme
Dark
Light
Auto
공부
(5)
spot 인스턴스에서 서버 가용성 개선하기
eBPF로 서버 성능 Profiling하는 법: Pyroscope의 구현 살펴보기
정수론부터 RSA까지
strace로 shaka-packager 버그 추적
Kubernetes The Hard Way
TIL
(937)
AI
(43)
DevOps
(230)
Network
(61)
OS
(155)
개발
(113)
과학
(1)
데이터베이스
(64)
서버
(72)
수학
(20)
알고리즘
(24)
암호학
(32)
언어
(95)
컴퓨터구조
(3)
코드
(24)
독후감
(43)
과학
(1)
사회
(2)
산문
(3)
소설
(12)
인문
(11)
자기계발
(7)
철학
(7)
생각
(6)
고민
변화에 대하여
의식의 영역에 대하여
본질을 보려면
짧은 생각들
소유냐 존재냐
회고
(14)
2022.03-04 대덕소마고 입학소감/다짐
2022.05-08 프로젝트와 인간관계
2022.09-2023.02 불안과 판단
2023.03-07 DMS 리더 회고
2023.08-11 나는 누구인가?
2023.12 더 많은 걸 배우기 위한 경험
2024.01-02 회사 인턴 회고
2024.03-04 고3 근황
2024.05-07 고등학교 마무리
2024.08-12 첫 회사
2025.01-03 입출력
2025.03-08 효능감이란 무엇일까
2025.09-12 연말회고
2026.01-08 담론
Email
GitHub
Select theme
Dark
Light
Auto
태그: rust
총 22개의 글이 있습니다.
Ordering
스레드
2026. 7. 12.
`Ordering`은 원자적 연산(atomic operation)이 다른 스레드에서 어떤 순서로 관찰되는지를 지정하는 열거형이다. `std::sync::atomic` 모듈의 `AtomicUsize`, `AtomicBool` 등 원자적 타입의 `load`, `store`, `compare_exchange` 같은 메서드에 인자로 전달한다. 컴파일러와 CPU는 실제 실행 결과가 같다면 명령어의 순서를 재배열(reorder)할 수 있는데, 이는 싱글 스레드에서는 문제가 없지만 여러 스레드가 메모리를 공유하는 상황에서는 한 스레드의 변경 사항이 다른 스레드에 어떤 순서로 보이는지가 프로그램의 정확성에 직접적인 영향을 준다. `Ordering`은 이러한 재배열을 어느 정도까지 허용할지를 결정하며, 값이 엄격할수록(
컴파일 과정
rust
2026. 3. 16.
Rust 컴파일러(`rustc`)는 소스 코드를 여러 단계에 걸쳐 네이티브 바이너리로 변환한다. 소스 코드 (.rs) → 렉싱 → TokenStream → 파싱 → AST → 매크로 확장 → AST (확장됨) → 이름 해석 → AST (바인딩 완료) → HIR 변환 → HIR → 타입 검사 → HIR (타입 정보 첨부) → MIR 변환 → MIR → borrow check + 최적화 + 모노모피제이션 → MIR (최적화됨) → LLVM IR 생성 → LLVM IR → LLVM 최적화 + 코드 생성 → 오브젝트 파일 → 링킹 → 실행 바이너리 렉싱 (Lexical Analysis) 소스 코드 텍스트를 의미 있는 최소 단위인 토큰(token)으로 쪼개
macro_rules
rust
2026. 3. 14.
`macro_rules!`는 Rust의 선언적 매크로(declarative macro)를 정의하는 구문이다. 컴파일 타임에 패턴 매칭으로 코드를 생성한다. rust macro_rules! 매크로이름 { (패턴) ={ 확장 코드 }; } `(패턴) ={ 확장 코드 }` 한 쌍을 arm이라고 한다. `match` 문과 비슷하게, 여러 arm을 정의하면 위에서부터 순서대로 매칭을 시도한다. rust macro_rules! say { () ={ println!("nothing") }; ($x:expr) ={ println!("{}", $x) }; } say!(); // println!("nothing") say!("hello"
temporary value is freed
메모리-참조
2024. 4. 19.
Rust에서 `temporary value is freed` 에러는 임시 값이 사용되기 전에 해제될 때 발생한다. 임시 값이 스코프를 벗어나 메모리가 해제되었는데, 해제된 값에 대한 참조가 여전히 남아있으면 이 에러가 발생한다. 이 에러를 방지하려면 값의 라이프타임이 실제 사용 범위와 일치하도록 소유권을 올바르게 관리해야 한다. 예시 rust let mut did_config = "{}"; let seed_input = options.value_of("seed").unwrap_or("tbd"); if (seed_input != "tbd") { let json_config = json!({ "seed": seed_input }); did_config = json_c
동시성
스레드
2024. 4. 9.
대부분의 요즘 운영 체제에서, 실행되는 프로그램의 코드는 프로세스 내에서 실행되고, 프로그램 내에서도 동시에 실행되는 독립적인 스레드를 가진다. 계산 부분을 여러 개의 스레드로 쪼개는 것은 프로그램이 동시에 여러 개의 일을 할 수 있기 때문에 성능을 향상시킬 수 있지만, 프로그램을 복잡하게 만들기도 한다. 러스트 표준 라이브러리는 언어 런타임의 크기를 작게 유지하기 위해 1:1 스레드 구현만 제공한다. 스레드 생성 새로운 스레드를 생성하기 위해서는 `thread::spawn` 함수를 호출하고, 새로운 스레드 내에서 실행하기를 원하는 코드가 담겨 있는 클로저를 넘기면 된다. rust use std::thread; use std::time::Duration; fn main() { threa
extern
ffi
2024. 4. 8.
`extern` 키워드를 사용하면 외부 코드를 링크하거나 import할 수 있다. `extern` 키워드는 Rust에서 두 가지 용도로 사용된다. 하나는 `crate` 키워드와 함께 사용하여 프로젝트 내의 다른 Rust crate를 인식시키는 것이다 (예: `extern crate lazy_static;`). 다른 하나는 외부 함수 인터페이스(FFI, Foreign Function Interface)에서 사용하는 것이다. FFI에서 `extern`은 두 가지 맥락에서 사용된다. 첫 번째는 외부 블록(external block) 형태로, Rust 코드가 외부 코드를 호출할 수 있도록 함수 인터페이스를 선언하는 것이다. rust [link(name = "my_c_library")]
FFI
ffi
2024. 4. 8.
FFI(Foreign Function Interface)는 한 프로그래밍 언어에서 다른 프로그래밍 언어의 코드를 호출하기 위한 인터페이스를 말한다. Rust에서는 toml에 lib 형태로 저장한 crate방식으로 사용할 수 있다. Rust에서 C 코드 호출하기 snappy] extern { fn snappy_max_compressed_length(source_length: size_t) -size_t; fn
repr
ffi
2024. 4. 8.
repr(Rust) 가장 기본적으로, 모든 타입은 바이트 단위의 정렬(alignment)을 가진다. 정렬이 n인 값은 반드시 n의 배수인 주소에만 저장될 수 있다. 즉 정렬이 2라면 짝수 주소에 저장되어야 하고, 1이라면 아무 곳에나 저장될 수 있다. 정렬은 최소 1이며, 항상 2의 거듭제곱이다. 원시 타입(primitive)은 보통 자신의 크기에 맞춰 정렬되지만, 이는 플랫폼마다 다르다. 예를 들어 x86에서 `u64`와 `f64`는 4바이트(32비트)로 정렬되는 경우가 많다. 타입의 크기는 항상 정렬의 배수여야 한다(0은 모든 정렬에 대해 유효한 크기다). 이 규칙 덕분에 해당 타입의 배열은 항상 크기의 배수만큼 오프셋을 더하는 방식으로 인덱싱할 수 있다. 단, 동적 크기 타입(DST)의 경우
멀티 스레드 웹 서버 만들기
스레드
2024. 4. 8.
Docs에 있는 예제를 따라 정리한 글임을 미리 밝힙니다. 요청했을 때 아래와 같은 웹 화면을 반환하는 웹 서버를 만들어보자! Rust 프로젝트는 아래와 같이 생성할 수 있다. bash $ cargo new hello --bin Created binary (application) `hello` project $ cd hello TCP 연결 처리 우선 `std::net`를 사용해서 하나의 TCP 연결을 처리하는 코드를 짜볼 것이다. `TcpListener` 를 사용하여 `127.0.0.1:7878` 주소로 TCP연결을
클로저
rust
2024. 4. 8.
Closure는 변수에 저장하거나 다른 함수에 인자로 넘길 수 있는 익명 함수이다. 한 곳에서 Closure를 만들고 실제 실행은 다른 곳에서 하도록 코드를 구성할 수 있게 한다. 상위 스코프 변수 참조 함수와 다르게 Closure는 호출되는 스코프로부터 변수들을 캡처할 수 있다. 변수를 참조하는 Closure를 정의했을 때, 해당 변수에 대한 소유권은 Closure가 가져간다. rust fn main() { let x = 4; let equal_to_x = |z| z == x; let y = 4; assert!(equal_to_x(y)); } 함수에서 상위 스코프의 변수를 참조하는 경우 에러가 발생한다. rust fn main() {
Condvar
스레드
2024. 3. 28.
구조체 Condvar는 Condition Variable의 약자로, 이벤트가 발생할 때까지 스레드를 차단하여 CPU 시간을 소비하지 않도록 하기 위해 사용한다. 조건 변수는 일반적으로 boolean predicate, 뮤텍스와 함께 사용된다. 스레드를 차단해야 한다고 판단하기 전에 뮤텍스 내에서 항상 조건을 검증한다. 이 모듈의 함수는 현재 실행 중인 스레드를 차단한다. 동일한 조건 변수에 여러 뮤텍스를 사용하려고 시도하면 런타임 패닉이 발생할 수 있다. 예제 rust use std::sync::{Arc, Mutex, Condvar}; use std::thread; let pair = Arc::
String
rust
2024. 3. 23.
String과 str rust fn main() { let s1: &str = "World"; println!("s1: {s1}"); let mut s2: String = String::from("Hello "); println!("s2: {s2}"); s2.push_str(s1); println!("s2: {s2}"); let s3: &str = &s2[6..]; println!("s3: {s3}"); } Rust에서 `&str`은 문자열 슬라이스에 대한 (불변) 참조이다. (C++의 `const char*`와 유사하지만 항상 유효한 문자열을 가리킨다) `String`은 문자열을 담을 수 있는 버퍼이다. (문자열을 이루는
Trait
rust
2024. 3. 23.
여러 타입(type)의 공통된 행위/특성을 표시한 것을 Trait이라고 한다. Rust에서의 Trait는 (약간의 차이는 있지만) 다른 프로그래밍 언어에서의 인터페이스(interface)와 비슷한 개념이다. Trait는 trait 라는 키워드를 사용하여 선언하며, trait 블럭 안에 공통 메서드의 원형(method signature)을 갖는다 rust trait Draw { fn draw(&self, x: i32, y: i32); } `Rectangle` 이라는 구조체에 `Draw` 라는 trait를 구현하기 위해서는 `impl 트레이트명 for 타입명`과 같이 정의하고 trait 안의 메서드들을 구현하면 된다. rust s
구조체 impl
rust
2024. 3. 23.
Rust에서 데이터를 표현하는 구조체(혹은 enum, trait 객체)의 맥락에서 그 구조체와 연관된 함수들을 정의할 수 있는데, 이렇게 연관되어진 함수들을 메서드라 한다. 메서드는 맥락이 되는 구조체 인스턴스로부터 호출되어 사용된다. Rust에서 구조체(struct)에 메서드들을 구현하는 구현 블럭(implementation block)은 "impl" 키워드를 사용하여 정의된다. impl 구현블럭 impl 키워드는 구현 블럭(implementation block)을 정의할 때 사용하는데, impl 뒤에 타입명을 적고 impl 블럭 안에 메서드(method) 혹은 연관 함수(associated function)를 넣게 된다. impl 안에 정의된 함수는 그 타입과 연관된 함수라는 의미에서 Associa
Rc 타입과 Weak 타입
메모리-참조
2024. 3. 23.
소유권 규칙에 따라 Rust에서 어떤 값은 여러 소유자를 가질 수 없다. Reference Counted를 의미하는 `Rc`는 힙 메모리에 할당된 타입 `T` 값의 소유권을 공유할 수 있게 해주는 타입이다. 즉, 스마트 포인터 `Rc`를 사용하면 타입 `T`의 값에 대한 여러 개의 소유자를 만들 수 있다. 기본적으로, `Rc` 타입은 Clone Trait을 구현하고 있고 clone을 호출해서 `T` 값에 대한 새로운 포인터를 생성하며, 모든 `Rc` 포인터가 해제되면 메모리에 할당된 `T` 값이 drop되는 구조이다. Rust에서 공유된 참조자는 수정할 수 없는데, Rc 타입 또한 예외가 아니며 일반적인 방법으로는 mutable한 참조를 얻을 수 없다. 만약, mutable 한 참조가 필요하면 `Ce
Unwrap
메모리-참조
2024. 3. 23.
unwrap을 호출한 객체는 기본적으로 복사를 수행한다. 복사와 소유권 이동 둘다 가능한 시점에서 복사가 발생한다. rust fn main() { let s = Some(12); let a = s.unwrap(); println!("{}", a); let b = s.unwrap(); println!("{}", b); } 복사를 수행하기 위해서는 해당 타입이 Copy 트레잇을 구현해야 한다. 복사가 안된다면 메모리 소유권 이동이 발생한다. rust struct MyStruct{ x:i32, y:i32, } fn main() { let s = Some(MyStruct { x: 123,
소유권과 Lifetime
메모리-참조
2024. 3. 23.
기본적으로 모든 변수 바인딩은 유효한 “범위(스코프)“를 가지며, 범위 밖에서 변수 사용하면 에러가 발생한다. 스코프가 종료되면 변수는 “삭제(drop)“되었다고 하며 그 변수의 데이터는 메모리에서 해제된다. Rust에서는 스코프가 종료될 때 다른 리소스를 해제하기 위해 소멸자가 호출되도록 하는 것을 변수가 값을 소유한다고 정의한다. 러스트의 각각의 값은 해당값의 오너(owner)라고 불리우는 변수를 갖고 있으며 한번에 딱 하나의 오너만 존재할 수 있다. rust fn main() { let s1: String = String::from("Rust"); let s2: String = s1; } 위 코드는 `"Rust"`라는 String 값에 대한 소유권을 `s1`에서 `
스마트 포인터 활용
메모리-참조
2024. 3. 23.
스마트 포인터(Smart Pointer)는 포인터처럼 작동하지만 추가적인 메타데이터와 능력들도 가지고 있는 데이터 구조이다. `String`과 `Vec`는 스마트 포인터이다. 스마트 포인터는 보통 구조체를 이용하여 구현되어 있다. 스마트 포인터가 일반적인 구조체와 구분되는 특성은 스마트 포인터가 `Deref`와 `Drop` 트레잇을 구현한다는 것이다. `Deref` 트레잇은 스마트 포인터 구조체의 인스턴스가 참조자처럼 동작하도록 하여, 참조자나 스마트 포인터 둘 중 하나와 함께 작동하는 코드를 작성하게 해준다. 스마트 포인터가 평범한 참조자처럼 취급될 수 있도록 구현한다. `Deref`를 구현한 구조체에 대해 `*`로 값을 참조하면, `deref` 함수를 호출한 후 `*`를 한번 호출하는 것으로
Anyhow
예외처리
2024. 3. 23.
Anyhow는 일반화된 Error 타입을 이용해 코드에서 발생하는 에러를 한 가지 타입으로 처리할 수 있게 도와주는 라이브러리이다. Rust에서는 엄격하게 타입을 검사하기 때문에, 여러 라이브러리에서 사용하는 서로 다른 에러 타입을 처리하기 위해서는 `map_err`로 에러를 변환해 통일하거나 `Box`를 이용해 타입을 일반화하거나 타입의 제약조건을 덜어내는 방법을 사용한다. `map_err`을 사용할 때는, 문자열로 에러를 변환하거나 새로운 에러 타입을 만들어 통일한다. rust fn stringify(x: u32) -String { format!("error code: {}", x) } let x: Result = Err(404); x.map_err
조건문과 반복문
rust
2024. 3. 23.
조건문 일반적인 if 조건문은 다른 언어와 비슷하게 사용할 수 있다. rust fn main() { let number = 6; if number % 4 == 0 { println!("number is divisible by 4"); } else if number % 3 == 0 { println!("number is divisible by 3"); } else if number % 2 == 0 { println!("number is divisible by 2"); } else { println!("number is not divisible by 4, 3, or 2"); } } matc
타입과 변수
rust
2024. 3. 23.
변수 정의 변수를 정의할 때는 let 키워드를 사용한다. 타입 추론을 지원하기에 타입 정의 부분을 생략해도 된다. rust let thing1: i32 = 100; let thing2 = 200 + thing1; // mut은 mutable을 의미하는 것으로, 수정 가능한 변수인지를 표현한다. let mut changing_thing = true; changing_thing = false; let (part1, part2) = ("first", "second"); struct Example { a: bool, b: u64, } let Example { a, b: _ } = Example { a: true, b: 10004, }; assert!(a); // 변수
함수와 메서드
rust
2024. 3. 23.
함수 rust fn main() { print_fizzbuzz_to(20); } fn is_divisible(n: u32, divisor: u32) -bool { if divisor == 0 { return false; } n % divisor == 0 } fn fizzbuzz(n: u32) -String { let fizz = if is_divisible(n, 3) { "fizz" } else { "" }; let buzz = if is_divisible(n, 5) { "buzz" } else { "" }; if fizz.is_empty() && buzz.is_empty() { return format!("{n}")