From 82e298ba579ad091935052c4a27fbe05034de400 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]" 가변 참
유효하지 않다고 말해줍니다. 첫 번째 가변 대여는
r1
에 있고,
println!
에서 사용될 때까지 남아있어야 하지만, 이 가변 참조자의
생성과 사용 사이에서 r1
과 같은 데이터를 빌리는 r2
의 가변 참조자를
-만들려고 있습니다.
같은 데이터에 대하여 동시에 여러 가변 참조자의 사용을 막는 이러한 제약은 값의 변경에 대한 제어가 원활하도록 해 줍니다. 대부분의 언어들이 언제든 값 변경을 허용하기 때문에, 러스트에 갓 입문한 사람들에게는 장애물처럼 diff --git a/ch05-01-defining-structs.html b/ch05-01-defining-structs.html index 99e1116d98..1be9f60888 100644 --- a/ch05-01-defining-structs.html +++ b/ch05-01-defining-structs.html @@ -392,14 +392,14 @@
user2
를 생성한
-이후에는 user1
를 더 이상 사용할 수 없는데, 이는 user1
의 username
+이후에는 user1
을 더 이상 사용할 수 없는데, 이는 user1
의 username
필드의 String
이 user2
로 이동되기 때문입니다. user2
에 email
과
username
의 String
모두를 제공하고 user1
에서는 active
와
sign_in_count
값만 사용한다면, user2
를 만든 이후에도 user1
는
diff --git a/ch05-02-example-structs.html b/ch05-02-example-structs.html
index c3d4cb8d0c..2bdfe71201 100644
--- a/ch05-02-example-structs.html
+++ b/ch05-02-example-structs.html
@@ -305,7 +305,7 @@ 프로그램을 디버깅하는 동안 Rectangle
인스턴스 내 모든 필드 값을
-출력해서 확인할 수 있다면 좋을 것 같군요. 예제 5-11는 앞서 다뤄본
+출력해서 확인할 수 있다면 좋을 것 같군요. 예제 5-11은 앞서 다뤄본
println!
매크로를 사용해 본 예시이나,
작동하진 않습니다.
파일명: src/main.rs
diff --git a/ch06-01-defining-an-enum.html b/ch06-01-defining-an-enum.html index 640df63982..1832224967 100644 --- a/ch06-01-defining-an-enum.html +++ b/ch06-01-defining-an-enum.html @@ -196,7 +196,7 @@IpAddrKind
이라는 열거형을 정의하면서 포함할 수 있는 IP 주소인 V4
와 V6
를
+
IpAddrKind
라는 열거형을 정의하면서 포함할 수 있는 IP 주소인 V4
와 V6
를
나열함으로써 이 개념을 코드에 표현할 수 있습니다.
이것들을 열거형의 배리언트라고 합니다:
-enum IpAddrKind { @@ -213,7 +213,7 @@
} fn route(ip_kind: IpAddrKind) {}
이제 IpAddrKind
은 코드 어디에서나 쓸 수 있는 커스텀 데이터 타입이 되었습니다.
이제 IpAddrKind
는 코드 어디에서나 쓸 수 있는 커스텀 데이터 타입이 되었습니다.
아래처럼 IpAddrKind
의 두 개의 배리언트에 대한 인스턴스를 만들 수 있습니다:
-enum IpAddrKind { @@ -295,8 +295,8 @@
열거형 값
String
타입인address
필드를 갖는IpAddr
를 정의했습니다. 그리고 이 구조체의 인스턴스 두 개를 생성했습니다. 첫 번째home
은kind
의 값으로IpAddrKind::V4
를, 연관된 주소 데이터로 -127.0.0.1
를 갖습니다. 두 번째loopback
은IpAddrKind
의 다른 배리언트인 -V6
를 값으로 갖고, 연관된 주소로::1
를 갖습니다.kind
와address
의 +127.0.0.1
을 갖습니다. 두 번째loopback
은IpAddrKind
의 다른 배리언트인 +V6
를 값으로 갖고, 연관된 주소로::1
을 갖습니다.kind
와address
의 값을 함께 사용하기 위해 구조체를 사용했습니다. 그렇게 함으로써 배리언트가 연관된 값을 갖게 되었습니다.각 열거형 배리언트에 데이터를 직접 넣는 방식을 사용해서 열거형을 구조체의 일부로 @@ -317,7 +317,7 @@
열거형 값 없어졌습니다. 또한 여기서 열거형의 동작에 대한 다른 세부 사항을 살펴보기가 좀 더 쉬워졌습니다: 각 열거형 배리언트의 이름이 해당 열거형 인스턴스의 생성자 함수처럼 된다는 것이죠. 즉,
IpAddr::V4()
는String
인수를 -입력받아서IpAddr
타입의 인스턴스를 결과를 만드는 함수입니다. +입력받아서IpAddr
타입의 인스턴스 결과를 만드는 함수입니다. 열거형을 정의한 결과로써 이러한 생성자 함수가 자동적으로 정의됩니다.구조체 대신 열거형을 사용하면 또 다른 장점이 있습니다. diff --git a/print.html b/print.html index 61e8b3d618..326d66831d 100644 --- a/print.html +++ b/print.html @@ -3870,7 +3870,7 @@
가변 참 유효하지 않다고 말해줍니다. 첫 번째 가변 대여는
r1
에 있고,println!
에서 사용될 때까지 남아있어야 하지만, 이 가변 참조자의 생성과 사용 사이에서r1
과 같은 데이터를 빌리는r2
의 가변 참조자를 -만들려고 있습니다. +만들고 있습니다.같은 데이터에 대하여 동시에 여러 가변 참조자의 사용을 막는 이러한 제약은 값의 변경에 대한 제어가 원활하도록 해 줍니다. 대부분의 언어들이 언제든 값 변경을 허용하기 때문에, 러스트에 갓 입문한 사람들에게는 장애물처럼 @@ -4666,14 +4666,14 @@
‘변수와 데이터 간 상호작용 방식: 이동’
절에서 본 것처럼, 이 구문은 데이터를 이동시킵니다. 이 예제에서user2
를 생성한 -이후에는user1
를 더 이상 사용할 수 없는데, 이는user1
의username
+이후에는user1
을 더 이상 사용할 수 없는데, 이는user1
의username
필드의String
이user2
로 이동되기 때문입니다.user2
에username
의String
모두를 제공하고user1
에서는active
와sign_in_count
값만 사용한다면,user2
를 만든 이후에도user1
는 @@ -4927,7 +4927,7 @@< 제공합니다. 명료성 측면에서 승리입니다.
트레이트 파생으로 유용한 기능 추가하기
프로그램을 디버깅하는 동안
Rectangle
인스턴스 내 모든 필드 값을 -출력해서 확인할 수 있다면 좋을 것 같군요. 예제 5-11는 앞서 다뤄본 +출력해서 확인할 수 있다면 좋을 것 같군요. 예제 5-11은 앞서 다뤄본println!
매크로를 사용해 본 예시이나, 작동하진 않습니다.파일명: src/main.rs
@@ -5443,7 +5443,7 @@정리
v4, v6는 근본적으로 IP 주소이기 때문에, 이 둘은 코드에서 모든 종류의 IP 주소에 적용되는 상황을 다룰 때 동일한 타입으로 처리되는 것이 좋습니다. -
IpAddrKind
이라는 열거형을 정의하면서 포함할 수 있는 IP 주소인V4
와V6
를 +
IpAddrKind
라는 열거형을 정의하면서 포함할 수 있는 IP 주소인V4
와V6
를 나열함으로써 이 개념을 코드에 표현할 수 있습니다. 이것들을 열거형의 배리언트라고 합니다:} fn route(ip_kind: IpAddrKind) {}enum IpAddrKind { @@ -5460,7 +5460,7 @@
정리
이제 IpAddrKind
은 코드 어디에서나 쓸 수 있는 커스텀 데이터 타입이 되었습니다.
이제 IpAddrKind
는 코드 어디에서나 쓸 수 있는 커스텀 데이터 타입이 되었습니다.
아래처럼 IpAddrKind
의 두 개의 배리언트에 대한 인스턴스를 만들 수 있습니다:
enum IpAddrKind { @@ -5542,8 +5542,8 @@
열거형 값
String
타입인address
필드를 갖는IpAddr
를 정의했습니다. 그리고 이 구조체의 인스턴스 두 개를 생성했습니다. 첫 번째home
은kind
의 값으로IpAddrKind::V4
를, 연관된 주소 데이터로 -127.0.0.1
를 갖습니다. 두 번째loopback
은IpAddrKind
의 다른 배리언트인 -V6
를 값으로 갖고, 연관된 주소로::1
를 갖습니다.kind
와address
의 +127.0.0.1
을 갖습니다. 두 번째loopback
은IpAddrKind
의 다른 배리언트인 +V6
를 값으로 갖고, 연관된 주소로::1
을 갖습니다.kind
와address
의 값을 함께 사용하기 위해 구조체를 사용했습니다. 그렇게 함으로써 배리언트가 연관된 값을 갖게 되었습니다.각 열거형 배리언트에 데이터를 직접 넣는 방식을 사용해서 열거형을 구조체의 일부로 @@ -5564,7 +5564,7 @@
열거형 값 없어졌습니다. 또한 여기서 열거형의 동작에 대한 다른 세부 사항을 살펴보기가 좀 더 쉬워졌습니다: 각 열거형 배리언트의 이름이 해당 열거형 인스턴스의 생성자 함수처럼 된다는 것이죠. 즉,
IpAddr::V4()
는String
인수를 -입력받아서IpAddr
타입의 인스턴스를 결과를 만드는 함수입니다. +입력받아서IpAddr
타입의 인스턴스 결과를 만드는 함수입니다. 열거형을 정의한 결과로써 이러한 생성자 함수가 자동적으로 정의됩니다.구조체 대신 열거형을 사용하면 또 다른 장점이 있습니다. diff --git a/searchindex.js b/searchindex.js index 1162c3000e..fc363d0551 100644 --- a/searchindex.js +++ b/searchindex.js @@ -1 +1 @@ -Object.assign(window.search, {"doc_urls":["title-page.html#the-rust-programming-language","foreword.html#들어가기에-앞서","ch00-00-introduction.html#소개","ch00-00-introduction.html#러스트는-누구에게-적합할까요","ch00-00-introduction.html#개발팀","ch00-00-introduction.html#학생","ch00-00-introduction.html#회사","ch00-00-introduction.html#오픈-소스-개발자","ch00-00-introduction.html#속도와-안정성을-중시하는-사람","ch00-00-introduction.html#이-책은-어떤-사람을-위한-책인가요","ch00-00-introduction.html#이-책을-어떻게-읽어야-할까요","ch00-00-introduction.html#소스-코드","ch01-00-getting-started.html#시작해봅시다","ch01-01-installation.html#러스트-설치","ch01-01-installation.html#커맨드-라인-표기","ch01-01-installation.html#rustup-설치---linux-및-macos","ch01-01-installation.html#rustup-설치---windows","ch01-01-installation.html#트러블-슈팅","ch01-01-installation.html#업데이트-및-삭제","ch01-01-installation.html#로컬-문서","ch01-02-hello-world.html#hello-world","ch01-02-hello-world.html#프로젝트-디렉터리-생성하기","ch01-02-hello-world.html#러스트-프로그램-작성하고-실행하기","ch01-02-hello-world.html#러스트-프로그램-뜯어보기","ch01-02-hello-world.html#컴파일과-실행은-별개의-과정입니다","ch01-03-hello-cargo.html#카고를-사용해봅시다","ch01-03-hello-cargo.html#카고로-프로젝트-생성하기","ch01-03-hello-cargo.html#카고로-프로젝트를-빌드하고-실행하기","ch01-03-hello-cargo.html#릴리즈-빌드-생성하기","ch01-03-hello-cargo.html#관례로서의-카고","ch01-03-hello-cargo.html#정리","ch02-00-guessing-game-tutorial.html#추리-게임","ch02-00-guessing-game-tutorial.html#새로운-프로젝트를-준비하기","ch02-00-guessing-game-tutorial.html#추릿값을-처리하기","ch02-00-guessing-game-tutorial.html#변수에-값-저장하기","ch02-00-guessing-game-tutorial.html#사용자-입력받기","ch02-00-guessing-game-tutorial.html#result-타입으로-잠재적-실패-다루기","ch02-00-guessing-game-tutorial.html#println-자리표시자를-이용한-값-출력하기","ch02-00-guessing-game-tutorial.html#첫-번째-부분-테스트하기","ch02-00-guessing-game-tutorial.html#비밀번호를-생성하기","ch02-00-guessing-game-tutorial.html#크레이트를-사용하여-더-많은-기능-가져오기","ch02-00-guessing-game-tutorial.html#임의의-숫자-생성하기","ch02-00-guessing-game-tutorial.html#비밀번호와-추릿값을-비교하기","ch02-00-guessing-game-tutorial.html#반복문을-이용하여-여러-번의-추리-허용하기","ch02-00-guessing-game-tutorial.html#정답을-맞힌-후-종료하기","ch02-00-guessing-game-tutorial.html#잘못된-입력값-처리하기","ch02-00-guessing-game-tutorial.html#정리","ch03-00-common-programming-concepts.html#일반적인-프로그래밍-개념","ch03-01-variables-and-mutability.html#변수와-가변성","ch03-01-variables-and-mutability.html#상수","ch03-01-variables-and-mutability.html#섀도잉","ch03-02-data-types.html#데이터-타입","ch03-02-data-types.html#스칼라-타입","ch03-02-data-types.html#복합-타입","ch03-03-how-functions-work.html#함수","ch03-03-how-functions-work.html#매개변수","ch03-03-how-functions-work.html#구문과-표현식","ch03-03-how-functions-work.html#반환-값을-갖는-함수","ch03-04-comments.html#주석","ch03-05-control-flow.html#제어-흐름문","ch03-05-control-flow.html#if-표현식","ch03-05-control-flow.html#반복문을-이용한-반복","ch03-05-control-flow.html#정리","ch04-00-understanding-ownership.html#소유권-이해하기","ch04-01-what-is-ownership.html#소유권이-뭔가요","ch04-01-what-is-ownership.html#스택-영역과-힙-영역","ch04-01-what-is-ownership.html#소유권-규칙","ch04-01-what-is-ownership.html#변수의-스코프","ch04-01-what-is-ownership.html#string-타입","ch04-01-what-is-ownership.html#메모리와-할당","ch04-01-what-is-ownership.html#소유권과-함수","ch04-01-what-is-ownership.html#반환-값과-스코프","ch04-02-references-and-borrowing.html#참조와-대여","ch04-02-references-and-borrowing.html#가변-참조자","ch04-02-references-and-borrowing.html#댕글링-참조","ch04-02-references-and-borrowing.html#참조자-규칙","ch04-03-slices.html#슬라이스","ch04-03-slices.html#문자열-슬라이스","ch04-03-slices.html#그-외-슬라이스","ch04-03-slices.html#정리","ch05-00-structs.html#구조체로-연관된-데이터를-구조화하기","ch05-01-defining-structs.html#구조체-정의-및-인스턴트화","ch05-01-defining-structs.html#필드-초기화-축약법-사용하기","ch05-01-defining-structs.html#기존-인스턴스를-이용해-새-인스턴스를-만들-때-구조체-업데이트-문법-사용하기","ch05-01-defining-structs.html#명명된-필드-없는-튜플-구조체를-사용하여-다른-타입-만들기","ch05-01-defining-structs.html#필드가-없는-유사-유닛-구조체","ch05-01-defining-structs.html#구조체-데이터의-소유권","ch05-02-example-structs.html#구조체를-사용한-예제-프로그램","ch05-02-example-structs.html#튜플로-리팩터링하기","ch05-02-example-structs.html#구조체로-리팩터링하여-코드에-더-많은-의미를-담기","ch05-02-example-structs.html#트레이트-파생으로-유용한-기능-추가하기","ch05-03-method-syntax.html#메서드-문법","ch05-03-method-syntax.html#메서드-정의하기","ch05-03-method-syntax.html#--연산자는-없나요","ch05-03-method-syntax.html#더-많은-매개변수를-가진-메서드","ch05-03-method-syntax.html#연관-함수","ch05-03-method-syntax.html#여러-개의-impl-블록","ch05-03-method-syntax.html#정리","ch06-00-enums.html#열거형과-패턴-매칭","ch06-01-defining-an-enum.html#열거형-정의하기","ch06-01-defining-an-enum.html#열거형-값","ch06-01-defining-an-enum.html#option-열거형이-널-값보다-좋은-점들","ch06-02-match.html#match-제어-흐름-구조","ch06-02-match.html#값을-바인딩하는-패턴","ch06-02-match.html#option를-이용하는-매칭","ch06-02-match.html#매치는-철저합니다","ch06-02-match.html#포괄-패턴과-_-자리표시자","ch06-03-if-let.html#if-let을-사용한-간결한-제어-흐름","ch06-03-if-let.html#정리","ch07-00-managing-growing-projects-with-packages-crates-and-modules.html#커져-가는-프로젝트를-패키지-크레이트-모듈로-관리하기","ch07-01-packages-and-crates.html#패키지와-크레이트","ch07-02-defining-modules-to-control-scope-and-privacy.html#모듈을-정의하여-스코프-및-공개-여부-제어하기","ch07-02-defining-modules-to-control-scope-and-privacy.html#모듈-치트-시트","ch07-02-defining-modules-to-control-scope-and-privacy.html#모듈로-관련된-코드-묶기","ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#경로를-사용하여-모듈-트리의-아이템-참조하기","ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#pub-키워드로-경로-노출하기","ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#super로-시작하는-상대-경로","ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#구조체-열거형을-공개하기","ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#use-키워드로-경로를-스코프-안으로-가져오기","ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#보편적인-use-경로-작성법","ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#as-키워드로-새로운-이름-제공하기","ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#pub-use로-다시-내보내기","ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#외부-패키지-사용하기","ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#중첩-경로를-사용하여-대량의-use-나열을-정리하기","ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#글롭-연산자","ch07-05-separating-modules-into-different-files.html#별개의-파일로-모듈-분리하기","ch07-05-separating-modules-into-different-files.html#대체-파일-경로","ch07-05-separating-modules-into-different-files.html#정리","ch08-00-common-collections.html#일반적인-컬렉션","ch08-01-vectors.html#벡터에-여러-값의-목록-저장하기","ch08-01-vectors.html#새-벡터-만들기","ch08-01-vectors.html#벡터-업데이트하기","ch08-01-vectors.html#벡터-요소-읽기","ch08-01-vectors.html#벡터-값에-대해-반복하기","ch08-01-vectors.html#열거형을-이용해-여러-타입-저장하기","ch08-01-vectors.html#벡터가-버려지면-벡터의-요소도-버려집니다","ch08-02-strings.html#문자열에-utf-8-텍스트-저장하기","ch08-02-strings.html#문자열이-뭔가요","ch08-02-strings.html#새로운-문자열-생성하기","ch08-02-strings.html#문자열-업데이트하기","ch08-02-strings.html#문자열-내부의-인덱싱","ch08-02-strings.html#문자열-슬라이싱하기","ch08-02-strings.html#문자열에-대한-반복을-위한-메서드","ch08-02-strings.html#문자열은-그렇게-단순하지-않습니다","ch08-03-hash-maps.html#해시맵에-서로-연관된-키와-값-저장하기","ch08-03-hash-maps.html#새로운-해시맵-생성하기","ch08-03-hash-maps.html#해시맵의-값-접근하기","ch08-03-hash-maps.html#해시맵과-소유권","ch08-03-hash-maps.html#해시맵-업데이트하기","ch08-03-hash-maps.html#해시-함수","ch08-03-hash-maps.html#정리","ch09-00-error-handling.html#에러-처리","ch09-01-unrecoverable-errors-with-panic.html#panic으로-복구-불가능한-에러-처리하기","ch09-01-unrecoverable-errors-with-panic.html#panic에-대응하여-스택을-되감거나-그만두기","ch09-01-unrecoverable-errors-with-panic.html#panic-백트레이스-이용하기","ch09-02-recoverable-errors-with-result.html#result로-복구-가능한-에러-처리하기","ch09-02-recoverable-errors-with-result.html#서로-다른-에러에-대해-매칭하기","ch09-02-recoverable-errors-with-result.html#result와-match-사용에-대한-대안","ch09-02-recoverable-errors-with-result.html#에러-발생-시-패닉을-위한-숏컷-unwrap과-expect","ch09-02-recoverable-errors-with-result.html#에러-전파하기","ch09-02-recoverable-errors-with-result.html#에러를-전파하기-위한-숏컷-","ch09-02-recoverable-errors-with-result.html#-연산자가-사용될-수-있는-곳","ch09-03-to-panic-or-not-to-panic.html#panic이냐-panic이-아니냐-그것이-문제로다","ch09-03-to-panic-or-not-to-panic.html#예제-프로토타입-코드-그리고-테스트","ch09-03-to-panic-or-not-to-panic.html#여러분이-컴파일러보다-더-많은-정보를-가지고-있을-때","ch09-03-to-panic-or-not-to-panic.html#에러-처리를-위한-가이드라인","ch09-03-to-panic-or-not-to-panic.html#유효성을-위한-커스텀-타입-생성하기","ch09-03-to-panic-or-not-to-panic.html#정리","ch10-00-generics.html#제네릭-타입-트레이트-라이프타임","ch10-00-generics.html#함수를-추출하여-중복-없애기","ch10-01-syntax.html#제네릭-데이터-타입","ch10-01-syntax.html#제네릭-함수-정의","ch10-01-syntax.html#제네릭-구조체-정의","ch10-01-syntax.html#제네릭-열거형-정의","ch10-01-syntax.html#제네릭-메서드-정의","ch10-01-syntax.html#제네릭-코드의-성능","ch10-02-traits.html#트레이트로-공통된-동작을-정의하기","ch10-02-traits.html#트레이트-정의하기","ch10-02-traits.html#특정-타입에-트레이트-구현하기","ch10-02-traits.html#기본-구현","ch10-02-traits.html#매개변수로서의-트레이트","ch10-02-traits.html#트레이트를-구현하는-타입을-반환하기","ch10-02-traits.html#트레이트-바운드를-사용해-조건부로-메서드-구현하기","ch10-03-lifetime-syntax.html#라이프타임으로-참조자의-유효성-검증하기","ch10-03-lifetime-syntax.html#라이프타임으로-댕글링-참조-방지하기","ch10-03-lifetime-syntax.html#대여-검사기","ch10-03-lifetime-syntax.html#함수에서의-제네릭-라이프타임","ch10-03-lifetime-syntax.html#라이프타임-명시-문법","ch10-03-lifetime-syntax.html#함수-시그니처에서-라이프타임-명시하기","ch10-03-lifetime-syntax.html#라이프타임의-측면에서-생각하기","ch10-03-lifetime-syntax.html#구조체-정의에서-라이프타임-명시하기","ch10-03-lifetime-syntax.html#라이프타임-생략","ch10-03-lifetime-syntax.html#메서드-정의에서-라이프타임-명시하기","ch10-03-lifetime-syntax.html#정적-라이프타임","ch10-03-lifetime-syntax.html#제네릭-타입-매개변수-트레이트-바운드-라이프타임을-한-곳에-사용해-보기","ch10-03-lifetime-syntax.html#정리","ch11-00-testing.html#자동화-테스트-작성하기","ch11-01-writing-tests.html#테스트-작성-방법","ch11-01-writing-tests.html#테스트-함수-파헤치기","ch11-01-writing-tests.html#assert-매크로로-결과-검사하기","ch11-01-writing-tests.html#assert_eq-assert_ne-매크로를-이용한-동등-테스트","ch11-01-writing-tests.html#커스텀-실패-메시지-추가하기","ch11-01-writing-tests.html#should_panic-매크로로-패닉-발생-검사하기","ch11-01-writing-tests.html#result를-이용한-테스트","ch11-02-running-tests.html#테스트-실행-방법-제어하기","ch11-02-running-tests.html#테스트를-병렬-혹은-순차적으로-실행하기","ch11-02-running-tests.html#함수-출력-표시하기","ch11-02-running-tests.html#이름을-지정해-일부-테스트만-실행하기","ch11-02-running-tests.html#특별-요청이-없다면-일부-테스트-무시하기","ch11-03-test-organization.html#테스트-조직화","ch11-03-test-organization.html#유닛-테스트","ch11-03-test-organization.html#통합-테스트","ch11-03-test-organization.html#정리","ch12-00-an-io-project.html#io-프로젝트-커맨드-라인-프로그램-만들기","ch12-01-accepting-command-line-arguments.html#커맨드-라인-인수-받기","ch12-01-accepting-command-line-arguments.html#인수-값-읽기","ch12-01-accepting-command-line-arguments.html#args-함수와-유효하지-않은-유니코드","ch12-01-accepting-command-line-arguments.html#인수-값들을-변수에-저장하기","ch12-02-reading-a-file.html#파일-읽기","ch12-03-improving-error-handling-and-modularity.html#모듈성과-에러-처리-향상을-위한-리팩터링","ch12-03-improving-error-handling-and-modularity.html#바이너리-프로젝트에-대한-관심사-분리","ch12-03-improving-error-handling-and-modularity.html#clone을-사용한-절충안","ch12-03-improving-error-handling-and-modularity.html#에러-처리-수정","ch12-03-improving-error-handling-and-modularity.html#main으로부터-로직-추출하기","ch12-03-improving-error-handling-and-modularity.html#라이브러리-크레이트로-코드-쪼개기","ch12-04-testing-the-librarys-functionality.html#테스트-주도-개발로-라이브러리-기능-개발하기","ch12-04-testing-the-librarys-functionality.html#실패하는-테스트-작성하기","ch12-04-testing-the-librarys-functionality.html#테스트를-통과하도록-코드-작성하기","ch12-05-working-with-environment-variables.html#환경-변수-사용하기","ch12-05-working-with-environment-variables.html#대소문자를-구분하지-않는-search-함수에-대한-실패하는-테스트-작성하기","ch12-05-working-with-environment-variables.html#search_case_insensitive-함수-구현하기","ch12-06-writing-to-stderr-instead-of-stdout.html#표준-출력-대신-표준-에러로-에러-메시지-작성하기","ch12-06-writing-to-stderr-instead-of-stdout.html#에러가-기록되었는지-검사하기","ch12-06-writing-to-stderr-instead-of-stdout.html#표준-에러로-에러-출력하기","ch12-06-writing-to-stderr-instead-of-stdout.html#정리","ch13-00-functional-features.html#함수형-언어의-특성-반복자와-클로저","ch13-01-closures.html#클로저-자신의-환경을-캡처하는-익명-함수","ch13-01-closures.html#클로저로-환경-캡처하기","ch13-01-closures.html#클로저-타입-추론과-명시","ch13-01-closures.html#참조자를-캡처하거나-소유권-이동하기","ch13-01-closures.html#캡처된-값을-클로저-밖으로-이동하기와-fn-트레이트","ch13-02-iterators.html#반복자로-일련의-아이템들-처리하기","ch13-02-iterators.html#iterator-트레이트와-next-메서드","ch13-02-iterators.html#반복자를-소비하는-메서드","ch13-02-iterators.html#다른-반복자를-생성하는-메서드","ch13-02-iterators.html#환경을-캡처하는-클로저-사용하기","ch13-03-improving-our-io-project.html#io-프로젝트-개선하기","ch13-03-improving-our-io-project.html#반복자를-사용하여-clone-제거하기","ch13-03-improving-our-io-project.html#반복자-어댑터로-더-간결한-코드-만들기","ch13-03-improving-our-io-project.html#루프와-반복자-중-선택하기","ch13-04-performance.html#성능-비교하기-루프-vs-반복자","ch13-04-performance.html#정리","ch14-00-more-about-cargo.html#카고와-cratesio-더-알아보기","ch14-01-release-profiles.html#릴리즈-프로필을-통한-빌드-커스터마이징하기","ch14-02-publishing-to-crates-io.html#cratesio에-크레이트-배포하기","ch14-02-publishing-to-crates-io.html#유용한-문서화-주석-만들기","ch14-02-publishing-to-crates-io.html#pub-use로-편리한-공개-api-내보내기","ch14-02-publishing-to-crates-io.html#cartesio-계정-설정하기","ch14-02-publishing-to-crates-io.html#새-크레이트에-메타데이터-추가하기","ch14-02-publishing-to-crates-io.html#cratesio에-배포하기","ch14-02-publishing-to-crates-io.html#이미-존재하는-크레이트의-새-버전-배포하기","ch14-02-publishing-to-crates-io.html#cargo-yank로-cratesio에서-버전-사용하지-않게-하기","ch14-03-cargo-workspaces.html#카고-작업공간","ch14-03-cargo-workspaces.html#작업공간-생성하기","ch14-03-cargo-workspaces.html#작업공간에-두-번째-패키지-생성하기","ch14-04-installing-binaries.html#cargo-install로-cratesio에-있는-바이너리-설치하기","ch14-05-extending-cargo.html#커스텀-명령어로-카고-확장하기","ch14-05-extending-cargo.html#정리","ch15-00-smart-pointers.html#스마트-포인터","ch15-01-box.html#box를-사용하여-힙에-있는-데이터-가리키기","ch15-01-box.html#box을-사용하여-힙에-데이터-저장하기","ch15-01-box.html#박스로-재귀적-타입-가능하게-하기","ch15-02-deref.html#deref-트레이트로-스마트-포인터를-보통의-참조자처럼-취급하기","ch15-02-deref.html#포인터를-따라가서-값-얻기","ch15-02-deref.html#box를-참조자처럼-사용하기","ch15-02-deref.html#자체-스마트-포인터-정의하기","ch15-02-deref.html#deref-트레이트를-구현하여-임의의-타입을-참조자처럼-다루기","ch15-02-deref.html#함수와-메서드를-이용한-암묵적-역참조-강제","ch15-02-deref.html#역참조-강제가-가변성과-상호작용하는-법","ch15-03-drop.html#drop-트레이트로-메모리-정리-코드-실행하기","ch15-03-drop.html#stdmemdrop으로-값을-일찍-버리기","ch15-04-rc.html#rc-참조-카운트-스마트-포인터","ch15-04-rc.html#rc를-사용하여-데이터-공유하기","ch15-04-rc.html#rc를-클론하는-것은-참조-카운트를-증가시킵니다","ch15-05-interior-mutability.html#refcell와-내부-가변성-패턴","ch15-05-interior-mutability.html#refcell으로-런타임에-대여-규칙-집행하기","ch15-05-interior-mutability.html#내부-가변성-불변값에-대한-가변-대여","ch15-05-interior-mutability.html#rc와-refcell를-조합하여-가변-데이터의-복수-소유자-만들기","ch15-06-reference-cycles.html#순환-참조는-메모리-누수를-발생시킬-수-있습니다","ch15-06-reference-cycles.html#순환-참조-만들기","ch15-06-reference-cycles.html#순환-참조-방지하기-rc를-weak로-바꾸기","ch15-06-reference-cycles.html#정리","ch16-00-concurrency.html#겁-없는-동시성","ch16-01-threads.html#스레드를-이용하여-코드를-동시에-실행하기","ch16-01-threads.html#spawn으로-새로운-스레드-생성하기","ch16-01-threads.html#join-핸들을-사용하여-모든-스레드가-끝날-때까지-기다리기","ch16-01-threads.html#스레드에-move-클로저-사용하기","ch16-02-message-passing.html#메시지-패싱을-사용하여-스레드-간-데이터-전송하기","ch16-02-message-passing.html#채널과-소유권-이동","ch16-02-message-passing.html#여러-값-보내기와-수신자가-기다리는지-알아보기","ch16-02-message-passing.html#송신자를-복제하여-여러-생산자-만들기","ch16-03-shared-state.html#공유-상태-동시성","ch16-03-shared-state.html#뮤텍스를-사용하여-한번에-한-스레드에서의-데이터-접근을-허용하기","ch16-03-shared-state.html#refcellrc와-mutexarc-간의-유사성","ch16-04-extensible-concurrency-sync-and-send.html#sync와-send-트레이트를-이용한-확장-가능한-동시성","ch16-04-extensible-concurrency-sync-and-send.html#send를-사용하여-스레드-사이에-소유권-이동을-허용하기","ch16-04-extensible-concurrency-sync-and-send.html#sync를-사용하여-여러-스레드로부터의-접근을-허용하기","ch16-04-extensible-concurrency-sync-and-send.html#send와-sync를-손수-구현하는-것은-안전하지-않습니다","ch16-04-extensible-concurrency-sync-and-send.html#정리","ch17-00-oop.html#러스트의-객체-지향-프로그래밍-기능들","ch17-01-what-is-oo.html#객체-지향-언어의-특성","ch17-01-what-is-oo.html#객체는-데이터와-동작을-담습니다","ch17-01-what-is-oo.html#상세-구현을-은닉하는-캡슐화","ch17-01-what-is-oo.html#타입-시스템과-코드-공유로서의-상속","ch17-01-what-is-oo.html#다형성","ch17-02-trait-objects.html#트레이트-객체를-사용하여-다른-타입의-값-허용하기","ch17-02-trait-objects.html#공통된-동작을-위한-트레이트-정의하기","ch17-02-trait-objects.html#트레이트-구현하기","ch17-02-trait-objects.html#트레이트-객체는-동적-디스패치를-수행합니다","ch17-03-oo-design-patterns.html#객체-지향-디자인-패턴-구현하기","ch17-03-oo-design-patterns.html#post를-정의하고-초안-상태의-새-인스턴스-생성하기","ch17-03-oo-design-patterns.html#게시물-콘텐츠의-텍스트-저장하기","ch17-03-oo-design-patterns.html#초안-게시물의-내용이-비어있음을-보장하기","ch17-03-oo-design-patterns.html#게시물에-대한-검토-요청이-게시물의-상태를-변경합니다","ch17-03-oo-design-patterns.html#content의-동작을-변경하는-approve-메서드-추가하기","ch17-03-oo-design-patterns.html#상태-패턴의-장단점","ch17-03-oo-design-patterns.html#정리","ch18-00-patterns.html#패턴과-매칭","ch18-01-all-the-places-for-patterns.html#패턴이-사용될-수-있는-모든-곳","ch18-01-all-the-places-for-patterns.html#match-갈래","ch18-01-all-the-places-for-patterns.html#if-let-조건-표현식","ch18-01-all-the-places-for-patterns.html#while-let-조건-루프","ch18-01-all-the-places-for-patterns.html#for-루프","ch18-01-all-the-places-for-patterns.html#let-구문","ch18-01-all-the-places-for-patterns.html#함수-매개변수","ch18-02-refutability.html#반박-가능성-패턴이-매칭에-실패할지의-여부","ch18-03-pattern-syntax.html#패턴-문법","ch18-03-pattern-syntax.html#리터럴-매칭","ch18-03-pattern-syntax.html#명명된-변수-매칭","ch18-03-pattern-syntax.html#다중-패턴","ch18-03-pattern-syntax.html#를-이용한-값의-범위-매칭","ch18-03-pattern-syntax.html#값을-해체하여-분리하기","ch18-03-pattern-syntax.html#패턴에서-값-무시하기","ch18-03-pattern-syntax.html#매치-가드를-사용한-추가-조건","ch18-03-pattern-syntax.html#-바인딩","ch18-03-pattern-syntax.html#정리","ch19-00-advanced-features.html#고급-기능","ch19-01-unsafe-rust.html#안전하지-않은-러스트","ch19-01-unsafe-rust.html#안전하지-않은-슈퍼파워","ch19-01-unsafe-rust.html#원시-포인터-역참조하기","ch19-01-unsafe-rust.html#안전하지-않은-함수-또는-메서드-호출하기","ch19-01-unsafe-rust.html#가변-정적-변수의-접근-혹은-수정하기","ch19-01-unsafe-rust.html#안전하지-않은-트레이트-구현하기","ch19-01-unsafe-rust.html#유니온-필드에-접근하기","ch19-01-unsafe-rust.html#unsafe-코드를-사용하는-경우","ch19-03-advanced-traits.html#고급-트레이트","ch19-03-advanced-traits.html#연관-타입으로-트레이트-정의에서-자리표시자-타입-지정하기","ch19-03-advanced-traits.html#기본-제네릭-타입-매개변수와-연산자-오버로딩","ch19-03-advanced-traits.html#모호성-방지를-위한-완전-정규화-문법-같은-이름의-메서드-호출하기","ch19-03-advanced-traits.html#슈퍼트레이트를-사용하여-한-트레이트에서-다른-트레이트의-기능을-요구하기","ch19-03-advanced-traits.html#뉴타입-패턴을-사용하여-외부-타입에-외부-트레이트-구현하기","ch19-04-advanced-types.html#고급-타입","ch19-04-advanced-types.html#타입-안전성과-추상화를-위한-뉴타입-패턴-사용하기","ch19-04-advanced-types.html#타입-별칭으로-타입의-동의어-만들기","ch19-04-advanced-types.html#절대-반환하지-않는-부정-타입","ch19-04-advanced-types.html#동적-크기-타입과-sized-트레이트","ch19-05-advanced-functions-and-closures.html#고급-함수와-클로저","ch19-05-advanced-functions-and-closures.html#함수-포인터","ch19-05-advanced-functions-and-closures.html#클로저-반환하기","ch19-06-macros.html#매크로","ch19-06-macros.html#매크로와-함수의-차이","ch19-06-macros.html#일반적인-메타프로그래밍을-위한-macro_rules를-사용한-선언적-매크로","ch19-06-macros.html#속성에서-코드를-생성하기-위한-절차적-매크로","ch19-06-macros.html#커스텀-derive-매크로-작성-방법","ch19-06-macros.html#속성형-매크로","ch19-06-macros.html#함수형-매크로","ch19-06-macros.html#정리","ch20-00-final-project-a-web-server.html#최종-프로젝트-멀티스레드-웹-서버-구축하기","ch20-01-single-threaded.html#싱글스레드-웹-서버-구축하기","ch20-01-single-threaded.html#tcp-연결-수신-대기하기","ch20-01-single-threaded.html#요청-읽기","ch20-01-single-threaded.html#http-요청-자세히-살펴보기","ch20-01-single-threaded.html#응답-작성하기","ch20-01-single-threaded.html#실제-html-반환하기","ch20-01-single-threaded.html#요청의-유효성-검사와-선택적-응답","ch20-01-single-threaded.html#리팩터링","ch20-02-multithreaded.html#싱글스레드-서버를-멀티스레드-서버로-바꾸기","ch20-02-multithreaded.html#현재의-서버-구현에서-느린-요청-시뮬레이션","ch20-02-multithreaded.html#스레드-풀로-처리량-개선하기","ch20-03-graceful-shutdown-and-cleanup.html#우아한-종료와-정리","ch20-03-graceful-shutdown-and-cleanup.html#threadpool에-대한-drop-트레이트-구현하기","ch20-03-graceful-shutdown-and-cleanup.html#작업을-기다리는-스레드에게-정지-신호-보내기","ch20-03-graceful-shutdown-and-cleanup.html#정리","appendix-00.html#부록","appendix-01-keywords.html#부록-a-키워드","appendix-01-keywords.html#현재-사용중인-키워드","appendix-01-keywords.html#미래에-사용하기-위해-예약된-키워드","appendix-01-keywords.html#원시-식별자","appendix-02-operators.html#부록-b-연산자와-기호","appendix-02-operators.html#연산자","appendix-02-operators.html#비연산자-기호","appendix-03-derivable-traits.html#부록-c-파생-가능한-트레이트","appendix-03-derivable-traits.html#프로그래머-출력을-위한-debug","appendix-03-derivable-traits.html#동등-비교를-위한-partialeq-및-eq","appendix-03-derivable-traits.html#순서-비교를-위한-partialord-및-ord","appendix-03-derivable-traits.html#값을-복제하기-위한-clone과-copy","appendix-03-derivable-traits.html#어떤-값을-고정-크기의-값으로-매핑하기-위한-hash","appendix-03-derivable-traits.html#기본값을-위한-default","appendix-04-useful-development-tools.html#부록-d---유용한-개발-도구","appendix-04-useful-development-tools.html#rustfmt로-자동-포맷팅하기","appendix-04-useful-development-tools.html#rustfix로-코드-수정하기","appendix-04-useful-development-tools.html#clippy로-더-많은-린트-사용하기","appendix-04-useful-development-tools.html#rust-analyzer를-사용한-ide-통합","appendix-05-editions.html#부록-e---에디션","appendix-06-translation.html#부록-f-번역본","appendix-07-nightly-rust.html#부록-g---러스트가-만들어지는-과정과-nightly-러스트","appendix-07-nightly-rust.html#정체되지-않는-안정성","appendix-07-nightly-rust.html#칙칙폭폭-릴리즈-채널과-기차-타기","appendix-07-nightly-rust.html#불안정한-기능","appendix-07-nightly-rust.html#rustup과-러스트-nightly의-역할","appendix-07-nightly-rust.html#rfc-과정과-팀"],"index":{"documentStore":{"docInfo":{"0":{"body":22,"breadcrumbs":6,"title":3},"1":{"body":6,"breadcrumbs":0,"title":0},"10":{"body":49,"breadcrumbs":0,"title":0},"100":{"body":234,"breadcrumbs":0,"title":0},"101":{"body":142,"breadcrumbs":1,"title":1},"102":{"body":75,"breadcrumbs":2,"title":1},"103":{"body":75,"breadcrumbs":1,"title":0},"104":{"body":114,"breadcrumbs":2,"title":1},"105":{"body":88,"breadcrumbs":1,"title":0},"106":{"body":69,"breadcrumbs":2,"title":1},"107":{"body":110,"breadcrumbs":0,"title":0},"108":{"body":4,"breadcrumbs":0,"title":0},"109":{"body":3,"breadcrumbs":0,"title":0},"11":{"body":1,"breadcrumbs":0,"title":0},"110":{"body":50,"breadcrumbs":0,"title":0},"111":{"body":4,"breadcrumbs":0,"title":0},"112":{"body":77,"breadcrumbs":0,"title":0},"113":{"body":72,"breadcrumbs":0,"title":0},"114":{"body":129,"breadcrumbs":0,"title":0},"115":{"body":158,"breadcrumbs":1,"title":1},"116":{"body":31,"breadcrumbs":1,"title":1},"117":{"body":94,"breadcrumbs":0,"title":0},"118":{"body":126,"breadcrumbs":2,"title":1},"119":{"body":80,"breadcrumbs":2,"title":1},"12":{"body":6,"breadcrumbs":0,"title":0},"120":{"body":31,"breadcrumbs":1,"title":0},"121":{"body":46,"breadcrumbs":3,"title":2},"122":{"body":57,"breadcrumbs":1,"title":0},"123":{"body":128,"breadcrumbs":2,"title":1},"124":{"body":7,"breadcrumbs":1,"title":0},"125":{"body":72,"breadcrumbs":0,"title":0},"126":{"body":16,"breadcrumbs":0,"title":0},"127":{"body":2,"breadcrumbs":0,"title":0},"128":{"body":10,"breadcrumbs":0,"title":0},"129":{"body":1,"breadcrumbs":0,"title":0},"13":{"body":6,"breadcrumbs":0,"title":0},"130":{"body":44,"breadcrumbs":0,"title":0},"131":{"body":20,"breadcrumbs":0,"title":0},"132":{"body":142,"breadcrumbs":0,"title":0},"133":{"body":35,"breadcrumbs":0,"title":0},"134":{"body":25,"breadcrumbs":0,"title":0},"135":{"body":15,"breadcrumbs":0,"title":0},"136":{"body":7,"breadcrumbs":4,"title":2},"137":{"body":15,"breadcrumbs":2,"title":0},"138":{"body":89,"breadcrumbs":2,"title":0},"139":{"body":171,"breadcrumbs":2,"title":0},"14":{"body":1,"breadcrumbs":0,"title":0},"140":{"body":185,"breadcrumbs":2,"title":0},"141":{"body":42,"breadcrumbs":2,"title":0},"142":{"body":15,"breadcrumbs":2,"title":0},"143":{"body":8,"breadcrumbs":2,"title":0},"144":{"body":11,"breadcrumbs":0,"title":0},"145":{"body":24,"breadcrumbs":0,"title":0},"146":{"body":50,"breadcrumbs":0,"title":0},"147":{"body":27,"breadcrumbs":0,"title":0},"148":{"body":100,"breadcrumbs":0,"title":0},"149":{"body":11,"breadcrumbs":0,"title":0},"15":{"body":29,"breadcrumbs":3,"title":3},"150":{"body":21,"breadcrumbs":0,"title":0},"151":{"body":9,"breadcrumbs":0,"title":0},"152":{"body":3,"breadcrumbs":2,"title":1},"153":{"body":52,"breadcrumbs":2,"title":1},"154":{"body":126,"breadcrumbs":2,"title":1},"155":{"body":133,"breadcrumbs":2,"title":1},"156":{"body":62,"breadcrumbs":1,"title":0},"157":{"body":36,"breadcrumbs":4,"title":3},"158":{"body":82,"breadcrumbs":3,"title":2},"159":{"body":92,"breadcrumbs":1,"title":0},"16":{"body":17,"breadcrumbs":2,"title":2},"160":{"body":111,"breadcrumbs":1,"title":0},"161":{"body":215,"breadcrumbs":1,"title":0},"162":{"body":8,"breadcrumbs":4,"title":2},"163":{"body":7,"breadcrumbs":2,"title":0},"164":{"body":36,"breadcrumbs":2,"title":0},"165":{"body":14,"breadcrumbs":2,"title":0},"166":{"body":155,"breadcrumbs":2,"title":0},"167":{"body":7,"breadcrumbs":2,"title":0},"168":{"body":15,"breadcrumbs":0,"title":0},"169":{"body":152,"breadcrumbs":0,"title":0},"17":{"body":23,"breadcrumbs":0,"title":0},"170":{"body":0,"breadcrumbs":0,"title":0},"171":{"body":184,"breadcrumbs":0,"title":0},"172":{"body":149,"breadcrumbs":0,"title":0},"173":{"body":35,"breadcrumbs":0,"title":0},"174":{"body":189,"breadcrumbs":0,"title":0},"175":{"body":30,"breadcrumbs":0,"title":0},"176":{"body":5,"breadcrumbs":0,"title":0},"177":{"body":29,"breadcrumbs":0,"title":0},"178":{"body":133,"breadcrumbs":0,"title":0},"179":{"body":233,"breadcrumbs":0,"title":0},"18":{"body":7,"breadcrumbs":0,"title":0},"180":{"body":177,"breadcrumbs":0,"title":0},"181":{"body":195,"breadcrumbs":0,"title":0},"182":{"body":72,"breadcrumbs":0,"title":0},"183":{"body":2,"breadcrumbs":0,"title":0},"184":{"body":88,"breadcrumbs":0,"title":0},"185":{"body":47,"breadcrumbs":0,"title":0},"186":{"body":128,"breadcrumbs":0,"title":0},"187":{"body":7,"breadcrumbs":0,"title":0},"188":{"body":185,"breadcrumbs":0,"title":0},"189":{"body":90,"breadcrumbs":0,"title":0},"19":{"body":8,"breadcrumbs":0,"title":0},"190":{"body":37,"breadcrumbs":0,"title":0},"191":{"body":122,"breadcrumbs":0,"title":0},"192":{"body":84,"breadcrumbs":0,"title":0},"193":{"body":15,"breadcrumbs":0,"title":0},"194":{"body":45,"breadcrumbs":0,"title":0},"195":{"body":3,"breadcrumbs":0,"title":0},"196":{"body":16,"breadcrumbs":0,"title":0},"197":{"body":3,"breadcrumbs":0,"title":0},"198":{"body":331,"breadcrumbs":0,"title":0},"199":{"body":422,"breadcrumbs":1,"title":1},"2":{"body":14,"breadcrumbs":0,"title":0},"20":{"body":11,"breadcrumbs":4,"title":2},"200":{"body":230,"breadcrumbs":2,"title":2},"201":{"body":202,"breadcrumbs":0,"title":0},"202":{"body":425,"breadcrumbs":1,"title":1},"203":{"body":43,"breadcrumbs":2,"title":2},"204":{"body":19,"breadcrumbs":0,"title":0},"205":{"body":9,"breadcrumbs":0,"title":0},"206":{"body":214,"breadcrumbs":0,"title":0},"207":{"body":198,"breadcrumbs":0,"title":0},"208":{"body":162,"breadcrumbs":0,"title":0},"209":{"body":4,"breadcrumbs":0,"title":0},"21":{"body":28,"breadcrumbs":2,"title":0},"210":{"body":69,"breadcrumbs":0,"title":0},"211":{"body":359,"breadcrumbs":0,"title":0},"212":{"body":1,"breadcrumbs":0,"title":0},"213":{"body":31,"breadcrumbs":2,"title":1},"214":{"body":26,"breadcrumbs":1,"title":0},"215":{"body":30,"breadcrumbs":1,"title":0},"216":{"body":55,"breadcrumbs":2,"title":1},"217":{"body":51,"breadcrumbs":1,"title":0},"218":{"body":112,"breadcrumbs":1,"title":0},"219":{"body":13,"breadcrumbs":1,"title":0},"22":{"body":37,"breadcrumbs":2,"title":0},"220":{"body":145,"breadcrumbs":1,"title":0},"221":{"body":91,"breadcrumbs":2,"title":1},"222":{"body":350,"breadcrumbs":1,"title":0},"223":{"body":332,"breadcrumbs":2,"title":1},"224":{"body":120,"breadcrumbs":1,"title":0},"225":{"body":10,"breadcrumbs":1,"title":0},"226":{"body":317,"breadcrumbs":1,"title":0},"227":{"body":523,"breadcrumbs":1,"title":0},"228":{"body":1,"breadcrumbs":1,"title":0},"229":{"body":131,"breadcrumbs":2,"title":1},"23":{"body":21,"breadcrumbs":2,"title":0},"230":{"body":754,"breadcrumbs":2,"title":1},"231":{"body":8,"breadcrumbs":1,"title":0},"232":{"body":12,"breadcrumbs":1,"title":0},"233":{"body":52,"breadcrumbs":1,"title":0},"234":{"body":1,"breadcrumbs":1,"title":0},"235":{"body":2,"breadcrumbs":0,"title":0},"236":{"body":0,"breadcrumbs":0,"title":0},"237":{"body":143,"breadcrumbs":0,"title":0},"238":{"body":155,"breadcrumbs":0,"title":0},"239":{"body":169,"breadcrumbs":0,"title":0},"24":{"body":55,"breadcrumbs":2,"title":0},"240":{"body":302,"breadcrumbs":1,"title":1},"241":{"body":37,"breadcrumbs":0,"title":0},"242":{"body":66,"breadcrumbs":2,"title":2},"243":{"body":38,"breadcrumbs":0,"title":0},"244":{"body":95,"breadcrumbs":0,"title":0},"245":{"body":81,"breadcrumbs":0,"title":0},"246":{"body":4,"breadcrumbs":2,"title":1},"247":{"body":586,"breadcrumbs":2,"title":1},"248":{"body":265,"breadcrumbs":1,"title":0},"249":{"body":4,"breadcrumbs":1,"title":0},"25":{"body":8,"breadcrumbs":0,"title":0},"250":{"body":70,"breadcrumbs":2,"title":1},"251":{"body":2,"breadcrumbs":1,"title":0},"252":{"body":3,"breadcrumbs":2,"title":1},"253":{"body":74,"breadcrumbs":1,"title":0},"254":{"body":4,"breadcrumbs":3,"title":1},"255":{"body":148,"breadcrumbs":2,"title":0},"256":{"body":251,"breadcrumbs":5,"title":3},"257":{"body":17,"breadcrumbs":3,"title":1},"258":{"body":102,"breadcrumbs":2,"title":0},"259":{"body":34,"breadcrumbs":3,"title":1},"26":{"body":84,"breadcrumbs":0,"title":0},"260":{"body":7,"breadcrumbs":2,"title":0},"261":{"body":28,"breadcrumbs":5,"title":3},"262":{"body":2,"breadcrumbs":1,"title":0},"263":{"body":50,"breadcrumbs":1,"title":0},"264":{"body":411,"breadcrumbs":1,"title":0},"265":{"body":61,"breadcrumbs":7,"title":3},"266":{"body":9,"breadcrumbs":1,"title":0},"267":{"body":2,"breadcrumbs":1,"title":0},"268":{"body":27,"breadcrumbs":0,"title":0},"269":{"body":7,"breadcrumbs":2,"title":1},"27":{"body":104,"breadcrumbs":0,"title":0},"270":{"body":24,"breadcrumbs":2,"title":1},"271":{"body":259,"breadcrumbs":1,"title":0},"272":{"body":12,"breadcrumbs":2,"title":1},"273":{"body":99,"breadcrumbs":1,"title":0},"274":{"body":32,"breadcrumbs":2,"title":1},"275":{"body":96,"breadcrumbs":1,"title":0},"276":{"body":82,"breadcrumbs":2,"title":1},"277":{"body":139,"breadcrumbs":1,"title":0},"278":{"body":22,"breadcrumbs":1,"title":0},"279":{"body":97,"breadcrumbs":2,"title":1},"28":{"body":5,"breadcrumbs":0,"title":0},"280":{"body":186,"breadcrumbs":2,"title":1},"281":{"body":17,"breadcrumbs":2,"title":1},"282":{"body":171,"breadcrumbs":2,"title":1},"283":{"body":115,"breadcrumbs":2,"title":1},"284":{"body":7,"breadcrumbs":2,"title":1},"285":{"body":28,"breadcrumbs":2,"title":1},"286":{"body":735,"breadcrumbs":1,"title":0},"287":{"body":125,"breadcrumbs":3,"title":2},"288":{"body":5,"breadcrumbs":0,"title":0},"289":{"body":245,"breadcrumbs":0,"title":0},"29":{"body":10,"breadcrumbs":0,"title":0},"290":{"body":415,"breadcrumbs":2,"title":2},"291":{"body":6,"breadcrumbs":0,"title":0},"292":{"body":13,"breadcrumbs":0,"title":0},"293":{"body":6,"breadcrumbs":0,"title":0},"294":{"body":74,"breadcrumbs":1,"title":1},"295":{"body":201,"breadcrumbs":1,"title":1},"296":{"body":260,"breadcrumbs":1,"title":1},"297":{"body":106,"breadcrumbs":0,"title":0},"298":{"body":99,"breadcrumbs":0,"title":0},"299":{"body":46,"breadcrumbs":0,"title":0},"3":{"body":0,"breadcrumbs":0,"title":0},"30":{"body":8,"breadcrumbs":0,"title":0},"300":{"body":58,"breadcrumbs":0,"title":0},"301":{"body":3,"breadcrumbs":0,"title":0},"302":{"body":363,"breadcrumbs":0,"title":0},"303":{"body":19,"breadcrumbs":2,"title":2},"304":{"body":3,"breadcrumbs":4,"title":2},"305":{"body":20,"breadcrumbs":3,"title":1},"306":{"body":22,"breadcrumbs":3,"title":1},"307":{"body":8,"breadcrumbs":4,"title":2},"308":{"body":3,"breadcrumbs":2,"title":0},"309":{"body":10,"breadcrumbs":0,"title":0},"31":{"body":6,"breadcrumbs":0,"title":0},"310":{"body":6,"breadcrumbs":0,"title":0},"311":{"body":24,"breadcrumbs":0,"title":0},"312":{"body":112,"breadcrumbs":0,"title":0},"313":{"body":9,"breadcrumbs":0,"title":0},"314":{"body":3,"breadcrumbs":0,"title":0},"315":{"body":29,"breadcrumbs":0,"title":0},"316":{"body":120,"breadcrumbs":0,"title":0},"317":{"body":241,"breadcrumbs":0,"title":0},"318":{"body":10,"breadcrumbs":0,"title":0},"319":{"body":48,"breadcrumbs":0,"title":0},"32":{"body":59,"breadcrumbs":0,"title":0},"320":{"body":66,"breadcrumbs":1,"title":1},"321":{"body":61,"breadcrumbs":0,"title":0},"322":{"body":54,"breadcrumbs":0,"title":0},"323":{"body":132,"breadcrumbs":0,"title":0},"324":{"body":440,"breadcrumbs":2,"title":2},"325":{"body":261,"breadcrumbs":0,"title":0},"326":{"body":0,"breadcrumbs":0,"title":0},"327":{"body":15,"breadcrumbs":0,"title":0},"328":{"body":0,"breadcrumbs":0,"title":0},"329":{"body":34,"breadcrumbs":1,"title":1},"33":{"body":102,"breadcrumbs":0,"title":0},"330":{"body":66,"breadcrumbs":0,"title":0},"331":{"body":27,"breadcrumbs":0,"title":0},"332":{"body":51,"breadcrumbs":0,"title":0},"333":{"body":102,"breadcrumbs":0,"title":0},"334":{"body":48,"breadcrumbs":0,"title":0},"335":{"body":182,"breadcrumbs":0,"title":0},"336":{"body":0,"breadcrumbs":0,"title":0},"337":{"body":18,"breadcrumbs":0,"title":0},"338":{"body":84,"breadcrumbs":0,"title":0},"339":{"body":19,"breadcrumbs":0,"title":0},"34":{"body":62,"breadcrumbs":0,"title":0},"340":{"body":48,"breadcrumbs":0,"title":0},"341":{"body":325,"breadcrumbs":0,"title":0},"342":{"body":283,"breadcrumbs":0,"title":0},"343":{"body":154,"breadcrumbs":0,"title":0},"344":{"body":57,"breadcrumbs":0,"title":0},"345":{"body":1,"breadcrumbs":0,"title":0},"346":{"body":14,"breadcrumbs":0,"title":0},"347":{"body":2,"breadcrumbs":0,"title":0},"348":{"body":14,"breadcrumbs":0,"title":0},"349":{"body":75,"breadcrumbs":0,"title":0},"35":{"body":44,"breadcrumbs":0,"title":0},"350":{"body":372,"breadcrumbs":0,"title":0},"351":{"body":50,"breadcrumbs":0,"title":0},"352":{"body":34,"breadcrumbs":0,"title":0},"353":{"body":5,"breadcrumbs":0,"title":0},"354":{"body":4,"breadcrumbs":1,"title":1},"355":{"body":1,"breadcrumbs":0,"title":0},"356":{"body":91,"breadcrumbs":0,"title":0},"357":{"body":146,"breadcrumbs":0,"title":0},"358":{"body":433,"breadcrumbs":0,"title":0},"359":{"body":236,"breadcrumbs":0,"title":0},"36":{"body":92,"breadcrumbs":1,"title":1},"360":{"body":64,"breadcrumbs":0,"title":0},"361":{"body":5,"breadcrumbs":0,"title":0},"362":{"body":21,"breadcrumbs":0,"title":0},"363":{"body":231,"breadcrumbs":0,"title":0},"364":{"body":146,"breadcrumbs":0,"title":0},"365":{"body":72,"breadcrumbs":1,"title":1},"366":{"body":0,"breadcrumbs":0,"title":0},"367":{"body":110,"breadcrumbs":0,"title":0},"368":{"body":92,"breadcrumbs":0,"title":0},"369":{"body":9,"breadcrumbs":0,"title":0},"37":{"body":38,"breadcrumbs":1,"title":1},"370":{"body":8,"breadcrumbs":0,"title":0},"371":{"body":75,"breadcrumbs":1,"title":1},"372":{"body":24,"breadcrumbs":0,"title":0},"373":{"body":318,"breadcrumbs":1,"title":1},"374":{"body":20,"breadcrumbs":0,"title":0},"375":{"body":19,"breadcrumbs":0,"title":0},"376":{"body":0,"breadcrumbs":0,"title":0},"377":{"body":14,"breadcrumbs":0,"title":0},"378":{"body":23,"breadcrumbs":0,"title":0},"379":{"body":82,"breadcrumbs":1,"title":1},"38":{"body":24,"breadcrumbs":0,"title":0},"380":{"body":135,"breadcrumbs":0,"title":0},"381":{"body":45,"breadcrumbs":1,"title":1},"382":{"body":79,"breadcrumbs":0,"title":0},"383":{"body":99,"breadcrumbs":1,"title":1},"384":{"body":173,"breadcrumbs":0,"title":0},"385":{"body":62,"breadcrumbs":0,"title":0},"386":{"body":0,"breadcrumbs":0,"title":0},"387":{"body":83,"breadcrumbs":0,"title":0},"388":{"body":1521,"breadcrumbs":0,"title":0},"389":{"body":9,"breadcrumbs":0,"title":0},"39":{"body":4,"breadcrumbs":0,"title":0},"390":{"body":628,"breadcrumbs":2,"title":2},"391":{"body":638,"breadcrumbs":0,"title":0},"392":{"body":0,"breadcrumbs":0,"title":0},"393":{"body":0,"breadcrumbs":0,"title":0},"394":{"body":0,"breadcrumbs":0,"title":0},"395":{"body":37,"breadcrumbs":0,"title":0},"396":{"body":12,"breadcrumbs":0,"title":0},"397":{"body":56,"breadcrumbs":0,"title":0},"398":{"body":0,"breadcrumbs":2,"title":1},"399":{"body":148,"breadcrumbs":1,"title":0},"4":{"body":8,"breadcrumbs":0,"title":0},"40":{"body":169,"breadcrumbs":0,"title":0},"400":{"body":141,"breadcrumbs":1,"title":0},"401":{"body":12,"breadcrumbs":2,"title":1},"402":{"body":4,"breadcrumbs":2,"title":1},"403":{"body":17,"breadcrumbs":3,"title":2},"404":{"body":32,"breadcrumbs":3,"title":2},"405":{"body":35,"breadcrumbs":3,"title":2},"406":{"body":10,"breadcrumbs":2,"title":1},"407":{"body":19,"breadcrumbs":2,"title":1},"408":{"body":2,"breadcrumbs":2,"title":1},"409":{"body":15,"breadcrumbs":2,"title":1},"41":{"body":110,"breadcrumbs":0,"title":0},"410":{"body":71,"breadcrumbs":2,"title":1},"411":{"body":69,"breadcrumbs":2,"title":1},"412":{"body":18,"breadcrumbs":4,"title":3},"413":{"body":24,"breadcrumbs":2,"title":1},"414":{"body":16,"breadcrumbs":2,"title":1},"415":{"body":0,"breadcrumbs":4,"title":2},"416":{"body":4,"breadcrumbs":2,"title":0},"417":{"body":68,"breadcrumbs":2,"title":0},"418":{"body":8,"breadcrumbs":2,"title":0},"419":{"body":51,"breadcrumbs":4,"title":2},"42":{"body":311,"breadcrumbs":0,"title":0},"420":{"body":10,"breadcrumbs":3,"title":1},"43":{"body":115,"breadcrumbs":0,"title":0},"44":{"body":54,"breadcrumbs":0,"title":0},"45":{"body":188,"breadcrumbs":0,"title":0},"46":{"body":5,"breadcrumbs":0,"title":0},"47":{"body":0,"breadcrumbs":0,"title":0},"48":{"body":124,"breadcrumbs":0,"title":0},"49":{"body":14,"breadcrumbs":0,"title":0},"5":{"body":0,"breadcrumbs":0,"title":0},"50":{"body":114,"breadcrumbs":0,"title":0},"51":{"body":49,"breadcrumbs":0,"title":0},"52":{"body":209,"breadcrumbs":0,"title":0},"53":{"body":186,"breadcrumbs":0,"title":0},"54":{"body":46,"breadcrumbs":0,"title":0},"55":{"body":85,"breadcrumbs":0,"title":0},"56":{"body":157,"breadcrumbs":0,"title":0},"57":{"body":129,"breadcrumbs":0,"title":0},"58":{"body":17,"breadcrumbs":0,"title":0},"59":{"body":0,"breadcrumbs":0,"title":0},"6":{"body":1,"breadcrumbs":0,"title":0},"60":{"body":266,"breadcrumbs":0,"title":0},"61":{"body":259,"breadcrumbs":0,"title":0},"62":{"body":5,"breadcrumbs":0,"title":0},"63":{"body":3,"breadcrumbs":0,"title":0},"64":{"body":2,"breadcrumbs":0,"title":0},"65":{"body":11,"breadcrumbs":0,"title":0},"66":{"body":2,"breadcrumbs":0,"title":0},"67":{"body":24,"breadcrumbs":0,"title":0},"68":{"body":28,"breadcrumbs":1,"title":1},"69":{"body":256,"breadcrumbs":0,"title":0},"7":{"body":0,"breadcrumbs":0,"title":0},"70":{"body":43,"breadcrumbs":0,"title":0},"71":{"body":70,"breadcrumbs":0,"title":0},"72":{"body":145,"breadcrumbs":0,"title":0},"73":{"body":219,"breadcrumbs":0,"title":0},"74":{"body":107,"breadcrumbs":0,"title":0},"75":{"body":1,"breadcrumbs":0,"title":0},"76":{"body":145,"breadcrumbs":0,"title":0},"77":{"body":294,"breadcrumbs":0,"title":0},"78":{"body":17,"breadcrumbs":0,"title":0},"79":{"body":2,"breadcrumbs":0,"title":0},"8":{"body":1,"breadcrumbs":0,"title":0},"80":{"body":5,"breadcrumbs":0,"title":0},"81":{"body":130,"breadcrumbs":0,"title":0},"82":{"body":49,"breadcrumbs":0,"title":0},"83":{"body":111,"breadcrumbs":0,"title":0},"84":{"body":32,"breadcrumbs":0,"title":0},"85":{"body":17,"breadcrumbs":0,"title":0},"86":{"body":110,"breadcrumbs":0,"title":0},"87":{"body":74,"breadcrumbs":0,"title":0},"88":{"body":27,"breadcrumbs":0,"title":0},"89":{"body":58,"breadcrumbs":0,"title":0},"9":{"body":0,"breadcrumbs":0,"title":0},"90":{"body":233,"breadcrumbs":0,"title":0},"91":{"body":6,"breadcrumbs":0,"title":0},"92":{"body":130,"breadcrumbs":0,"title":0},"93":{"body":53,"breadcrumbs":0,"title":0},"94":{"body":137,"breadcrumbs":0,"title":0},"95":{"body":40,"breadcrumbs":0,"title":0},"96":{"body":69,"breadcrumbs":1,"title":1},"97":{"body":1,"breadcrumbs":0,"title":0},"98":{"body":5,"breadcrumbs":0,"title":0},"99":{"body":41,"breadcrumbs":0,"title":0}},"docs":{"0":{"body":"Steve Klabnik, Carol Nichols 지음. 기여해주신 러스트 커뮤니티 여러분과 한국어 번역에 참여해주신 분들께 감사드립니다. 이 텍스트 버전은 여러분이 (2023년 2월 9일에 출시된) 러스트 1.67.1 혹은 이후 버전을 사용하고 있음을 가정합니다. 러스트를 설치하거나 업데이트하려면 1장의 ‘설치’절 을 보세요. 이 책은 온라인, 오프라인 모두 제공됩니다. 온라인에는 원본(영문) 이외에도 번역본이 존재하며, 각각 https://doc.rust-lang.org/stable/book/ (영문)에서 읽어보실 수 있습니다. 오프라인 본(영문)은 설치되어있는 rustup의 rustup docs --book 명령어로 열어보실 수 있습니다. 커뮤니티 번역본 도 물론 이용 가능하며, 여러분이 읽고 계시는 한국어 번역본은 다음 링크를 통해 읽으실 수 있습니다: https://doc.rust-kr.org . No Starch Press 에서는 영문 원서가 종이책 및 ebook으로 제공됩니다. **🚨 더 상호작용적인 배움의 경험을 원하시나요? 다른 버전의 러스트 책을 시도해 보세요: 퀴즈, 하이라이팅, 시각화 등등의 기능이 있습니다: https://rust-book.cs.brown.edu","breadcrumbs":"The Rust Programming Language » The Rust Programming Language","id":"0","title":"The Rust Programming Language"},"1":{"body":"콕 집어서 말할 순 없지만, 러스트 프로그래밍 언어는 권한 부여 (empowerment) 에 근간을 두고 있습니다: 여러분이 지금 어떤 종류의 코드를 작성하고 있건 간에, 러스트는 여러분에게 더 많은 권한을 부여하여 프로그래머가 다양한 분야에서 이전보다 더 자신감 있게 프로그래밍할 수 있도록 도와줍니다. 예를 들어 메모리 관리, 데이터 표현, 동시성 등 저수준을 세부적으로 다루는 ‘시스템 수준의’ 프로그래밍을 생각해봅시다. 예로부터 이 분야는 악명 높은 함정을 피하기 위해 수 년 동안 관련 지식을 쌓아온 소수 정예만이 다가갈 수 있는 난해한 영역으로 여겨져 왔습니다. 그리고 이런 사람들마저도 코드가 이용당하거나, 망가지거나, 붕괴하지 않도록 심혈을 기울여 작업해야 합니다. 러스트는 이런 오래된 문제를 제거하는 동시에 일반적인 프로그래머에게 친숙하고 세련된 도구를 제공함으로써 이 장벽들을 부숩니다. 저수준 제어에 ‘살짝만 발을 담글’ 필요가 있는 프로그래머들은 까다로운 툴체인의 세세한 특징을 학습할 필요 없이 러스트만으로도 자신의 목적을 달성할 수 있습니다. 더 좋은 점은 이 언어가 속도와 메모리 사용 측면에서 효율적인 신뢰할 수 있는 코드로 자연스럽게 안내하도록 설계되었다는 점입니다. 이전부터 저수준 코드를 작성하던 프로그래머들은 러스트를 사용하여 야망을 키울 수 있습니다. 예를 들면, 러스트에서 병렬화를 도입하는 것은 비교적 위험도가 낮은 작업입니다: 컴파일러가 고전적인 실수를 잡아주거든요. 또한 실수로 인한 충돌이나 취약점을 발생시키지 않을 것이라는 확신을 가지고 코드에 대한 더 공격적인 최적화를 수행할 수 있습니다. 러스트는 저수준 시스템 프로그래밍에만 국한되지 않습니다. CLI 앱, 웹 서버 및 기타 여러 종류의 코드를 작성할 수 있을 정도로 표현력이 풍부하고 개발자 친화적으로 설계되어 있습니다 — 이 책의 뒷부분에서 두 경우에 대한 간단한 예제를 볼 것입니다. 러스트로 작업하면 한 분야에서 구축한 기술을 다른 분야에도 써먹을 수 있게 해줍니다; 웹 앱을 작성하는 것으로 러스트를 배운 다음, 동일한 기술을 라즈베리 파이를 대상으로 적용해 볼 수 있지요. 이 책은 러스트의 잠재력을 완전히 담아내어 사용자의 역량을 강화할 수 있도록 노력했습니다. 이 책은 러스트에 대한 지식뿐만 아니라 프로그래머로서의 역량과 자신감도 향상시킬 수 있도록 친근하고 접근하기 쉬운 텍스트로 구성되어 있습니다. 그럼, 바로 시작해서 배울 준비를 해보죠—그리고 러스트 커뮤니티에 오신 것을 환영합니다! — Nicholas Matsakis, Aaron Turon","breadcrumbs":"들어가기에 앞서 » 들어가기에 앞서","id":"1","title":"들어가기에 앞서"},"10":{"body":"먼저, 이 책은 앞에서부터 뒤까지 순서대로 읽는 가정하에 작성되었음을 알려드립니다. 따라서 보통 앞 장에서는 기초 내용을 배우고, 뒷장에서는 앞서 나온 내용을 기반으로 한 심화 내용을 배웁니다. 이 책에는 개념 장과 프로젝트 장의 두 가지 종류가 있습니다. 개념 장에서는 러스트에서의 어떤 개념에 대해 알아봅니다. 프로젝트 장에서는 그간 배운 내용을 적용하여 작은 프로그램을 함께 만들어 봅니다. 2장, 12장, 20장은 프로젝트 장이고 나머지는 개념 장입니다. 1장은 러스트를 설치하고 ‘Hello, world!’ 프로그램을 작성하는 방법, 그리고 러스트의 패키지 매니저 및 빌드 도구인 카고의 사용법을 다룹니다. 2장은 숫자 추리 게임을 직접 작성하면서 러스트로 프로그래밍하는 법을 배웁니다. 이후에 깊이 있게 배울 여러 개념을 추상적으로 다뤄볼 수 있습니다. 자기 손으로 직접 실습해 보는 걸 선호하시는 분에게 제격입니다. 3장은 다른 프로그래밍 언어와 유사한 러스트 특성을 다루는 내용이며, 4장은 소유권 시스템을 다루는 내용입니다. 이 부분은 여러 방법으로 읽을 수 있습니다. 3장을 건너뛰고 바로 4장 소유권 시스템부터 배우거나, 하나씩 차근차근 배우는 걸 선호하면 2장을 건너뛰고 3장부터 본 후, 2장으로 돌아와 배운 내용을 프로젝트에 적용해 볼 수도 있지요. 5장은 구조체 및 메서드를 다루며, 6장은 열거형과 match 표현식, if let 제어 흐름문을 다룹니다. 구조체와 열거형은 앞으로 커스텀 타입을 만드는 데 사용할 겁니다. 7장은 공개 API (Application Programming Interface) 를 만들 때, 작성한 코드와 해당 API를 체계화하기 위한 모듈 시스템 및 접근 권한 규칙을 다루며, 8장은 벡터, 문자열, 해시맵 등 표준 라이브러리가 제공하는 일반적인 컬렉션 자료구조를 다룹니다. 9장에서는 러스트의 에러 처리 철학 및 기법을 알아보겠습니다. 10장은 여러 가지 타입에 적용될 수 있는 코드를 정의하도록 해주는 제네릭 (generic), 트레이트 (trait), 라이프타임 (lifetime) 을 다루며 11장에서는 작성한 프로그램 로직이 잘 작동함을 확인하는 데 필요한 테스트 관련 내용을 다룹니다. 12장에서는 이때까지 배운 수많은 개념을 이용해 커맨드 라인 도구 grep의 기능 일부를 직접 구현해 볼 겁니다. 13장은 클로저 및 반복자를 다룹니다: 함수형 프로그래밍 언어에서 유래된 러스트의 기능입니다. 14장은 카고에 대한 심화 내용 및 여러분이 만든 라이브러리를 남들이 쓸 수 있도록 배포하는 방법을 다룹니다. 15장은 표준 라이브러리가 제공하는 스마트 포인터와 스마트 포인터를 구현하는 트레이트를 다룹니다. 16장에서는 여러 동시성 프로그래밍 모델에 대해 돌아보고, 러스트에서는 어째서 두려움 없이 멀티스레드 프로그래밍을 할 수 있는지 이야기하겠습니다. 17장에서는 여러분에게 익숙할 객체 지향 프로그래밍 원칙과 러스트의 표현 양식 간에 차이를 살펴보겠습니다. 18장은 러스트 프로그램 전반에 걸쳐 아이디어를 표현하는 데 강력한 방법인 패턴, 그리고 패턴 매칭을 참고 자료 형식으로 다룹니다. 19장은 안전하지 않은 러스트, 매크로, 라이프타임, 트레이트, 타입, 함수, 클로저 등 다양한 고급 주제를 다룹니다. 20장에서는 저수준 멀티스레드 웹 서버를 직접 구현하는 것으로 프로젝트 실습을 마칠 예정입니다. 마지막으로, 부록에는 러스트 관련 유용한 정보를 참고 자료 형식으로 담아두었습니다. 부록 A에는 러스트에서 사용하는 키워드들을, 부록 B에는 연산자 및 기호를, 부록 C에는 표준 라이브러리가 제공하는 derivable 트레이트를, 부록 D에는 여러 유용한 개발 도구에 대한 내용을, 부록 E에는 러스트 에디션을 각각 설명합니다. 부록 F에서는 이 책의 번역본에 대해서, 부록 G에서는 러스트와 nightly 러스트가 어떻게 만들어지는지 다룹니다. 이 책은 어떻게 읽든 상관없습니다. 일단 넘기고 싶은 부분은 넘긴 뒤, 뒷부분을 읽다가 내용이 헷갈릴 때 다시 앞으로 돌아와 읽으셔도 됩니다. 다만, 자신에게 가장 도움이 되는 방식대로 읽으시길 권합니다. 러스트를 배우는 과정에서 중요한 부분은 컴파일러가 보여주는 에러 메시지를 읽는 법을 배우는 것입니다: 에러 메시지만 잘 읽어도 코드 속 에러를 고칠 수 있기 때문이지요. 따라서, 여러분이 에러 메시지를 읽는 실력을 자연스럽게 늘릴 수 있도록 컴파일되지 않는 예제 코드와 해당 예제에서 발생하는 에러 메시지를 다양하게 보여드릴 겁니다. 그러니 눈에 보이는 아무 예제나 컴파일을 돌렸더니 에러가 나타나더라도, 일부러 에러가 나타나게 만든 예제일 수 있으니 당황하지 마시고 해당 예제 주위의 글을 읽어보세요. 편의를 위해, 오작동하도록 만든 코드에는 페리스 (Ferris) 가 등장하니 구분하는 데 참고하셔도 좋습니다. 페리스 의미 컴파일되지 않는 코드 패닉이 발생하는 코드 의도대로 작동하지 않는 코드 덧붙이자면, 컴파일되지 않는 코드가 등장하는 내용 중 대부분은 해당 코드가 정상 작동하도록 수정해 나가는 내용입니다.","breadcrumbs":"소개 » 이 책을 어떻게 읽어야 할까요?","id":"10","title":"이 책을 어떻게 읽어야 할까요?"},"100":{"body":"아래처럼 IpAddrKind의 두 개의 배리언트에 대한 인스턴스를 만들 수 있습니다: # enum IpAddrKind {\n# V4,\n# V6,\n# }\n# # fn main() { let four = IpAddrKind::V4; let six = IpAddrKind::V6;\n# # route(IpAddrKind::V4);\n# route(IpAddrKind::V6);\n# }\n# # fn route(ip_kind: IpAddrKind) {} 열거형을 정의할 때의 식별자로 네임스페이스가 만들어져서, 각 배리언트 앞에 이중 콜론(::)을 붙여야 한다는 점을 주의하세요. 이 방식은 IpAddrKind::V4, IpAddrKind::V6가 모두 IpAddrKind 타입이라는 것을 표현할 수 있기 때문에 유용합니다. 이제 IpAddrKind 타입을 인수로 받는 함수를 정의해 봅시다: # enum IpAddrKind {\n# V4,\n# V6,\n# }\n# # fn main() {\n# let four = IpAddrKind::V4;\n# let six = IpAddrKind::V6;\n# # route(IpAddrKind::V4);\n# route(IpAddrKind::V6);\n# }\n# fn route(ip_kind: IpAddrKind) {} 그리고, 배리언트 중 하나를 사용해서 함수를 호출할 수 있습니다: # enum IpAddrKind {\n# V4,\n# V6,\n# }\n# # fn main() {\n# let four = IpAddrKind::V4;\n# let six = IpAddrKind::V6;\n# route(IpAddrKind::V4); route(IpAddrKind::V6);\n# }\n# # fn route(ip_kind: IpAddrKind) {} 열거형을 사용하면 더 많은 이점이 있습니다. IP 주소 타입에 대해 더 생각해 보면, 지금으로서는 실제 IP 주소 데이터 를 저장할 방법이 없고 어떤 종류 인지만 알 수 있습니다. 5장에서 구조체에 대해 배웠다면, 이 문제를 예제 6-1처럼 구조체를 사용하여 해결하고 싶을 수 있겠습니다: # fn main() { enum IpAddrKind { V4, V6, } struct IpAddr { kind: IpAddrKind, address: String, } let home = IpAddr { kind: IpAddrKind::V4, address: String::from(\"127.0.0.1\"), }; let loopback = IpAddr { kind: IpAddrKind::V6, address: String::from(\"::1\"), };\n# } 예제 6-1: struct를 사용해서 IP 주소의 데이터와 IpAddrKind 배리언트 저장하기 여기서는 IpAddrKind (이전에 정의한 열거형) 타입인 kind 필드와 String 타입인 address 필드를 갖는 IpAddr를 정의했습니다. 그리고 이 구조체의 인스턴스 두 개를 생성했습니다. 첫 번째 home은 kind의 값으로 IpAddrKind::V4를, 연관된 주소 데이터로 127.0.0.1를 갖습니다. 두 번째 loopback은 IpAddrKind의 다른 배리언트인 V6를 값으로 갖고, 연관된 주소로 ::1를 갖습니다. kind와 address의 값을 함께 사용하기 위해 구조체를 사용했습니다. 그렇게 함으로써 배리언트가 연관된 값을 갖게 되었습니다. 각 열거형 배리언트에 데이터를 직접 넣는 방식을 사용해서 열거형을 구조체의 일부로 사용하는 방식보다 더 간결하게 동일한 개념을 표현할 수 있습니다. IpAddr 열거형의 새로운 정의에서 두 개의 V4와 V6 배리언트는 연관된 String 타입의 값을 갖게 됩니다: # fn main() { enum IpAddr { V4(String), V6(String), } let home = IpAddr::V4(String::from(\"127.0.0.1\")); let loopback = IpAddr::V6(String::from(\"::1\"));\n# } 열거형의 각 배리언트에 직접 데이터를 붙임으로써, 구조체를 사용할 필요가 없어졌습니다. 또한 여기서 열거형의 동작에 대한 다른 세부 사항을 살펴보기가 좀 더 쉬워졌습니다: 각 열거형 배리언트의 이름이 해당 열거형 인스턴스의 생성자 함수처럼 된다는 것이죠. 즉, IpAddr::V4()는 String 인수를 입력받아서 IpAddr 타입의 인스턴스를 결과를 만드는 함수입니다. 열거형을 정의한 결과로써 이러한 생성자 함수가 자동적으로 정의됩니다. 구조체 대신 열거형을 사용하면 또 다른 장점이 있습니다. 각 배리언트는 다른 타입과 다른 양의 연관된 데이터를 가질 수 있습니다. V4 IP 주소는 항상 0 ~ 255 사이의 숫자 4개로 된 구성 요소를 갖게 될 것입니다. V4 주소에 4개의 u8 값을 저장하길 원하지만, V6 주소는 하나의 String 값으로 표현되길 원한다면, 구조체로는 이렇게 할 수 없습니다. 열거형은 이런 경우를 쉽게 처리합니다: # fn main() { enum IpAddr { V4(u8, u8, u8, u8), V6(String), } let home = IpAddr::V4(127, 0, 0, 1); let loopback = IpAddr::V6(String::from(\"::1\"));\n# } 두 가지 다른 종류의 IP 주소를 저장하기 위해 코드에 열거형을 정의하는 몇 가지 방법을 살펴봤습니다. 그러나, 누구나 알듯이 IP 주소와 그 종류를 저장하는 것은 흔하기 때문에, 표준 라이브러리에 정의된 것을 사용할 수 있습니다! 표준 라이브러리에서 IpAddr를 어떻게 정의하고 있는지 살펴봅시다. 위에서 정의하고 사용했던 것과 동일한 열거형과 배리언트를 갖고 있지만, 배리언트에 포함된 주소 데이터는 두 가지 다른 구조체로 되어 있으며, 각 배리언트마다 다르게 정의하고 있습니다: struct Ipv4Addr { // --생략--\n} struct Ipv6Addr { // --생략--\n} enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr),\n} 이 코드로 알 수 있듯, 열거형 배리언트에는 어떤 종류의 데이터라도 넣을 수 있습니다. 문자열, 숫자 타입, 구조체 등은 물론, 다른 열거형마저도 포함할 수 있죠! 이건 여담이지만, 러스트의 표준 라이브러리 타입은 여러분의 생각보다 단순한 경우가 꽤 있습니다. 현재 스코프에 표준 라이브러리를 가져오지 않았기 때문에, 표준 라이브러리에 IpAddr 정의가 있더라도 동일한 이름의 타입을 만들고 사용할 수 있음을 주의하세요. 타입을 스코프로 가져오는 것에 대해서는 7장에서 더 살펴보겠습니다. 예제 6-2에 있는 열거형의 다른 예제를 살펴봅시다. 이 예제에서는 각 배리언트에 다양한 종류의 타입들이 포함되어 있습니다: enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32),\n}\n# # fn main() {} 예제 6-2: Message 열거형은 각 배리언트가 다른 타입과 다른 양의 값을 저장합니다. 이 열거형에는 다른 데이터 타입을 갖는 네 개의 배리언트가 있습니다: Quit은 연관된 데이터가 전혀 없습니다. Move은 구조체처럼 이름이 있는 필드를 갖습니다. Write은 하나의 String을 가집니다. ChangeColor는 세 개의 i32을 가집니다. 예제 6-2에서처럼 배리언트로 열거형을 정의하는 것은 다른 종류의 구조체들을 정의하는 것과 비슷합니다. 열거형이 구조체와 다른 점은 struct 키워드를 사용하지 않는다는 것과 모든 배리언트가 Message 타입으로 묶인다는 것입니다. 아래 구조체들은 이전 열거형의 배리언트가 갖는 것과 동일한 데이터를 가질 수 있습니다: struct QuitMessage; // 유닛 구조체\nstruct MoveMessage { x: i32, y: i32,\n}\nstruct WriteMessage(String); // 튜플 구조체\nstruct ChangeColorMessage(i32, i32, i32); // 튜플 구조체\n# # fn main() {} 각기 다른 타입을 갖는 여러 개의 구조체를 사용한다면, 이 메시지 중 어떤 한 가지를 인수로 받는 함수를 정의하기 힘들 것입니다. 예제 6-2에 정의한 Message 열거형은 하나의 타입으로 이것이 가능합니다. 열거형과 구조체는 한 가지 더 유사한 점이 있습니다. 구조체에 impl을 사용해서 메서드를 정의한 것처럼, 열거형에도 정의할 수 있습니다. 여기 Message 열거형에 정의한 call이라는 메서드가 있습니다: # fn main() {\n# enum Message {\n# Quit,\n# Move { x: i32, y: i32 },\n# Write(String),\n# ChangeColor(i32, i32, i32),\n# }\n# impl Message { fn call(&self) { // 메서드 본문이 여기 정의될 것입니다 } } let m = Message::Write(String::from(\"hello\")); m.call();\n# } 메서드 본문에서는 self를 사용하여 호출한 열거형의 값을 가져올 것입니다. 이 예제에서 생성한 변수 m은 Message::Write(String::from(\"hello\")) 값을 갖게 되고, 이 값은 m.call()이 실행될 때 call 메서드 안에서 self가 될 것입니다. 이제 표준 라이브러리에 포함된 열거형 중에서 굉장히 유용하고 자주 사용되는 Option 열거형을 살펴봅시다:","breadcrumbs":"열거형과 패턴 매칭 » 열거형 정의하기 » 열거형 값","id":"100","title":"열거형 값"},"101":{"body":"이번 절에서는 표준 라이브러리에서 열거형으로 정의된 또 다른 타입인 Option에 대한 사용 예를 살펴보겠습니다. Option 타입은 값이 있거나 없을 수 있는 아주 흔한 상황을 나타냅니다. 예를 들어 비어있지 않은 리스트의 첫 번째 아이템을 요청한다면 값을 얻을 수 있을 것입니다. 그렇지만 비어있는 리스트로부터 첫 번째 아이템을 요청한다면 아무 값도 얻을 수 없을 것입니다. 이 개념을 타입 시스템으로 표현한다는 것은 처리해야 하는 모든 경우를 처리했는지 컴파일러가 확인할 수 있다는 의미입니다; 이러한 기능은 다른 프로그래밍 언어에서 매우 흔하게 발생하는 버그를 방지해줍니다. 프로그래밍 언어 디자인은 가끔 어떤 기능들이 포함되었는지의 관점에서 생각되기도 하지만, 어떤 기능을 포함하지 않을 것이냐도 중요합니다. 러스트는 다른 언어들에서 흔하게 볼 수 있는 널 (null) 개념이 없습니다. 널 은 값이 없음을 표현하는 하나의 값입니다. 널 개념이 존재하는 언어에서, 변수의 상태는 둘 중 하나입니다. 널인 경우와, 널이 아닌 경우죠. 널을 고안한 토니 호어 (Tony Hoare) 는 그의 2009년 발표 ‘널 참조: 10억 달러짜리 실수 (Null References: The Billion Dollar Mistake)’에서 다음과 같이 말합니다: 저는 그걸 10억 달러짜리 실수라고 부릅니다. 저는 그 당시 객체 지향 언어에서 참조를 위한 첫 포괄적인 타입 시스템을 디자인하고 있었습니다. 제 목표는 컴파일러에 의해 자동으로 수행되는 체크를 통해 모든 참조자의 사용이 절대로 안전함을 보장하는 것이었습니다. 하지만 구현이 무척 간단하다는 단순한 이유로 널 참조를 넣고 싶은 유혹을 참을 수 없었습니다. 이는 수없이 많은 에러와 취약점, 시스템 종료를 유발했고, 아마도 지난 40년간 10억 달러 수준의 고통과 손실을 초래해왔습니다. 널 값으로 발생하는 문제는, 널 값을 널이 아닌 값처럼 사용하려고 할 때 여러 종류의 에러가 발생할 수 있다는 것입니다. 널이나 널이 아닌 속성은 어디에나 있을 수 있고, 너무나도 쉽게 이런 종류의 에러를 만들어 냅니다. 하지만, ‘현재 어떠한 이유로 인해 유효하지 않거나, 존재하지 않는 하나의 값’이라는 널이 표현하려고 하는 개념은 여전히 유용합니다. 널의 문제는 실제 개념에 있기보다, 특정 구현에 있습니다. 이처럼 러스트에는 널이 없지만, 값의 존재 혹은 부재의 개념을 표현할 수 있는 열거형이 있습니다. 그 열거형이 바로 Option
이며, 다음과 같이 표준 라이브러리에 정의되어 있습니다 : enum Option { None, Some(T),\n} Option 열거형은 너무나 유용하기 때문에, 러스트에서 기본으로 임포트하는 목록인 프렐루드에도 포함되어 있습니다. 이것의 배리언트 또한 프렐루드에 포함되어 있습니다: 따라서 Some, None 배리언트 앞에 Option::도 붙이지 않아도 됩니다. 하지만 Option 는 여전히 그냥 일반적인 열거형이며, Some(T)와 None도 여전히 Option 의 배리언트 입니다. 문법은 아직 다루지 않은 러스트의 기능입니다. 이것은 제네릭 타입 매개변수 (generic type parameter) 이며, 제네릭에 대해서는 10장에서 더 자세히 다룰 것입니다. 지금은 라는 것이 Option 열거형의 Some 배리언트가 어떤 타입의 데이터라도 담을 수 있게 한다는 것, 그리고 T의 자리에 구체적인 타입을 집어넣는 것이 전체 Option 타입을 모두 다른 타입으로 만든다는 것만 알아두면 됩니다. 아래에 숫자 타입과 문자열 타입을 갖는 Option 값에 대한 예들이 있습니다: # fn main() { let some_number = Some(5); let some_char = Some('e'); let absent_number: Option = None;\n# } some_number의 타입은 Option 입니다. some_char의 타입은 Option 이고 둘은 서로 다른 타입입니다. Some 배리언트 내에 어떤 값을 명시했기 때문에 러스트는 이 타입들을 추론할 수 있습니다. absent_number에 대해서는 전반적인 Option 타입을 명시하도록 해야 합니다: None 값만 봐서는 동반되는 Some 배리언트가 어떤 타입의 값을 가질지 컴파일러가 추론할 수 없기 때문입니다. 위 예제에서는 absent_number가 Option 타입임을 명시했습니다. Some 값을 얻게 되면, 값이 존재한다는 것과 해당 값이 Some 내에 있다는 것을 알 수 있습니다. None 값을 얻게 되면, 얻은 값이 유효하지 않다는, 어떤 면에서는 널과 같은 의미를 갖습니다. 그렇다면 왜 Option 가 널보다 나을까요? 간단하게 말하면, Option 와 T(T는 어떤 타입이던 될 수 있음)이 다른 타입이기 때문에, 컴파일러는 Option 값을 명백하게 유효한 값처럼 사용하지 못하도록 합니다. 예를 들면, 아래 코드는 Option 에 i8을 더하려고 하고 있으므로 컴파일되지 않습니다: # fn main() { let x: i8 = 5; let y: Option = Some(5); let sum = x + y;\n# } 이 코드를 실행하면, 아래와 같은 에러 메시지가 출력됩니다: $ cargo run Compiling enums v0.1.0 (file:///projects/enums)\nerror[E0277]: cannot add `Option ` to `i8` --> src/main.rs:5:17 |\n5 | let sum = x + y; | ^ no implementation for `i8 + Option ` | = help: the trait `Add