며칠전에 러스트를 배워보고 싶다는 생각에 무작정 rust doc을 찾아서 읽었다.
공식 doc이 있는데 정말 상세하게 나와있는 doc이라는 생각이 들었고 읽는데 많은 시간이 걸리지도 않았다. 현재는 IO프로젝트까지 읽고 해당 grep 프로젝트 코드를 작성한 상태이다.
역시나 모든 언어에 존재하는 변수와 데이터 타입, 함수, 제어문들에 대해 배웠는데 한가지 흥미로운 점은 다른 언어에서는 볼 수 없었던 개념이 언어 전반에 녹아있다는 생각이었다. 예전부터 러스트를 관심갖고 지켜보면서 러스트로 만든 프로젝트 사이트들을 돌아다니면서 시간날때 꼭 배워봐야겠다는 생각을 하면서 어떻게 하면 속도와 메모리 안전성을 둘다 가져갈 수 있는지에 대해 많이 궁금했었다. 그리고 그와 관련된 내용으로 소유권과 참조자, 빌림에 대해 배웠다. 그중에서 가장 신기했던 내용은 바로 빌림을 검사한다는 내용이었다. 또한 빌림 check에 더해서 스코프까지 추가되서 dangling pointer 문제도 해결할 수 있다는 점이 너무 신기했다. 참조되지 않는 메모리가 혼자 덩그러니 남아있을 이유도 없어지게 된다.
하지만 와중에 느낀 점은 결국에는 이러한 점들이 개발 속도를 늦출 것이라는 생각이 들었다. 아직 고급 기능인 클로저나 스레드 혹은 스마트 포인터에 대해 더 공부하지 않았지만 적어도 작은 cli 프로젝트를 만든 현 상태에서는 그렇게 느꼈다. 왜냐면 나는 처음에 ownership과 빌림 check 라는 개념이라는 게 있다는 내용을 보면서 이것이 어떤 기능의 형태로써 존재하는 것이지 않을까 추측했었다. 하지만 이 개념은 마치 일종의 언어 철학처럼 모든 syntax에서 고려해야할 일종의 고려사항이었다. 말 그래도 설계에 녹아있어서 이런 점을 모른다면 이후로 단 한줄의 구문도 작성하지 못할 것이라는 생각이 들었다.
이 언어가 러닝커브가 높다는 말을 들었는데 그 이유도 이러한 녹여진 개념들을 잘 알고 앞으로 작성할 코드에서 계속해서 고려하는 것이 어렵기에 그런 말을 하는 것이라는 생각이 들었다. 또한 다른 언어들에서는 없었던 개념들이기에 생소함에서 오는 어려움이 러닝커브를 높이는 것이 아닐까라는 생각이 들었다.
잠깐 짧은 기간동안 배우게 되어서 아직 부족한 부분이 많고 솔직히 말해서 아직도 String과 String리터럴과의 차이를 언급하면서 등장하는 슬라이스라는 개념이 진짜 잘 이해가 안된다. 또한 rust 컴파일러가 특정 변수의 생명주기인 라이프타임을 쫓아가면서 어디까지 살아있는지 체크하기 위해 사용하는 기능 중의 하나인 'a 혹은 'static 이라는 개념이 있는데 이것도 아리송하다. 한번밖에 읽어보지 않아서 아직 아리송한것 같아서 앞으로 이 부분만 중점적으로 읽어봐야 겠다. 그리고 다른 언어들과는 다르게 String에 대해서 아주 깊게 다루는 언어라는 생각이 들었다.
또한 흥미로운 점은 함수에서 아예 null을 반환할 수가 없게 Result<T, E>를 반환해준다. 즉 null이 없다. 아예 처음부터 Result<T, E>를 반환하게끔 만들어버리는 거다. 대신 제너릭 왼쪽 표기에서 E로 되있는 것 처럼 caller에게 에러를 전파시키면서 에러 처리를 위임시키는데 즉 caller가 마음대로 예외를 처리할 수 있게 해준다. 물론 제대로된 결과가 나왔다면 Ok()이므로 원하는 대로 진행하면 되지만 도저히 처리할 수 없는 순간에는 마치 ctrl + c 와 같은 개념이 존재한다. 바로 panic! 이라는 개념이 등장한다. 뭔가 짐작이 갈 수도 있는데 말 그대로 패닉이다.! 그냥 멈춘다. ctrl + c 처럼 멈춰서 밖으로 나가 버린다. 중학교때 c언어를 작성할때 가끔 이런식으로 그냥 터미널 밖으로 날라가버릴때가 있었는데 약간 그런 느낌이다.
또한 한가지 재밌는 점은 열거형의 다양성이다. 열거형을 굉장히 다양하게 사용할 수 있다. 즉 열거형의 응용이 엄청나다. 구조체와 붙여서 자주 사용하는데 제너릭으로 만들어서 사용할 수도 있고 나중에 검사할적에는 match 라는 구문을 통해 분기로 갈라지듯이 검사하는 기능을 가지고 있다. 이때의 분기를 arm 이라고 한다. match 는 특정 리턴된 값이나 전달받은 값에 대해서 그 값이 어떤 타입인지 혹은 아예 값을 검사하여 arm으로 분기시켜 처리한다. 이걸 보면서 switch 문과 비슷하다고 생각을 하게 되었다.
예전에 어느 커뮤니티에서 러스트를 비판하는 글을 읽은 적이 있었다. 바로 개발 속도와 스타일이다. 개발속도가 느리다는 점은 이미 위에서 언급했는데 한가지 이해가 가지 않았던건 러스트가 구조체를 통해 예전 C 스타일에서 객체지향을 흉내내려고 애썼던 방식과 비슷하게 oop를 처리한다는 글을 본적이 있었다. 그 당시에 그런 글을 볼 적에 왜 러스트는 멀티패러다임언어인데 이런 비판을 받을까? 객체지향도 지원한다는데 왜 이런 비판이 있는걸까? 라고 많이 고민했었다. 왜냐면 그때까지는 내가 기존에 알던 class 문법이 러스트에도 존재하는지 알았다. 이 당시 이 생각이 정말 안일했던게 객체지향이라면 무조건 class 관련 문법이 존재해야 한다고 생각했기 때문이 아닐까. (객체지향을 문법이라고 생각한 사고방식의 잘못이 아닐까? 그저 대상을 객체지향적으로 바라본다면 아무래도 상관없지않을까? 그런데 그렇게 바라보다보니 지금과 같은 syntax가 가장 적합했기에 계속 사용되는 것은 아닐까?)
하지만 이번에 공부하면서 왜 그 글에서 해당 비판을 했었는지 알게 되었다. class 라는 문법조차 없었고 구조체를 필드로써 가져가면서 구조체 메서드를 impl 을 통해 정의할 수 있게 만들어주면서 대상의 행위를 정의해주는 방식으로 구현되는 방식이었다.
class에는 당연히 속성이 있을 것이고 행위가 있을 것이기에 우리가 흔히 접하는 python이나 java에서는 당연히 필드 써주고 메서드 작성해주면 그만이다. 그런데 사람들이 말하기를 예전에 C 에서 객체지향개념을 사용할 적에 구조체를 필드처럼 사용해서 속성을 정의해줬고 함수 포인터를 사용해서 행위를 정의하는 방식으로 사용했고 이것이 문제가 많았고 꼼수같은 기술도 많이 사용했다고 한다. 즉 syntax로 존재하는게 아니라 그냥 테크닉으로서 구현한 것이다. 그런데 rust에서도 이런 방식처럼 쓰고 있다는 비판이 있는 것이다. 물론 C 처럼 작성하는 것은 아니겠지만 class 개념처럼 사람들이 떠올렸던 그런 익숙했던 개념이 아니었다는 점에서 사람들의 기대에 부응하지 못한 이유에서 였다고 생각한다.
그리고 나도 개인적으로 우리에게 너무 익숙한 그런 class 관련 문법들이 즐비했으면 좋겠다는 생각을 했다. 하지만 이것도 결국엔 생소함이라는 생각을 했다. 아직 언어 철학에 대해 깊게 알진 못하지만 반드시 이런 방식을 택한 이유에는 safety를 위해서이지 않을까라는 생각이 들었다.
그리고 이런 면에서도 그렇고 빌림 검사기나 소유권들의 개념들 그리도 변수의 생명주기를 추적해서 더 작은 스코프의 변수가 다른 곳에서 참조됨에도 불구하고 미리 소유권이 말소된다면 얄짤없이 컴파일조차 되지 않는 모습을 보면 어째 이 언어가 각광받는 이유는 speed가 아니라 safety측면에서 뛰어나기 때문이 아닐까? 물론 c/c++과 대등하거나 혹은 아주 근접한 속도로 실행된다고 한다. 하지만 그럼에도 불구하고 러스트를 배우면서 느끼는 점은 러스트 설계자들이 러스트라는 언어를 설계하면서 너희들이 정말 실수하지 않게 만들어줄게...(일부러 실수하고 싶어도 못하게 만들어줄게...?) 라는 각오를 하고 만들었다는 느낌이 든다. 아직 깊은 내용까지 배우지 않았지만 그냥 현재로서 받은 첫인상은 그렇다.
즉 그렇기 때문에 결국엔 개발속도가 느려질 수 밖에 없는 언어라는 점은 분명하다. 러스트를 홍보하는데는 정말 많은 키워드가 있다. 그리고 열성 rust 사용자들인 rustean 분들도 열띤 홍보를 하고 계신다. 그럼에도 불구하고 나는 아직도 조금은 회의적인 시각이 있다. Discord가 go로 만들었으면서도 이후에 rust로 갈아엎는 이유는 rust가 go보다 단지 더 뛰어나서가 아니라 사업적 측면에서의 선택을 고려하지 않을 수 없다라는 생각이 들었다. 당연히 스타트업 입장에서는 빠른 개발과 빠른 출시가 우선이다. 당연히 그런 면에서 go를 선택했을 것이고 회사가 안정궤도에 올랐으니 돈과 시간이 생겼을 것이기에 rust 로 갈아엎는 일을 벌이고 있는 것이 아닐까라는 생각이 들었다. 결국에는 언어의 우위가 아니라 프로젝트를 진행하면서 오고갔던 제안들과 수많은 고민 속에서의 선택에 해당된다는 생각이 들었다.
일부 사람들 중에 web3.0을 언급하면서 solana를 보라면서 rust가 위대해질 수 밖에 없는 이유를 이야기하신다. web3.0이 혁신이지 rust가 혁신의 주가 되는 것은 아니다. 작품이 위대할 순 있지만 도구가 위대하기 때문에 작품이 위대할 순 없다고 생각한다. 왜냐면 위대한 작품을 만들기 위해서는 하나의 도구만 사용할 수 없기 때문이다. 하지만 속도와 안전성 대문에 rust를 채택하겠다면 그것만이 맞는 말이 된다고 생각한다. 그렇기 때문에 개발 속도와 비용, 러닝커브 즉 모든 것을 고려하여 선정할때는 단지 고려대상에 언급될 뿐이라는 생각이 든다. 즉 러스트는 반드시 필수적이지는 않다.
rust는 특히 wasm 과 관련하여 언급하고 있는 내용들이 많았는데 이 부분은 나도 많이 궁금하다. rust를 배워본 김에 이왕 wasm까지 배워보고 싶은 생각도 있다. 그 이유는 wasm으로 만들어낼 무언가가 너무도 재밌을 것 같기 때문이다. 지난번에 맞팔을 한 어느 팔로워분께서 흥미로운 포스팅을 하셨는데 자신의 게임 엔진을 wasm으로 포팅하여 웹에서 돌아가게 만든 후기를 올리셨다. 하지만 그분 말씀대로 지금 wasm 개발환경이 너무나 성숙하지 못했고 불편한게 이만저만이 아니라고 하셨다. 하지만 그럼에도 불구하고 앞으로 wasm을 통해서 웹에서 돌릴 수 있는 무언가 재미난게 쏟아져나올 거라는 생각이 들면서 너무 궁금했다. 이런 흥미로운 기술이 나왔는데 고작 개발환경이 불편하다고 해서 가만히 있을 사람들이 아니란 생각이 들었다. 어떻게 해서든 관련 툴이든 부트처럼 감싸주는 새로운 기술이든 뭐가되었든 뭔가가 더 나올거라는 생각이 들었다.
그래서 언젠가 앞으로 이번처럼 시간이 생긴다면 wasm도 써보면 재밌겠다는 생각이 들었다.
끝으로 불과 며칠되지 않았지만 정말 재밌게 배웠다. 아직 반복자와 클로저, cargo의 깊은 내용, 스마트 포인터, 동시성, 객체지향적으로 쓸 수 있는 방법과 패턴과 관련된 내용들이 한참 더 남았다. 이 부분들을 배우면서 좀 더 깊은 내용을 알 수 있지 않을까 싶다.
사실 최근에 개발에 대한 흥미가 조금 떨어졌던 점도 있었다. 작은 프로젝트를 맡게 되어서 처음에는 재밌게 시작했지만 갈수록 코드가 쌓이고 버그들도 생기면서 혼자서는 모든걸 다루기 버거워졌다. 그런데 그런 상황속에서 누구도 도와주지 않는 상황이 생기면서 이것이 업무이거나 혹은 해야만 하는 과제로써 느껴지기 시작한 것이었다. 그런 기분이 들게 되는 순간 정말 말그대로 거부감이 생겨버렸다. 그러면서 내가 만들고 싶은 걸 만들고 싶다는 생각이 절실하게 들기도 했다. 물론 조금은 이기적인 생각일 수 있다. 사람은 하고싶은 것만 하고 살 순 없으니까 말이다. 정해진 과제나 업무가 있으면 어찌되었든 100퍼센트 완성시키는 것은 도리의 측면이 아니라 나 스스로에 대한 약속이기 때문이다. 하지만 원래 이러한 강제성이 존재하지 않았던 프로젝트였음에도 불구하고 나 스스로가 완벽하게 끝내야 한다는 강박에 얽매여 나를 옥죄고 있다는 생각이 들었다. 그래서 오랜만에 잠깐 숨돌릴겸 내가 알아보고 싶었던 기술에 대해서 알아볼까 하고 생각하고 선택한 것이 러스트였다. 2일정도 도큐먼트 보면서 조금 본것 가지고 Rust의 R자도 꺼내는게 사실 참 부끄러운 수준이지만 그래도 진짜 너무 재밌게 봤다. 개념도 너무 재밌었다. 말그대로 신기방기.
아래는 doc을 보면서 IO프로젝트를 만든 코드인데 앞으로는 vscode대신 intellij에서 rust를 써볼까 한다. vscode에서 자꾸 원하지도 않는 코드를 추천해주면서 커서가 들쑥날쑥한게 너무 불편하다. 설정에서 바꿀 수 있긴 할텐데 이왕 인텔리에서 스프링부트로 프로젝트 하는 마당에 옆에 프로젝트 하나 추가해서 러스트로 이것저것 뚝딱거려볼 생각이다.
아무튼 조금 더 공부해보자 재밌다! 아참참 그리고 테스트도 표준으로 지원해주는데 간편하다. 딱 군더더기 없이 필요한 기능만 있다.
언제나 생각하는건데 그냥 재밌게 하는게 중요한것 같다. 공부라고 생각하면 너무 지겨워진다.
'Rust' 카테고리의 다른 글
[Rust] Rust가 ++연산자를 지원하지 않는 이유 (0) | 2024.05.03 |
---|---|
[Rust] 러스트 Double Linked List 코드 (0) | 2024.04.12 |
[WASM] 웹 어셈블리의 미래 - WebAssembly (0) | 2022.01.26 |
[Rust] 러스트를 배워봅시다. (0) | 2022.01.12 |