728x90
반응형

Java 개발자를 위한 Rust, 파트 2

우리는 지금까지 어디로 갔습니까?

Java 개발자를 위한 Rust 시리즈의  번째 기사 에서 우리는 몇 가지 기본 구문, 일부 패턴 일치를 보았고 간략하게 다루었으며 가장 중요한 것은 프로그램의 데이터가 있는 위치에 대해 추론하려고 했습니다.enum

우리가 신속하게 코드 라인을 저장하려고 시도했을 때 RAII로 인해 중요한 리소스의 범위를 실수로 변경했고 코드를 컴파일하려고 할 때 빌림 검사기 에서 오류가 발생했습니다.

$ rustc greeter.rs
error[E0716]: temporary value dropped while borrowed
 --> greeter.rs:6:43
  |
6 |     let anybody_at_all = env::args().collect::<Vec<String>>().get(1);
  |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^       - temporary value is freed at the end of this statement
  |                          |
  |                          creates a temporary which is freed while still in use
7 |
8 |     let who: &str = if let Some(one) = anybody_at_all {
  |                                        -------------- borrow later used here
  |

두려운 차용 검사기 는 소유borrow later used here 한 값에 대한 참조(차용)를 효과적으로 알려줍니다. 이 경우 소유자가 해제된 동안 임시 가 사용됩니다. 이것은 관리되는 언어에서 오는 Rust를 시도하는 개발자들에게 너무 잘 알려진 오류 메시지입니다. 당신이 직접 Rust를 가지고 놀기 시작했다면 조만간 모험을 하면서 그런 메시지를 접했을 가능성이 있습니다.

Java에는 사용되지 않을 때만 메모리를 해제하는 가비지 수집기가 있을 뿐만 아니라 완전히 투명하게 힙 할당을 최적화할 수 있는 컴파일러도 있습니다. 이렇게 하면 메모리, 해제 또는 메모리 할당 위치(힙 또는 스택)에 대해 생각하지 않아도 됩니다. 반면에 Rust는 개발자에게 메모리 할당 위치와 방법에 대한 결정을 내립니다. 그것은 큰 힘을 동반하지만, 또한… 예, 책임이 있습니다. 적어도 컴파일러는 안전하지 않은 코드를 생성하도록 허용하지 않습니다. 때로는 컴파일러가 작업을 완료하도록 허용하지 않는 것처럼 느껴지기도 합니다. 이것은 일반적으로 프로그램을 통해 데이터가 "흐르는" 방식을 설명하지 않는 코딩 패턴에서 비롯됩니다. 왜냐하면 JVM은 이러한 것들에 대해 생각할 필요가 없고 누구라도 가리킬 수 있는 거대한 객체 바다를 생성하지 않도록 우리를 망쳤기 때문입니다. 모든 것.

소유권 및 이동

cargo new. _ 첫 번째 인수가 있는 경우 전달되도록 코드를 약간 변경할 것입니다. 그리 놀라운 방법은 아닙니다.

use std::env;

fn main() {
    let who = env::args().nth(1).unwrap_or(String::from("World"));
    println!("Hello, {who}!");
}

잠깐만! 이것은 우리가 이전에 본 것과는 다릅니다. 지금까지 우리가 했던 모든 작업이 한 줄짜리인 이유는 무엇입니까? 음… 예. 읽기 쉽게 만들 수 있었습니다 . 또는 적어도 이것이 읽기 쉽기를 바랍니다. 이제 반복자에서 두 번째 .nth(1)항목 을 가져오는 데 필요한 모든 것은 Args여전히 Option<String>​​; 그런 다음 프로그램에 제공된 인수  있는 경우 .unwrap밖으로 이동 합니다 . 반면에 가 있는 경우 대신 메서드에 제공된 인수에서 힙 할당 인스턴스를 만듭니다 .String OptionSome_orNoneString"World": &str

위의 코드에는 다음과 같은 새로운 구문이 있습니다 . 유형 에서 호출 String::from()되는 함수 입니다. 이는 정적 메서드 호출과 동일합니다. 여기 에서 참조하는 는 에서 찾을 수 있습니다 . A 는 Java에서 와 같이 명명된 필드에 관련 데이터를 보유합니다 . 그러나 우리는 그것에 대해 조금 후에 돌아올 것입니다.from()Stringfrom()struct Stringstructclass

그래서 밖으로 옮기는 이 사업  무엇입니까? 이전 게시물에서 보았듯이 는 어딘가에 살아야 합니다 . 그것이 Rust가 소유권이라고 부르는 것입니다. 그리고 모든 데이터의 소유자 는 한 명만 있을 수 있습니다 . 프로그램에 전달된 인수가 있는 경우 에 대한 호출 은 해당 의 소유자인 변형 에서 해당 인수를 반환합니다 . 즉, 범위를 벗어나는 즉시 콘텐츠도 -ped되고 the 가 해제됩니다. 그러나 우리는 우리의 작은 프로그램 전체에서 간접 참조 를 다루고 싶지 않습니다 . 전달 된 인수인지 또는String Option::SomeString env::args().nth(1)StringOption::SomeStringDropStringOptionString"World", 우리는 우리가 인쇄 who할 적절한 것을 가리키는 것 외에는 별로 신경 쓰지 않습니다. String이것이 .unwrap_or()우리를 위해 하는 일입니다.

두 개의 개별 비트를 분해해 보겠습니다. 먼저 Option<String>단순화를 위해 를 다룰 것이므로 먼저 코드를 리팩터링하여 다음을 얻습니다.

let anybody_at_all: Option<String> = env::args().nth(1);
let who: String = anybody_at_all.unwrap_or(String::from("World"));

이제 가 있으므로 프로그램에 항상 인수가 제공 anybody_at_all: Option<String>된다고 가정해 봅시다 . 다음과 같이 메서드 호출을 직선으로 바꿀 수 있습니다 ..unwrap_or.unwrap()

let who: String = anybody_at_all.unwrap();

이 코드는 이제 panic실제로 제공되는 인수가 없을 것입니다. 먼저 인수를 제공한 다음 생략합니다.

$ cargo run -- Jane
   Compiling rusty-java-2 v0.1.0
    Finished dev [unoptimized + debuginfo] target(s) in 0.75s
     Running `target/debug/rusty-java-2 Jane`
Hello, Jane!

$ cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/rusty-java-2`
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/main.rs:5:30
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

좋지 않습니다. 하지만 지금은 무시하고 .unwrap_or곧 우리 버전으로 돌아갈 것입니다. 실제로 성공하는 경로에 집중하여 호출 하면 it이 가진 anybody_at_all.unwrap()소유권을 변수로 이전합니다. 제공된 인수, 즉 이 예에서 from 은 우리의 that 에서 로 이동 했습니다 . 어느 시점에서 당신은 아마 무슨 일이 일어났는지 궁금할 것이고 당신이 묻는 것이 맞을 것입니다. 시행 착오가 여기서 다시 우리의 접근 방식으로 남아 있습니다 . 값 을 다시 시도해 봅시다 .Stringwho: StringString"Jane"Option::Someanybody_at_allwhoanybody_at_all.unwrap()

let anybody_at_all: Option<String> = env::args().nth(1);
let who: String = anybody_at_all.unwrap();
let _again: String = anybody_at_all.unwrap();

무엇이 _again될까요? (밑줄로 변수 이름을 시작하면 컴파일러에 사용할 계획이 없음을 알립니다). 참고가 아닙니다. 또한 에 String포함 Option되어 있으므로 입니다. 그렇다면 원래 문자열의 복사본일까요? 이것을 실행해 봅시다:

$ cargo run -- Jane
   Compiling rusty-java-2 v0.1.0
error[E0382]: use of moved value: `anybody_at_all`
   --> src/main.rs:6:26
    |
4   |     let anybody_at_all: Option<String> = env::args().nth(1);
    |         -------------- move occurs because `anybody_at_all` has type `Option<String>`, which does not implement the `Copy` trait
5   |     let who: String = anybody_at_all.unwrap();
    |                       -------------- -------- `anybody_at_all` moved due to this method call
    |                       |
    |                       help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
6   |     let _again: String = anybody_at_all.unwrap();
    |                          ^^^^^^^^^^^^^^ value used here after move
    |
note: this function takes ownership of the receiver `self`, which moves `anybody_at_all`
   --> .../lib/rustlib/src/rust/library/core/src/option.rs:775:25
    |
775 |     pub const fn unwrap(self) -> T {
    |                         ^^^^

For more information about this error, try `rustc --explain E0382`.
error: could not compile `rusty-java-2` due to previous error

좋아요, 무서운 오류 메시지입니다: move occurs because …​ does not implement the Copy trait?! 글쎄, 원본의 사본은 String분명히 없습니다. 그 가설에 대해 너무 많이. 그러나 우리는 무언가 움직 인 것을 봅니다 ! anybody_at_all moved 오류 메시지가 나타납니다!  Option자체가 그랬다. 어떤 fn unwrap(self)메서드 때문에 우리는 실제로 호출했습니다. 나중에 구문으로 돌아갑니다. 그러나 무슨 일이 일어났는가는 호출 anybody_at_all이 소비되는 결과를 낳았고 , 그 동안 포함된 it의 소유권 String을 who. 그래서 우리가 그것으로 할 수 있는 것은 아무것도 없고 anybody_at_all, 그것은 "사라지고" 우리가 invoke 를 했던 5행.unwrap() 너머에서 사용될 수 없습니다 .

소유권은 매우 유사한 방식으로 동일한 범위 내에서 한 변수에서 다른 변수로 이전됩니다.

let who: String = anybody_at_all.unwrap();
let moved: String = who;
println!("Hello, {who}!");
println!("Hello, {moved}!");

이것은 우리 가 변수에서 변수로 소유권을 이전하기 때문에 컴파일 되지 않습니다 . 따라서 이후에는 사용할  없으며 더 이상 사용할 수 없습니다.Stringwhomovedwhoprintln!

전화는 어때 .unwrap_or(String::from("World"))? 우리가 변종 panic을 다루는 경우를 제외하고는 정확히 동일하게 작동합니다 . Option::None이 경우 제공된 인수를 대신 반환합니다. 이것은 제네릭 형식 Option<T>이며 unwrap_ora T를 default: T 인수로 사용합니다.  String, 이 경우 a를 전달해야 합니다. 그렇기 때문에 이전 게시물에서 수행한 작업과 &str대신 처리한 문자열과 달리 힙에서 문자열을 인스턴스화해야 합니다. 이 프로그램은 "World" 항상 힙에 문자열을 할당합니다 . 이것은 메서드에 전달되는 인수이며 따라서 평가되어야 합니다. 즉, 함수 String::from가 항상 호출됩니다. 달리는 대안이 있습니다cargo clippy실제로 사용할 것을 권장합니다. 이는 Java의 람다 식에 해당하는 Rust를 사용하여 사용할 기본값을 느리게 평가하고 인수가 이미 제공된 경우 String불필요하게 힙에 할당하는 것을 방지 합니다. "World"그래도 나중 게시물을 위해 보관하겠습니다. 그래도 자유롭게 시도해 보세요!

struct그리고 차용

이제 우리는 소유권과 이사에 대해 상당히 잘 이해했으므로 차입에 대해 좀 더 자세히 살펴볼 때입니다. 앞서 말했듯이 참조는 값을 빌린 것입니다. str로드된 이진 코드에서 a에 대한 참조 또는 String실행 파일에 전달된 인수에서 가져온에 대한 참조를 다루었기 때문에 이전 게시물에서 상당한 양을 차용했습니다 . 이러한 차용은 모두 "읽기 전용"이었습니다. 참조가 가리키는 것을 변경할 수 없다는 의미입니다. &mut그들은 변경 가능한 참조인 참조 에 반대합니다 .

rustc여기 에 우리에게 부과할 중요한 규칙이 있습니다.

주어진 시간에 하나의 가변 참조 또는 여러 불변 참조를 가질 수 있습니다.
— The Rust Book
참조 규칙

즉, "살아 있는" 불변 참조자는 0개 이상 있을 수 있지만, 가변 참조자가 하나(그리고 하나만!) 있는 경우에는 불변 참조자가 0개만 있을 수 있습니다. 이는 값이 변경되는 동안 아무도 값을 읽지 않도록 보장합니다. 이것은 동시성 코드에 유용하지만, 단일 스레드 코드도 이러한 보장으로부터 이점을 얻는다는 것을 조금은 알게 될 것입니다.

그러나 이것이 프로덕션에서 무작위로 발생하는 버그가 아니라 컴파일 타임에 코드에서 전체 범주의 버그를 제거하는 데 어떻게 도움이 되는지 살펴보기 전에 RuntimeException먼저 참조 및 차용이 struct해당 impl블록과 어떻게 작용하는지 살펴보겠습니다. 먼저, structRust에서 a를 선언하는 방법은 다음과 같습니다.

struct Greeter {
    person: String,
}

structRust 의 A class는 Java의 a와 동일합니다. 먼저 struct키워드를 사용하여 선언한 다음 원하는 이름을 지정합니다. 그것이 선언하는 필드는 우리가 지금까지 본 Rust 구문을 따릅니다: <name>: <type>. 위의 예에서 person필드를 선언하는 줄은 쉼표( ,)로 끝납니다. Greeter이것은 구조체 의 마지막(유일한) 필드이므로 꼭 필요한 것은 아닙니다 . 그러나 쉼표가 필요하기 전에 선언되는 필드입니다. 항상 필드 선언을 쉼표로 끝내는 것이 좋은 방법으로 간주되므로 새 항목을 추가해야 하는 경우 버전 제어 시스템의 diff가 더 깔끔해집니다.

현재 우리 는 Java보다 structC에 더 가깝 습니다. 이 단계에서 아마도 생성자와 몇 가지 메서드를 예상할 것입니다. 전자부터 시작하겠습니다. 이 특별한 경우에는 생성자 자체가 필요하지 않습니다. 이 모든 것을 동일한 파일에 넣기 때문에 가시성은 중요하지 않습니다.  명시적으로 . 필드도 마찬가지입니다 . 즉 , 함수 의 어느 지점에서나 다음과 같은 구문을 사용하여 인스턴스화할 수 있습니다.structclassstructpubpersonmainGreeter

let greeter = Greeter {
    person: String::from("Jane"),
};

그리고 Rust의 Java에서 알 수 있듯이 생성자 가 없습니다. struct Greeter예를 들어 일부 인수 조작을 수행 하는 함수를 정의할 수 있습니다. a에 함수를 추가하는 것은 동일한 이름 struct의 블록으로 수행됩니다 . impl다음은 a 를 생성 하고 반환 하는 Greeter::new함수 의 예입니다( 참조가 아닌 자체).Personstruct

impl Greeter {
    fn new(person: String) -> Self {
        Self {
            person,
        }
    }
}

pub fn new다시 말하지만, 이 범위 외부에 노출되어야 하는 경우 함수는 로 public으로 선언 됩니다. 함수가 a 의 소유권 을 갖는 것을 볼 수 있습니다 String. 즉, 호출자가 String소유권을 이 함수로 옮긴다는 의미입니다. →그리고 화살표 a... 로 표시된 함수가 반환됩니다 Self.

Selfimpl블록 유형에 대한 자리 표시자입니다 . 이는 리팩터링할 때나 유형이 다소 장황할 때 유용합니다. 그러나 메서드 서명을 fn new(person: String) → Greeter. 함수 본문인 중괄호 안의 블록을 따릅니다. Greeter그러나 이번에 생성할 때 필드 person가 동일한 이름의 변수를 소유하도록 명시적으로 알리지 않습니다. 이전에 새로 만든 : 과 연결했을 때와 달리 String: person: String::from("Jane"). 이름이 같기 때문에 앞에 를person: 붙일 필요가 없습니다 . 중복되는 것으로 간주되므로 필요하지 않습니다. 마지막으로 본문의 한 줄은 ;새로 생성된Greeter인스턴스를 호출자에게, 즉 소유권을 호출자에게 이동합니다. 이 새로 생성 struct된 것이 스택에 생성되었다는 점도 언급할 가치가 있습니다. person의 이름 바이트가 결국 힙에 있더라도 이것은 String.

다시 Java Greeter::new의 메소드와 동일합니다 . static그렇다면 인스턴스 메서드를 어떻게 추가하시겠습니까? 먼저 인스턴스 메서드가 무엇인지 생각해 보겠습니다. 인스턴스 메소드는 객체 자체의 인스턴스에 작용하는 메소드입니다. 런타임에 발생하는 일은 인스턴스에 대한 참조가 일반 이전 함수에 암시적으로 전달된다는 것입니다. Rust는 이것을 좀 더 명시적으로 만듭니다. 다음은 구조체 에 .hi()메서드를 추가하는 코드입니다 .Greeter

impl Greeter {
    fn new(person: String) -> Self {
        Self {
            person,
        }
    }

    fn hi(&self) {
        let who = self.person.as_str();
        println!("Hello, {who}!");
    }
}

...에 대한 참조 self? 이번에는 소문자 자기? 예. 이것이 Rust가 인스턴스 메서드를 정의하는 방법입니다. 첫 번째 인수는 &self실제로 의 약어 이므로 의 유형에 대한 참조인 바인딩 이름이 지정 self: &Self됩니다 . 첫 번째 인수는 a , a 또는 a 일 수 있습니다 . 우리는 처음에 변형을 보았습니다. 그것은 인스턴스를 소비하는 인스턴스 메서드입니다. 따라서 메서드를 호출하는 데 사용된 바인딩은 일단 호출되면 쓸모 없게 됩니다. 이 구조체와 관련된 상태를 변경하기 때문에 변경 가능한 참조가 필요하다고 컴파일러에 알립니다. 한 가지 예는 Java의 setter이거나 예를 들어 . 제공된 새 항목을 재할당하려면 selfSelfGreeter&self&mut selfselfselfOption.unwrap()&mut selfset_personstruct GreeterString우리 person필드에 대한 참조는 변경 가능해야 합니다.

fn set_person(&mut self, person: String) {
    self.person = person;
}

로 선언 하면 필드 에 새 값을 할당할 때 &self변경하려고 시도하므로 컴파일러에서 불평할 것 입니다.selfperson

$ cargo run -- Jane
   Compiling rusty-java-2 v0.1.0
error[E0594]: cannot assign to `self.person`, which is behind a `&` reference
  --> src/main.rs:32:9
   |
31 |     fn set_person(&self, person: String) {
   |                   ----- help: consider changing this to be a mutable reference: `&mut self`
32 |         self.person = person;
   |         ^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written

For more information about this error, try `rustc --explain E0594`.
error: could not compile `rusty-java-2` due to previous error

아래는 main.rs이러한 모든 변경 사항이 포함된 현재 상태의 전체 내용입니다. 그리고 몇 가지 작은 변경 사항이 더 있습니다.

   

이제 우리는 메서드 person뿐만 아니라 참조를 반환하는 필드에 대한 getter도 가지고 있습니다 . bye()그 메서드의 본문은 이전에 본 것과 약간 다릅니다 hi(). 둘 다 사실상 동일합니다. 사람의 이름을 인쇄하기 위해 사람의 참조를 얻습니다. 23번째 줄  메서드 hi()에서 self.person필드 를 가져오고 사용할 .as_str()a를 반환하는 the를 호출하는 &str 반면, 28번째 줄println! 에서는 매크로 호출 내에서 the 에 대한 참조 , 즉 a 를 가져 &옵니다 . 두 경우 모두 구조체 밖으로 이동하지 않습니다 . 그 이동은 불법입니다. 우리는 필드만 참조합니다.self.person&Stringself.person

이제 실행하면 다음과 같은 결과가 나타납니다.

❯ cargo run -- Jane
   Compiling rusty-java-2 v0.1.0
    Finished dev [unoptimized + debuginfo] target(s) in 0.59s
     Running `target/debug/rusty-java-2 Jane`
Hello, Jane!
... and goodbye, Jane!

이제 이 구조체를 사용하여 차용을 약간 재생하면 이전 의 참조 규칙을 테스트할 수 있습니다.

주어진 시간에 하나의 가변 참조 또는 여러 불변 참조를 가질 수 있습니다.
— The Rust Book
참조 규칙

예를 들어 이것이 무엇을 할 것이라고 생각합니까?

let mut greeter = Greeter::new(String::from("Jane"));

let reference = &greeter;
greeter.set_person(String::from("John"));
reference.hi();

글쎄, 그것은 우리의 간단한 규칙을 위반하기 때문에 컴파일되지 않을 것입니다:

let reference = &greeter;
                -------- immutable borrow occurs here
greeter.set_person(String::from("John"));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
reference.hi();
-------------- immutable borrow later used here

의 메서드 선언을 보면 문제가 표시됩니다 set_person(&mut self, person: Person). 가 필요 &mut self하므로 메서드를 호출할 때 묵시적으로 greeter가변적으로 차용하려고 시도합니다. 불변 참조가 아직 살아 있기 때문에 우리는 할 수 없습니다. greeteron 을 호출하기 위해 대신 사용한다면 .hi()불변 참조는 "죽은" 상태가 되고 코드는 작동할 것입니다…

이 다른 간단한 예가 무엇을 할 것이라고 생각하십니까?

let mut greeter = Greeter::new(String::from("Jane"));

let person = greeter.person();
greeter.set_person(String::from("John"));
greeter.hi();
println!("Our previous person: {person}");

person이것은 우리가 인사 하는 사람 의 필드에 대한 참조를 차용하고 있기 때문에 조금 덜 명확할 수 있습니다 . 그러나 생각해 보면 결과가 이전과 거의 같다는 사실에 놀라지 않을 것입니다.

let person = greeter.person();
             ---------------- immutable borrow occurs here
greeter.set_person(String::from("John"));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
greeter.hi();
println!("Our previous person: {person}");
                                ------ immutable borrow later used here

빌림 자체의 "전이성"은 .person컴파일러 greeter에 의해 추적되므로 동일한 오류가 다시 발생합니다. 내부 에 대한 참조가 아직 있는 동안에는 내부 를 새 것으로 set_person교체 할 수 없습니다 . 이를 교체하면 여전히 사용 중인 이전 값을 -ping하는 것을 의미합니다. 마지막 참조가 만료된 후에만 정리할 가비지 수집기가 없다는 것을 기억하십시오.StringgreeterDrop

이 간단한 예제를 사용하여 참조의 수명 주기 를 실험 하고 참조 규칙이 어떻게 적용되는지 확인할 수 있습니다. Java 개발자로서 이 규칙에 익숙해지고 코드에서 데이터를 처리하는 방법에 대해 더 많이 생각하는 데 시간이 걸립니다. Rust는 데이터와 참조를 저장하는 위치와 방법에 대해 조금 더 생각해야 합니다.

지금 이 규칙이 왜 있는지 궁금하거나 때때로 실제로 도움이 되기보다는 제약이 더 많다고 느꼈을 수도 있습니다. 다른 스레드에 의해 동시에 수정되는 것에 대한 참조 외에 greeter.person, 이 가드에 값을 해제하는 것보다 더 많은 가치가 추가되지 않습니다… 또는 거기에 있습니까? 다음과 같은 간단한 자바 코드를 살펴보겠습니다.

List<Integer> list = new ArrayList<Integer>();

list.add(1);
list.add(2);
list.add(3);

for (Integer i : list) {
    System.out.println(i);
    list.remove(0);
}

목록을 반복하면서 값을 인쇄하고 이동하면서 제거합니다. 이 멍청한 예제와 달리 "실제" 코드에서는 이것이 계속 발생 합니다. 한동안 Java를 사용해 왔다면 이 작업이 이미 명확할 수 있지만 실행 결과는 다음과 같습니다.

1

Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1013)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:967)
	at Program.main(Program.java:12)

글쎄, 우리는 이것에 대해 너무 멀리 가지 않았습니다! A ConcurrentModificationException, 단일 스레드에서! 이제 동일한 코드를 Rust에서 사용해 봅시다:

let mut items = vec![1, 2, 3];

for i in &items {
    println!("{i}");
    items.remove(0);
}

여기서 무슨 일이 일어나고 있는지 먼저 설명하겠습니다. Vec<i32>편리한 vec!함수형 매크로에서 다시 생성 합니다. 벡터에 있는 요소의 유형은 i32, 부호 있는 32비트 정수 - Java의 int입니다. 이는 Rust에서 정수 리터럴이 평가하는 것이기 때문입니다.

그런 다음 vec 에 대한 참조 를 반복합니다 ?! 음 ... 아니. 거기에 있는 for 루프에는 컴파일러에 의해 추가된 구문 설탕이 있습니다. for i in items- 앰퍼샌드 없이 - 는 와 동일합니다 for i in items.into_iter(). from 의 소유권을 iterator into_iter() 로 이동 하는 곳 입니다. 결국 각 항목의 소유권은 루프로 이동됩니다. While  루프 의 각 요소에 대한 참조를 제공 하고 컬렉션을 그대로 유지하는 와 동일합니다.Vecveci in &itemsi in items.iter()vecitems

루프 블록은 이제 간단해야 합니다. 이것을 실행하면 어떻게 될까요?

for i in &items {
         ------
         |
         immutable borrow occurs here
         immutable borrow later used here
    println!("{i}");
    items.remove(0);
    ^^^^^^^^^^^^^^^ mutable borrow occurs here

음, 참조 규칙은 우리가 우리의 에 대한 변경 가능한 참조를 가져오는 것을 불가능하게 만들 것입니다. items우리는 암묵적으로 which 가 그것을 변경하기 위해 .removea &mut self를 호출하여 수행 Vec합니다. 우리가 불변 참조를 사용하여 해당 Vec.

이 코드는 어떻습니까?

let mut items = vec![1, 2, 3];

for i in &items {
    for i in &items {
        println!("{i}");
    }
}

이는 참조 규칙을 위반 하지 않습니다 . 키워드가 mut 있지만 참조가 아니라 를 소유하는 변수에 있습니다 Vec<i32>. 그런 다음 중첩 반복으로 이동하여 최대 2개의 불변 참조가 동시에 활성화되며 이는 규칙에 위배 되지 않습니다 . 이 코드는 이러한 루프 후에 itemsthen:을 변경하지 않고 variable does not need to be mutable첫 번째 i가 사용되지 않는 경우 컴파일러에서 경고를 생성하도록 if this is intentional, prefix it with an underscore합니다.

그렇다면 상황은 Drop어떻습니까?

인스턴스가 범위를 벗어나면 컴파일러는 Drop인스턴스를 -ping하는 역할을 하는 일부 코드를 삽입합니다. 즉, 더 많은 인스턴스, 파일 디스크립터, 소켓 등 보유할 수 있는 모든 리소스를 해제하고 결국에는 String 인스턴스용 힙의 메모리와 같이 사용한 메모리를 해제합니다.

Rust가 리소스 해제를 처리하는 방법을 이해하기 위해 약간의 실험을 시작하겠습니다. 로 빌드한 이 hi/bye "관용구"를 기반으로 빌드 Greeter하지만 약간 변경합니다. "안녕하세요!" 한 번은 항상 "bye"라고 표시되어 있는지 확인하십시오. 바로 시작하겠습니다.

   

좋아, 그래서 우리는 이미 무엇을 알고 있습니까? struct두 가지 유형 을 선언 합니다. Scope  TrackedScope. 둘 다 String이라는 힙 할당 필드 를 포함하는 동일한 구조를 갖습니다 name.

필드에는 하나 의 Scope기능과 하나의 메서드가 있습니다. 이 함수는 간단하지만 이전 에 약간의 유용성을 추가하고 Greetera 를 생성하기 전에 &str할당된 힙으로 변환합니다 . 방법 은 조금 더 흥미롭습니다. 참조를 받지 않고 대신 소비 합니다! 그러나 그렇게 하기 전에 범위가 이제 시작되었음을 인쇄한 다음 인스턴스에서 새로 생성된 인스턴스로 이동 한 다음 반환된 인스턴스 를 반환합니다. 따라서 이름은 보존되지만 원래 인스턴스는 삭제됩니다.Stringstruct Scopestart&selfselfTrackedScope StringScopeTrackedScopeScope

에 대해 얘기 Drop! 에 대한 impl블록 도 TrackedScope있지만 특성을 구현합니다 Drop. fn drop(&mut self)Java 인터페이스와 동등한 특성 은 범위가 종료되었음을 인쇄하여 여기에서 구현 하는 단일 메서드를 선언합니다 . 해당 drop메서드 호출은 컴파일러가 올바른 위치에 자동으로 추가하는 것입니다. 코드에서 수동으로 해당 메소드를 호출할 수는 없지만 컴파일러는 (다시!) 이를 금지합니다.

수동으로 drop무언가를 원 .drop()하고 인스턴스에서 호출하는 경우 표준 라이브러리에서 사용할 수 있는 편리한 유틸리티 함수가 있습니다 std::mem::drop. drop그 기능이 얼마나 특별한지 , 신뢰할 수 없는 실제 인스턴스에 어떤 종류의 마법을 사용하는지 궁금하실 것 입니다! 자, 한번 살펴봅시다! 그 아래에는 이 신비한 유틸리티 함수의 전체 소스 코드가 있습니다.

pub fn drop<T>(_x: T) {}

기다리다?! 뭐라고요? 그것은… 비어 있습니다!

예 그렇습니다. 함수 서명에서 마술이 다시 발생합니다. 전달된 인수의 소유권을 갖습니다! 이 메서드는 범위가 없는 일반적인 over T이므로 무엇이든 허용합니다. 그리고 그것 으로 절대 아무것도 하지 마십시오 ! 하지만 그 함수를 호출할 때 의 소유권 _x이 이 범위로 이동한 다음… 컴파일러는 범위를 벗어나는 것을 확인하고 필요한 정리 코드를 삽입합니다!

이제 아래의 몇 가지 경우를 고려하여 코드에서 -ing이 Scope어떻게 발생하는지 지금 사용하겠습니다 .drop

   

주목할 가치가 있는 것은 우리가 10행 에서 끝나는 7행 에 합성 블록을 추가한다는 것 입니다. 또한 범위 는 시작할 때 변수에 바인딩되지 않습니다. 그렇다면 출력은 어떻게 되어야 한다고 생각하십니까? 이것을 실행하고 보자:two

Scope 1 started
Scope 2 started
Scope 2 ended!
Scope 3 started
Scope 3 ended!
Scope 4 started
Scope 4 ended!
Scope 1 ended!

아마 놀랍지 않게, 시작 되기 직전 에 라인 10three 의 블록 끝에서 드롭됩니다 . 반환된 항목을 바인딩하지 않으므로 시작 직후 삭제되지만 바로 정리할 수 있습니다. while 은 해당 블록의 마지막 문과 유사하게만 작동합니다. 외부 범위에서 먼저 then 을 시작하여 결과를 로컬 변수에 바인딩하고 역순으로 -ped되는 것을 볼 수 있습니다 . first , then . 말이 되네요. 나중에 선언된 구조체 바인딩은 이전에 선언된 항목에 대한 참조를 보유할 수 있으므로 역순으로 삭제하면 제대로 정리됩니다!fourtwoTrackedScopethreeonefourdropfourone

요약하자면

그것은 다시 꽤 많은 내용이었습니다. 우리는 지금까지 소유권 의 개념을 훨씬 더 깊이 탐구했습니다. 주어진 데이터 조각의 소유자는 단 한 명뿐입니다. 그러나 해당 소유권은 이전될 수 있으며 이동 이라고도 합니다 . 그런 다음 참조 규칙에 따라 데이터에 대한 참조를 빌릴 수 있는 방법을 살펴보았습니다 . 마지막으로 Rust 컴파일러가 Drop 구조체 인스턴스를 -ping하여 리소스를 해제하는 방법을 확인했습니다.

우리는 실제로 struct우리 자신의 새로운 유형을 선언하고 함수와 메소드를 추가함으로써 이 작업의 대부분을 수행했습니다. &self이렇게 함으로써 우리는 구조체 에 선언될 수 있는 &mut self  가지 다른 유형의 메서드를 살펴보았습니다 self.

마지막으로 Rust에서 for 루프가 작동하는 방식과 Java와 다른 점을 엿볼 수 있습니다. 또한 Rust 표준 라이브러리의 코드를 사용하여 위 원칙의 일부 사용법을 설명했습니다. Java와 마찬가지로 해당 소스 코드를 읽을 수 있으며 Rust 표준 라이브러리 개발자가 언어를 활용하여 몇 가지 기본 문제를 해결하기 위해 코드를 작성하는 방법에 대해 더 잘 알기 위해 일부 시간을 할애하여 일부를 읽는 것이 좋습니다. 우리가 std::mem::drop().

cargo clippy 코드를 자주 실행 하라! 일단 컴파일되면 얻은 것을 리팩토링하는 데 시간을 보내십시오. 그리고 재실행 clippy! 자신의 용어로 언어를 탐색하는 데 시간을 보내는 것이 아마도 Rust 작성을 더 잘 다룰 수 있는 가장 좋은 방법일 것입니다! Java에서는 데이터가 상주해야 하는 위치, 즉 프로그램의 어느 부분이 어떤 데이터를 소유하고 해당 데이터를 효율적으로 공유할 수 있는지에 익숙해지는 것이 처음에는 다소 어려울 수 있습니다. 그러나 데이터가 코드를 통해 흐르는 방식에 대한 저항이 가장 적은 경로를 찾는 것이 결국 더 나은 Java 작성으로 이어질 것이라고 믿습니다.

우리가 다루어야 할 것이 훨씬 더 많습니다. 따라서 Java에서 오는 Rust에 대한 다음 모험과 함께 이번 달에 새로운 게시물을 기대하세요! 이것이 통찰력이 되었기를 바라며, 주저하지 말고 의견, 의견, 제안, 수정 사항, 불만 사항을 남겨주십시오…

https://wcgw.dev/posts/2023/rusty-java-2/#_where_did_we_get_so_far

728x90
728x90
반응형

 

 

https://github.com/graphul-rs/graphul

 

GitHub - graphul-rs/graphul: Optimize, speed, scale your microservices and save money 💵

Optimize, speed, scale your microservices and save money 💵 - GitHub - graphul-rs/graphul: Optimize, speed, scale your microservices and save money 💵

github.com

 

Graphul Web Framework

NodeJs 에서 사용하고 있는 Express 웹프레임워크에 영감을 받아 Rust 언어로 구축된 웹프레임워크

속도와, 마이크로서비스의 확정상을 개선하기 위해 디자인되어 있음

Rust로 작성되었기 때문에 메모리 안정성, 신뢰성, 동시성 과 퍼포먼스를 보장받는다..


Rust 용으로 만들어진 기존 프레임워크 개념의 다양한 어플리케이션들이 많이 나오고 있다.

Rust에 관심을 가지고 꾸준히 찾아보고 있어서 그런 느낌을 받을 수 있을것 같긴한데.. 좋은 컨셉의 제품들이 꾸준히 그리고 빠르게 출시되고 있어서 미래가 밝다고 볼 수 있다.

꽤나 기대가된다.

한 5년 정도 잡고 틈틈히 공부를 해서 마스터 해야겠다.

728x90
728x90
반응형

Electron
https://www.electronjs.org

 

Electron | Build cross-platform desktop apps with JavaScript, HTML, and CSS.

Build cross-platform desktop apps with JavaScript, HTML, and CSS.

www.electronjs.org

특징 : Chrominum 을 기반으로 여러 Frontend Framework 를 조합해서 개발

Tauri
https://tauri.app/

 

Build smaller, faster, and more secure desktop applications with a web frontend | Tauri Apps

Tauri is a framework for building tiny, blazing fast binaries for all major desktop platforms. Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface.

tauri.app

특징 : Rust 언어로 만들어진 Form 에 여러 Frontend Framework 를 조합해서 개발

WAILS
https://wails.io

 

The Wails Project | Wails

Build beautiful cross-platform applications using Go

wails.io

특징 : Go 기반에 여러 Frontend Framework 를 조합해서 개발

===================================

대표적인 Cross Plaform Application 개발 기술들이다.

Electron이 가장 오래되었고 각종 유명한 프로그램들이 Electron을 기반으로 만들어졌다.

가장 대표적인건 VS Code 이다. 

하지만 Chrominum 자체 배포에 용량이 크다는 문제점이 제기되는데 대안으로 Rust 언어로 만들어진 Tauri가 차츰 조명을 받으며 부상하고 있다. 

그리고 Tauri와 WAILS 의 비교를 보면 Tauri가 현재 좀더 핫하긴한데 특이한건 Wails의 성장속도가 꽤 가파르다는 사실이다. 아무래도 Rust 언어의 학습곡선보다 훨씬 낮은 Go 언어의 장점이 개발자들에거 더 어필하고 있는것 같다. Wails의 특장점은 아직 자세하게 파악되지 않았다. 그래서 다음 링크를 대체하려고 한다.

https://www.libhunt.com/compare-tauri-vs-wails

 

tauri vs Wails - compare differences and reviews? | LibHunt

First of all, I do like sciter, it's fresh air in wails,webview,electron & tauri.There are several cases why I prefer an electron: BrowserView, FileSystem api, newer css feature(Interop 2022 are greate), and all the newer js feature I use but I don't know

www.libhunt.com

 

728x90
728x90
반응형
Announcing Unreal Rust

https://www.reddit.com/r/rust_gamedev/comments/n9v8m9/rust_in_unreal_engine_may_2021_summary/

 

 

Rust in Unreal Engine (May 2021 Summary)

[Unreal Engine](https://www.unrealengine.com/en-US/) needs no introduction. It is *the* most powerful game engine in the world, with *the* best...

www.reddit.com

 

재미있는 글이 있었다.

Unreal Engine에 Rust를 사용할 수 있는냐 라는 글에 대한 내용인데 할 수는 있는데 좀 회의적인 반응의 글이다.

글 내용중에 곧 Unreal Engine 에서Unreal Verse 라는 Future Scripting Language 를 발표할꺼라는 내용이 좀 흥미를 끌었다. Python과 Lua의 혼합을 생각나게 하는 완전히 새로운 언어라고 하는데 많은 개발자들이 어려운 C++을 사용하지 않고 접근할 수 있는 일종의 쪽문 같은걸 만들어줄 생각인가보다.

 

그것보다 더 흥미로운 기사가 최근에 발표되었다.

https://maikklein.github.io/unreal-rust-1/

 

Maik Klein

Announcing Unreal Rust 2022-09-04 Links Introduction A few months ago I asked myself "What if I could write a game in Rust, but use Unreal as a renderer?". After a bit of thinking I came to the conclusion that exposing the Unreal renderer to Rust via C ffi

maikklein.github.io

 

C++이 아니라 Rust로 개발할 수 있는 환경을 시도하는것 같다.

아직은 Junk 단계이고 실제 사용할 수 없는 단계이지만 꾸준히 만들어갈 생각인가 보다. 

흥미롭긴한데.. Rust 언어도 C++ 만큼 학습커브를 가지고 있는 언어라서 어느만큼 호응이 있을지 모르겠다.

일단 지켜보자.

https://github.com/MaikKlein/unreal-rust

 

GitHub - MaikKlein/unreal-rust: Rust integration for Unreal Engine 5

Rust integration for Unreal Engine 5. Contribute to MaikKlein/unreal-rust development by creating an account on GitHub.

github.com

https://www.youtube.com/playlist?list=PLps1NSMUeqzicmTej83z-n1J383u1UVq1 

 

Unreal-rust

 

www.youtube.com

 

728x90
728x90
반응형

개발 환경은 Windows 기반으로 진행한다. Docker나 Windows WSL2 로 설정해서 Linux 상에서 개발을 하는것도 나쁘지 않은데 지금은 최대한 빠른템포로 작업을 해야 하기에 익숙한 Windows 환경에서 개발을 전제로 진행할것이다.

VS Code는 설치되어 있다고 가정한다.
Tauri VS Code Extension 추가

개발 OS : Windows 11 (Windows 10에서는 Webview2가 어떻게 설치되는지 확인안됨)
개발언어 : Rust
프레임워크 : Tauri, Yew
DB : 미확정
패키지매니저 : cargo, trunk


먼저 Tauri에서 Webview2를 사용하므로 현재 OS에 Webview2가 설치되어 있는지 확인해보자 (Linux와 macOS는 다름)

1. Rust 설치

https://www.rust-lang.org/learn/get-started

 

Getting started

A language empowering everyone to build reliable and efficient software.

www.rust-lang.org

현재 설치된 Windows OS가 32bit이면 왼쪽, 64bit 면 오른쪽 버튼을 클릭해서 Rust를 설치한다.

설치 후 cmd (Command 창)을 실행해 다음을 입력해본다.

rustc --version

버전이 표시되면 설치가 정상적으로 된것이다.

2. create-tauri-app 설치

RUST 를 설치하면 Cargo가 설치된다. Cargo 는 RUST 의 패키지의 의존성을 관리해주는 패키지 관리자 이다.

요즘 각 언어들의 패키지를 관리해주는 패키지 관리자들이 너무 많은데 여러 언어들을 조합해서 사용하다 보면 각각의 패키지 매니저들의 명령어들을 알아야 하는데 조금씩 틀려서 너무 헷갈린다.

시간내서 주로 사용하는 패키지 매니저들을 수집해보고 많이 사용하는 명령어들을 한곳에 모아두는 글을 작성해볼까 한다. 내가 너무 힘들다. 명령어 각각 외우려니깐 뒤죽박죽이 되어서 계속 헤맨다.

자 일단 Tauri app 프로젝트를 만들기위해 create-tauri-app 을 설치해보자

cargo install create-tauri-app

설치가 완료되면 설치된 패키지 확인을 해본다.

tauri-cli도 설치를 해야 하는데 create-tauri-app을 설치하면 패키지 리스트에는 나타나지 않지만 같이 설치가 되는것 같다.(좀 더 확인이 필요함)

cargo install --list

정상 설치가 확인이 되면 개발할 프로젝트를 생성해보자.

일단 프로젝트 명칭을 정해야 한다. 프로젝트명이 폴더명이 되므로 원하는 명칭을 미리 생각해둔다.
현재 프로젝트는 graduateapp-yew 로 정했다.

프로젝트 생성을 할때 다음의 절차를 가진다.

1. 프로젝트 명 등록 : 폴더명
2. 패키지관리자를 선택한다 (cargo, pnpm, yarn, npm)
3. 사용할 프론트엔드 프레임워크
> 어떤 패키지 관리자를 선택하느냐에 따라 선택할 프론트엔드 프레임워크가 다르다.
> 현재는 yew를 사용할 것이므로 cargo를 선택한다.

이렇게 3가지를 등록 선택하고 나면 프로젝트가 생성된다.


기본적인 템플릿형태로 프로젝트가 생성되기 때문에 한번 실행해 볼 수 있다.

하지만 yew의 경우는 별도의 추가적인 설치가 더 추가되어야 한다.

WASM 을 빌드/배포 하고 localhost 서버를 구동해주는 모듈이 필요한데 2가지 중 선택해서 사용하면 된다.

Trunk 사용

https://www.yew.rs/docs/getting-started/project-setup/using-trunk 

 

Using trunk | Yew

Install

yew.rs

wasm-pack 사용

https://yew.rs/docs/getting-started/project-setup/using-wasm-pack

 

Using wasm-pack | Yew

This tool was created by the Rust / Wasm Working Group for building WebAssembly applications. It supports packaging code into npm modules and has an accompanying Webpack plugin for easy integration with existing JavaScript applications. More information is

yew.rs

 

trunk는 빌드/배포와 local서버를 같이 사용할수 있고 wasm-pack은 빌드만 가능하고 local서버를 별도의 외부 모듈을 사용하는 형태로 사용되는데 자신에게 맞는 형태의 것들 사용하면 되겠다. 두가지의 장단점은 아직 잘 모르겠다. 그런데 특이하게 wasm-pack 의 인기도가 더 높은것 같아보여서 혹시 나중에 정리할 수 있다면 정리해보도록 하겠다.

그리고 현재 wasm-pack 을 cargo로 설치하면 openssl 관련 오류 떄문에 설치가 정상적으로 되지 않는데 wasm-pack 홈페이지에서 제공하는 exe 파일을 다운받아서 실행하면 사용가능하다.

일단 이번 프로젝트에서는 trunk 를 사용하기로 하고 trunk 관련 모듈을 설치한다.

# WebAssembly 대상 설치
rustup target add wasm32-unknown-unknown

# Trunk 설치
cargo install --locked trunk

# need to install wasm-bindgen manually.
cargo install --locked wasm-bindgen-cli

trunk 와 wasm-bindgen-cli 이 모두 설치되었고 안보이던 tauri-cli v1.1.1 도 리스트에 나타났다.

자 이제 설치는 모두 끝났으니 graduateapp-yew 폴더로 이동 후 앱을 개발모드로 실행해보도록 하자

-- 프로젝트 폴더로 경로를 이동한다.
cd graduateapp-yew

-- Tauri 실행
cargo tauri dev

 

 

정상적으로 실행되었다.

기존에 실행하던 svelte 와 react 연동보다 실행속도가 확실히 빠르다는걸 느낄수 있다.

 

내친김에 release 배포 build도 진행해보자

cargo tauri build

release 빌드를 실행하면 다음과 같은 오류가 발생한다.

 

tauri.conf.json 에 identifier 항목의 'com.tauri.dev' 가 앱 사이에서 유니크한 명칭이어야 한다는것 같은데 관련 글들을 읽어봐도 정확한 의미를 모르겠다. 일단 release 빌드 가능하도록 수정해주자

'com.graduateapp-yew.dev' -> 'com.graduateapp.yew'

그리고 tauri.conf.json 설정 파일에서 몇가지 더 수정해야 할 부분이 있는데 수정하지 않더라도 빌드 및 실행은 상관없지만 최종 배포본을 만들기 위해 언젠간 수정을 해줘야 할부분이라서 몇가지만 수정하고 가도록 한다.

Google 에 tauri.conf.json 으로 검색해보면 상단에 Configuration - Tauri Apps 링크가 보인다. 클릭하여 들어가보자

https://tauri.app/v1/api/config/

 

Configuration | Tauri Apps

The Tauri configuration object. It is read from a file where you can define your frontend assets, configure the bundler, enable the app updater, define a system tray, enable APIs via the allowlist and more.

tauri.app

꽤 많은 항목들이 있는데 추후 필요한부분 체크할때 참고해서 보도록 하자

release 모드로 빌드시 Wix 모듈을 사용해서 자동으로 설치파일을 만들어 주는데 그때 파일명으로 사용하는 속성

Package > ProductName : "GraduateTrading"

프로그램 title 명칭

Windows > title : "원하는 타이틀명칭"

 일단 두 부분만 원하는대로 수정해둔다.

cargo tauri build

다시 빌드를 해보고 target 폴더를 살펴보자

 

release > bundle > msi  폴더에 exe 실행파일이 생성되었다.

 

설치를 해보자

 

Launch GraduateTrading 항목을 체크하고 Finish 버튼을 클릭하자.

거의 Native 앱 정도로 빠르게 실행되는 Tauri App을 볼 수 있을것이다.

Release 모드로 빌드했을때 설치형 exe 파일과 실행형 exe 파일이 동시에 생기는데 설치하지 않고 실행만 하려면 
Target > release 폴더에 있는 GraduateTrading.exe 파일을 직접 실행하면 된다.

 

이제 Tauri 에 대한 경험을 마쳤으니 다음 장부터는 생성된 프로젝트 구조 분석과 Rust - Tauri - Yew - Trunk 간의 관계를 분석해 보도록 하겠다. 그래야 어떤 기술에 먼저 집중할 것인지 결정할 수 있을테니까...

 

Bye~~

728x90
728x90
반응형
728x90
728x90
반응형

어제 Tauri + Svelte 기반의 코인 매매 앱을 만들겠다고 첫글을 올렸다.

검색을 해보다 보니내가 만들 컨셉에 더 맞는 조합이 보여서 추가적으로 브렌치를 따기로 했다.

혹시 돈을 많이 벌기 위해 만드는 거냐고 생각할 수 있겠지만 매매프로그램 만드는게 쉽지 않다. 단순히 포트폴리오 정도로 생각하는게 더 적당할 듯 하다. 혹시(?) 잘되면 뭐 대박!!

 

tauri, yew에 대한 자세한 설명은 별도 카테고리에 설명을 하기로 하고 일단 개발환경 설치 부터 필요기술들에 대해서 하나씩 작성해보기로 하겠다. yew (Webassembly : WASM) 기반의 비동기 프로그래밍을 하기 위한 프론트엔드 프레임워크이다. 아직 초창기 버전이라 커뮤니티도 형성이 되어있지 않고 부족한 부분이 많겠지만 만들려고 하는 컨셉에는 많은 기능의 UI 컨트롤들이 필요하지 않고 성능과 안정성이 더 우선이기 때문에 큰 문제는 없지 않을까 싶다.

Tauri + Yew 기반 실행 화면

https://www.rust-lang.org

 

Rust Programming Language

A language empowering everyone to build reliable and efficient software.

www.rust-lang.org

https://tauri.app/ko/

 

Build smaller, faster, and more secure desktop applications with a web frontend | Tauri Apps

Tauri는 주요 데스크톱 플랫폼을 위한 작고 불티나게 빠른 바이너리를 만드는 프레임워크입니다. 개발자는 사용자 인터페이스를 위해 HTML, JS, CSS로 컴파일되는 그 어떤 프론트엔드 프레임워크라

tauri.app

https://yew.rs

 

What is Yew? | Yew

Yew is a modern Rust framework for creating multi-threaded

yew.rs

 

Bye~~

728x90
728x90
반응형

기대하고 있던 Tauri 가 1.0  정식버전이 릴리즈 되었다. -> 1.1 버전으로 최근에 업그레이드 되었네.

Electron의 무거움에 배울까말까 고민하고 있던 터엿는데 Tauri가 출시되면서 학습할 동기를 만들어준것 같다.

그래서 학습용으로 뭘 만들까 고민을 하다가 코인 매매앱을 만들어 보기로 했다.

이름은 심플하게 GraduateApp-TAURI 이다. 코인으로 졸업하게 해주세요 젭알!!! ㅠ.ㅠ

농담이고 일단 많은 기술적인 난제가 있을것 같긴한데 하나하나 만들어가면서 방법을 찾아보도록 하겠다.

개발초기 몇년간은 웹쪽에 관심이 있다가 너무 급여가 팍팍한데다가 정적인 페이지 기술의 한계가 보여서 CS(C#, JAVA)계열로 넘어갔지만 웹에 대한 관심은 항상 있었다. 그래서 하나 배워서 다 같이 연동해서 써먹을 수 있는게 없을까 항상 고민을 했는데 최근에 찾은 언어가 Rust 이다. 시스템 프로그래밍, 웹, 모바일, 데스크탑 프로그래밍  모두 가능하도록 계속 진화하고 있는데 지켜보고 있으면 뿌듯해진다. 내 주력언어가 되기를 기원하며 조금씩 학습을 진행하고 있다.

하지만 Rust는 아직 비주류 언어라서 대한민국에서 취업을 위해 배우기에는 시간적 리스크가 있고 학습곡선도 높기때문에 일반적인 업체 취업용으로는 추천하지 않는다. 다만 긴 호흡을 가지고 꾸준히 배우고 싶다면 한 번 도전해도 좋지 않을까 싶다. 그리고 Svelte도 핫한 언어이긴 하지만 취업용으로는 아직 추천하지 않는다.

이 메뉴 카테고리는 Tauri Svelte Vite 를 가지고 개인적인 프로그래밍을 하면서 학습내용을 정리하고 공유하는 곳이기에 Rust에 대한 사설은 더 하지 않겠다. Rust는 별도 메뉴에서 다룰 예정이다.

===============================================

Tauri가 뭔가?  황소!!

https://www.tauri.app

 

Build smaller, faster, and more secure desktop applications with a web frontend | Tauri Apps

Tauri is a framework for building tiny, blazing fast binaries for all major desktop platforms. Developers can integrate any front-end framework that compiles to HTML, JS and CSS for building their user interface.

tauri.app

https://vitejs.dev/

 

Vite

Next Generation Frontend Tooling

vitejs.dev

https://svelte.dev/

 

Svelte • Cybernetically enhanced web apps

Svelte is a radical new approach to building user interfaces. Whereas traditional frameworks like React and Vue do the bulk of their work in the browser, Svelte shifts that work into a compile step that happens when you build your app. Instead of using tec

svelte.dev

 

짜잔~~

개발에 사용할 굵직한 기술 3가지이다.

이렇게 3가지를 선택한 이유는 간단하다.

코인앱을 만들기에 속도적인 부분이 좀 중요한 포인트기 때문이다.

처음에는 Electron + Viewjs or React를 고민했는데 대체 할수 있고 성능적인 부분도 우위에 잇는 Tauri와 Svelte가 나타나서 냉큼 바꿔버렸다.

하나씩 기술적인 내용을 확인하고 개발목표와 목차들을 구성해 보도록 하자.

 

Bye!!

728x90
728x90
반응형

함수형 프로그래밍에 대한 개념을 이해하고 정리하여 문서로 남기기위해 검색을 하는 도중 다음과 같은 좋은 변역 블로그를 발견했다. 관심있으시면 한번 읽어보고 개념을 잡아보기 바란다.

프로그래밍 패러다임은 크게 2가지로 분류되고 세부적으로 분류하면 3가지로 분류할수 있다.

절차지향, 객체지향, 함수형 프로그래밍

각 패러다임의 단점들을 보완하기위해 순차적으로 발전된 형태로 진화하고 있는것인데 그렇다고해서 오른쪽의 것이 항상 좋은것은 아니다. 각각의 장단점이 존재하기 때문에 프로젝트 규모나 성향에 따라서 잘 선택해서 사용해야 한다.

아직 함수형 프로그래밍에 대해 익숙하지 않은데다가 어떤 단점이 있는지 조사하고 확인 중이라 함수형 프로그래밍이 다른것 보다는 좋다고 말할 수는 없을것 같은데 아래의 글들을 읽고나니 어느정도 감이 잡힌다.

블로그 주인장의 다음 요약글 중에 CPU에 관한 글이 앞으로 함수형 프로그래밍 패러다임을 배워야 할 당위성 중에 가장 와 닫는다. 그리고 관심있게 공부하고 있는 RUST 언어의 특성 중 가변 속성이 아닌 불변 속성을 지향 하는 이유도 이해할 수 있었다.

https://front-end.me/javascript/functional-programming-6/ 원문 중에서

단기간 학습해서 사용하겠다는 개념으로 접근할게 아니라 긴 호흡으로 이해하고 연습하고 적용해야 할 것 같아보인다. 

 

https://front-end.me/javascript/functional-programming-1/

 

[번역] 함수형 프로그래밍 전문가 되기 (Part 1)

이 글은 Charles Scalfani의 So You Want to be a Functional Programmer (Part 1) 를 번역한 게시물입니다. Thank you Charles Scalfani! Thanks to your writing, I can grow further as a developer…

front-end.me

https://front-end.me/javascript/functional-programming-2/

 

[번역] 함수형 프로그래밍 전문가 되기 (Part 2)

이 글은 Charles Scalfani의 So You Want to be a Functional Programmer (Part 2)를 번역한 게시물입니다. Thank you Charles Scalfani! Thanks to your writing, I can grow further as a developer. 함수형 프로그래밍의 개념을 이해하기

front-end.me

https://front-end.me/javascript/functional-programming-3/

 

[번역] 함수형 프로그래밍 전문가 되기 (Part 3)

이 글은 Charles Scalfani의 So You Want to be a Functional Programmer (Part 3)를 번역한 게시물입니다.  Thank you Charles Scalfani! Thanks to your writing, I can grow further as a developer. 함수형 프로그래밍의 개념을 이해하기

front-end.me

https://front-end.me/javascript/functional-programming-4/

 

[번역] 함수형 프로그래밍 전문가 되기 (Part 4)

이 글은 Charles Scalfani의So You Want to be a Functional Programmer (Part 4)를 번역한 게시물입니다.  Thank you Charles Scalfani! Thanks to your writing, I can grow further as a developer. 함수형 프로그래밍의 개념을 이해하기

front-end.me

https://front-end.me/javascript/functional-programming-5/

 

[번역] 함수형 프로그래밍 전문가 되기 (Part 5)

이 글은 Charles Scalfani의 So You Want to be a Functional Programmer (Part 5)를 번역한 게시물입니다. Thank you Charles Scalfani! Thanks to your writing, I can grow further as a developer. 함수형 프로그래밍의 개념을 이해하기

front-end.me

https://front-end.me/javascript/functional-programming-6/

 

[번역] 함수형 프로그래밍 전문가 되기 (Part 6)

이 글은 Charles Scalfani의 So You Want to be a Functional Programmer (Part 6)를 번역한 게시물입니다. Thank you Charles Scalfani! Thanks to your writing, I can grow further as a developer. 함수형 프로그래밍 컨셉들을 이해하는

front-end.me

 

 

https://onlyfor-me-blog.tistory.com/431

 

함수형 프로그래밍이란?

Rxjava, RxAndroid를 공부하는 중인데 둘을 공부하다 보면 함수형 프로그래밍이란 말이 매우 자주 보이고, Rx를 공부하려면 함수형 프로그래밍에 대한 이해가 필요해 보여 따로 정리해둔다. https://ko.w

onlyfor-me-blog.tistory.com

 

https://okayoon.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8C%A8%EB%9F%AC%EB%8B%A4%EC%9E%84%EB%AA%85%EB%A0%B9%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%EC%A0%88%EC%9E%90%EC%A0%81-%EA%B0%9D%EC%B1%84%EC%A7%80%ED%96%A5-%EC%84%A0%EC%96%B8%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8%ED%95%A8%EC%88%98%ED%98%95%EC%9D%98-%EC%A0%95%EC%9D%98-%ED%8A%B9%EC%A7%95-%EB%B9%84%EA%B5%90%EB%A5%BC-%EA%B0%84%EB%8B%A8%ED%9E%88-%EC%95%8C%EC%95%84%EA%B0%80%EC%9E%90

 

프로그래밍 패러다임(명령형 프로그램(절자적, 객채지향), 선언형 프로그램(함수형))의 정의, 특

프로그래밍의 관점을 갖게하고 결정하는 역할인 프로그램의 패러다임에 대해 알아보겠습니다. 발전하게 된 순서는 '절차적 -> 객체지향 -> 함수형'으로 단점들을 극복을 위해 나왔다고 합니다.

okayoon.tistory.com

 

728x90

+ Recent posts