Rust만의 특징은 크게 2개 trait와 ownership라고 할수있다
분명 처음 시작은 trait에 꽂혀서였고 (이 무렵 F# inline의 한계를 체감중)
ownership은 뭐 C++ RAII 같은거구나~ 하면서 넘겼다
하지만 내가 Rust를 배우는 도중 한 플젝을 만들면서 인식이 바뀌었다
프로젝트는 대강 이런 게임이였다
먼저 코어 라이브러리를 만들고 각 게임들이 이 코어를 사용해서 게임을 만들면
외부에서 connector를 통해 접속하면 코어에서 별개의 스레드에서 그 게임의 엔트리 함수를 실행해준다
그러면 그 스레드와 연결된 client끼리 connector를 통해 통신을 하고 각 client들이 적절히 UI를 표시해준다
여기서 이 코어 라이브러리가 가장 중요한데 왜냐면 게임의 context마다 스레드가 있고 connector들도 스레드가 있어서
수많은 스레드들의 정보를 안전하게 교환해줘야 하기 때문이다
처음엔 당연히 Rust를 배우려고 시도해본 플젝이므로 Rust로 배워가면서 짰다
하지만 Rust의 ownership은 녹록치 않았다
이런 희한한 소유권 에러가 계속 났고 항상 컴파일러에게 맞아가며 빨리 스코프가 끝나 'a의 지옥에서 벗어나기만을 바라는게 일상이였다
그러다가 문득
'아 C#의 갓갓 GC와 Task라면 이런 조팝 서버는 금방 만들지 않을까?' 하는 망상을 하며 C#을 켰다
분명 C#은 객체가 언제 살고 뒤지고 이게 빌려졌는지 안빌려졌는지 신경쓸 필요가 없었고
Task의 await 뽕은 좋았으며 테스트도 간단히 통과했다
문제는 그 다음이다 분명 통과한 테스트지만 노트북으로 돌려봤더니 터졌다
노트북 문제인가? 하면서 데탑으로 다시 돌려보니 또 터졌다
이쯤오니 어떤 망할일이 벌어졌는지 깨달았다
개판으로 짠 나머지 pass와 failed가 동시에 존재하는 슈뢰딩거의 코드가 돼버린것이다
그리고 시작된 디버깅도중 이런 멀티 스레딩의 버그는 디버거로 잡기 매우 빡친다는 사실을 여실히 느꼈다
애초에 클라를 64개씩 붙이고 돌려야 20%정도 터질정도로 재현이 빡세고 무작정 락을 걸면 데드락에 걸렸다
게다가 64+a개의 Task가 있는 디버거는 내 코드만큼 더러웠다
그제서야 이 코드는 버리는게 답이라는걸 알았고 얌전히 Rust 코드를 다시 들었다
그렇게 컴파일러에게 맞으면서 코딩을 한지 몇주안돼 내 코드는 내가 만든 범위내에선 잘 돌아갔다
뮤텍스를 잘못쓰면 데드락이 걸릴지언정 데이터 레이스는 일어나지 않았고 채널은 아주 편리했다
그때부터 trait와 ownership 둘 모두 사랑하고 컴파일러에게 맞는걸 꺼리지 않게됐다
ㅋㅋㅋ내가 지금 딱 수명에서 개 좆같음을 느끼고 있는 단계임
E0502 죽을때까지 봄 ㅋㅋ
본문 소유권 에러 하나하나가 주옥같네
map 예제는 entry 쓰는게 더 좋을듯
let num = *map.entry("456").or_insert(456);
ㅇㅇ 근데 내가 만들던거엔 entry도 결국 &mut먹는 클로저라 self가 묶여버려서 못썼음 ㅋㅋ