본문으로 건너뛰기

오늘 한 일

  • Rust 소유권, impl, String 공부
  • WebView 해결책 제시

Rust

Memory

: address, offset

memory에는 bit 형태로 데이터 저장, HW에서 다룰 정보는 byte 단위로 처리

address --- word 단위 data (논리적으로 4byte여야만 하는 건 아님)
address를 다루기 위해 variables를 사용
⇒ variable → address → 저장

offset --- byte 단위 data
offset을 다루기 위해 index를 사용


data[2]

→ data: address, [2]: offset

Ownership

: Rust는 ownership 개념을 활용해서 메모리 트래킹, 메모리 누수방지

소유자(Function)가 메모리를 정리할 책임을 가진다 = 함수가 끝나면(={} 이후) 변수를 반납한다


소유권 생성

fn main(){
let dull = Ligth::Dull;
}

변수를 정의한 함수(=owner)가 해당 변수의 소유권을 가진다.


소유권 이전

fn main(){
let dull = Ligth::Dull;

display_light(dull);
}

그 변수를 사용하는 다른 함수(=owner)가 해당 변수의 소유권을 가진다.
따라서 다른 함수가 종료하면 해당 변수를 반납하게 된다 (소유권을 가진 함수의 의무)


잘못된 코드

fn main(){
let a = 10;
func1(a); //1번째 호출
func1(a); //2번째 호출
}

⇒ 1번째 호출 때 func1이 실행되고, a의 소유권은 func1로 넘어간다
따라서 func1(a)가 끝날 때, a를 반납하므로 2번째 호출에서 a를 불러오지 못한다


소유권 참조/대여

fn main(){
let dull = Ligth::Dull;

display_light(&dull);
}

&를 사용, 소유권 이전이 없으므로 변수를 정의한 함수(=owner)가 해당 변수의 소유권을 가진다.


결론

⇒ 기본적으로 Rust는 call by reference 방식을 따르고, reference를 통해 메모리 반납을 관리한다.

이 때 &var 는 call by reference 방식은 유지하되 메모리 소유권을 이전하는 것이 아닌 대여 방식으로 관리하겠다고 명시하는 것이다.


call by value → 새로운 공간에 변수 값 할당

call by reference → 사용중인 메모리 공간의 주소를 넘겨줌

call by name → 함수를 인자로 다룰 때, f()는 함수의 결과값을 f는 함수 자체를 인자로 넘겨주는 것.
따라서 f는 서브루틴에서 실행될 때 결과값이 결정되므로 불필요한 실행 오버헤드를 방지한다.

call by value는 데이터 값을 넘겨준다고,
call by reference는 메모리 주소 값을 넘겨준다고,
call by name은 함수의 이름(메모리 주소)을 넘겨준다고 생각하면 된다.


impl

: enum, struct를 더 쉽게 관리할 수 있게 한다.

함수에서 해당 enum, struct를 인자로 받아올 때, 그 함수는 해당 enum, struct와 밀접하게 연관되어 있다.
그 struct가 정의되지 않으면 함수는 의미를 가지지 못하기 때문 → 해당 데이터구조와 연계한 정의

fn main() {
let hot = Temperature { };
Temperature::show_temp(hot);
}

struct Temperature{ }

impl Temperature{
fn show_temp(&self){
... //using self
}
}

+ impl의 참 의미 적용

fn main() {
let hot = Temperature { };
hot.show_temp();
}

struct Temperature{ }

impl Temperature{
fn show_temp(&self){
... //using self
}
}

⇒ 구조체를 마치 class처럼 사용 가능하다.
field는 struct 안에서 정의, struct를 사용하는 함수는 impl 안에서 정의

but, 객체지향 class 에서 method는 객체가 주체적으로 하는 ‘행위(기능)’를 표현할 때 적용한다.
impl은 객체(STRUCT)가 수동적으로 활용되는 상황에서 함수를 정의할 때 적용한다는 차이가 있다.

+ 생성자처럼 사용가능

impl Temperature{
fn freezing() -> Self{
Self { };
}

}

Vector(벡터)

: 정보의 열거 matrix의 관점에서 볼 때, array랑 다를 게 없다.

let numbers = vec![1,2,3];

let mut my_numbers = Vec::new();
vector.push();
vector.pop(); //last added STACK처럼
vector.len();
vector[index];

vector 요소 접근

for num in my_numbers{
... num
}

🎉 깜짝퀴즈

잘못된 코드

fn main() {
let nums = vec![10,20,30,40];

for num in nums{
if num == 30{
println!("thirty");
} else{
println!("{:?}", num);
}
}

println!("{:?}", nums[1]);
}

Ownership 개념을 잊지말자

충격실화 - for문에서 nums라는 벡터를 사용, scope 안에서 nums를 사용하게 되는데, 이때 nums의 소유권은 for문으로 옮겨간다.

따라서 nums가 아닌 &nums 를 넘겨줘야 하므로,


잘못된 코드

fn main() {
let nums = vec![10,20,30,40];

for num in &nums{ //&nums
if num == 30{
println!("thirty");
} else{
println!("{:?}", num);
}
}

println!("{:?}", nums.len());
}

&nums 로 지정했지만 여전히 문제가 있다.

error: no implementation for &{integer} == {integer}

num == 30 비교 과정에서 num은 &nums의 요소로 &{integer} 타입, 30은 integer 타입이므로 비교가 불가능하다고 한다.

& 에 대한 이해가 더 필요해보인다.


올바른 코드

//방법1
fn main() {
...
for num in &nums{ //&nums
if num == &30{ //&30으로 타입 맞춰주기
println!("thirty");
}
}
...
}

//방법2
fn main() {
...
for num in nums{ //&nums
match num{ //match 사용, 단순 수식 비교를 피함
30 => println!("thirty"),
_ => println!("{:?}", num)
}
}
...
}

왜 match에선 &{integer} 타입으로 비교하지 않아도 되는걸까?


match가 동작하는 법

: 패턴 매칭의 기능을 하며, 참조값이 아닌 value값 비교만을 지원한다.
그렇기 때문에 &integer 값 또한 똑같이 value 값인 integer로 비교할 수 있다.


String

: Rust에선 다양한 타입을 지원한다.

String : owned = struct에 값을 저장하고 싶을 때 &str : borrowed = 함수의 인자로 넘겨주고 싶을 때 (일반적인 상황)


&str 생성

"안녕하세요" // literal은 자동으로 borrowed 폼으로 만들어진다.
&{String Type}

String 생성

String::from("안녕하세요"); // String의 함수 사용
"안녕하세요".to_owned(); //&str의 함수 사용

+_::는 관련된 함수를, .는 관련된 함수에 자기자신을 포함하는(함수면 인자로 전달하는) 것을 의미


WebView 통신 해결책?

: 보아하니 alert 창에서 method를 정의할 수 없다고 뜨는 에러가 지속적으로 뜨고있다.
아마 JS에서 사용할 메소드는 postMessage라는 Flutter 라이브러리에서 정의된 함수라 포맷을 맞춰야하는데 저번에 통신에 보낼 인자가 없다는 이유로 아무 인자값이 없이 통신을 보내는 것이 문제라고 생각해서,

통신으로 null을 인자로 postMessage를 보내지말고 빈 JSON 구조라도 넣어서 보내라고 요청해둔 상태다.

=> 감격 ★★★ 드디어 해결 ★★★