티스토리 뷰

⚠️ 주의: 현재(2021년)의 제 의견은 이 당시와 다릅니다.
2021년 12월의 의견 보기


암호화폐 정보를 읽어와서 마스토돈에 뿌려주는 토이 프로젝트를 만들었습니다.

rust로요. 공부만 하다 중간에 멈췄던 그 언어로요...

이 글은 재미있는 아니 재미없는 삽질의 기록입니다. 의식의 흐름으로 주욱 작성되었습니다. 빌드하는 거 기다리면서 썼어요.

하루만에 짰습니다.

1. 왜

  • 트위터에서 코인봇 보니 부러워서
  • rust도 연습해보고 싶었음
  • 마스토돈 라이브러리는 선정이 과거에 끝났고 연습도 해봤음 (아직 이 라이브러리도 불안정)
  • 더 이유가 있었던 거 같은데 까먹음
  • 중간에는 오기로 계속함

2. 첫 선택

  • 처음에는 코인원 API (oauth2) → 마스토돈 (mammut) 으로 하려고 했습니다.
  • 마스토돈 인증 정보를 저장하는 건 조금 헤맸지만 성공했습니다.
  • 코인원 쪽은 oauth2의 장벽이 가로막더군요.

3. 인증정보 저장용 추상화 레이어 → 삭제

  • mammut을 본 적이 있어서 툿 하는 거까지는 무리가 없었는데
  • (아 맞다 여기에 openssl-prebuilt 안 설치해서 빌드가 안 되지 깔아야지 - mammut의 요구사항입니다)
  • 노드자살에서 트위터 다뤄봤던 경험에 의거, 자세히 보기전에 추상화 레이어를 만들었는데
  • 어라 mammut 앱 생성하는 데에 컨슈머 키와 컨슈머 시크릿을 안 받네?
  • 알고보니 oauth2 에서는 앱이 스스로를 서버에 등록할 수 있었던 것
  • (눈물을 머금고 추상화 레이어 삭제)
  • 접을까... 하다가 다시 시도

4. 마스토돈 인증정보 저장

  • api 봐가면서 짜는거라 별 무리는 없었습니다. 대신 oauth2 개요를 조금 공부하긴 했지...
  • toml 라이브러리로 직렬화 및 저장했는데 아마도 serde를 쓰지 않았을까 싶기도...
  • 아마 #[derive(Serialize, Deserialize)] 가 serde_derive 의 매크로 같은 거니까 썼을거에요
  • rust가 expression 기반 언어라 다른 제가 잘 아는 언어에서는 잘 못 하는 미친 짓을 좀 했습니다.
  • 그것은 match 조건에 블록 박고 안에서 람다 호출하기... 물음표 연산자 커버한다고 저 짓을 했죠. 물음표 연산자는 Result<데이터, Error>를 호출하는 함수에서만 쓸 수 있으니까요.
  • 아 근데 물음표 연산자랑 Result 조합 쓰면 디버깅이 힘들어지더라... 이게 터질 곳이 아니라 엉뚱한 데서 처리하니까요. (이상적이라면 그거 다 핸들링해줘야 하겠지만)

5. 코인원 oauth2 시도

  • 코인원 oauth2 가이드 따라하다보면 콘솔에서는 안 됩니다.
  • 그렇다고 제가 oauth를 잘 아는 것도 아니고....
  • 처음에는 yup_oauth2를 쓰려고 했는데 복잡도가 높더라구요. 다른 건 맘에 안 들고 해서 직접 http 요청을 해서 만드려고 했는데
  • 이것저것 다 하긴 싫으니까 batteries included라고 하는, mammut에서도 쓰는 (사실 이게 계기임) reqwest 를 쓰기로 했습니다.
  • oauth2 전체를 공부하기는 싫으니까 코인원 API 문서대로 하기로 했습니다.
  • 어? 시키는 대로 했는데 왜 JSON이 아니라 HTML 홈페이지를 던져줘???????????
  • 포기
  • 이전에 다른 분께서 업비트랑 코빗에서도 API를 제공하고, 심지어 업비트는 로그인도 필요없다고 하셔서 과감히 파일을 지우고(지우고 다음 과정에서 후회함) 업비트에서 가져오기로 결정했습니다.

아무래도 가이드는 같은 클라이언트에서 접근하는 걸 가정하는 모양이더군요. 어떻게 해도 안 되길래 포기했습니다.

6. 업비트 비공식 API

  • 이것도 코드가 좀 비효율적이긴 한데 대충 짜면 되더군요.
  • reqwest도 앞선 과정에서 간단히 배웠겠다 요청은 이걸로.
  • 업비트는 비공식 API이기도 하고 인증 정보를 저장할 필요는 없겠지... (할 일이 줄었습니다)
  • 무리 없이 짜긴 했는데 디버깅이 힘들긴 하더라구요. 빌드 한 번 하면 최소 1초는 기다려야 하니...

7. 포스팅

  • 메인에 짜다가 post.rs 로 분리했는데 사실 오늘 하루안에 끝내려던게 하루가 다 지나가더라구요. 그래서 알 게 뭐야 그러고 토이프로젝트인 셈으로 치고 막 짜내려갔습니다.
  • 그래서 post.rs가 더러워요... 아마도요.
  • rust에는 자리를 끊어서 숫자를 예쁘게 쓰는 게 없는 거 같길래 스택오버플로우 검색한 소스를 그대로 복붙해서 사용.
  • mammut 아직도 버그가 있더라구요. 근데 mammut 코드는 API를 매크로 (무서워) 로 짜놔서 디버깅하기 힘들어보이는데다 intellij Rust는 다 좋은데 CLion이 없다면 디버깅이 안 되는 실정이라... vscode에서도 llvm 디버깅도 아직 안 해봤기도 하고요.

8. 테스트

9. 라즈베리 파이에서 봇 돌려야죠

  • 크로스컴파일 같은 설정하고 자빠져있고 싶진 않아서 라파에서 직접 빌드하고 싶었습니다.
  • 라즈비안 apt-get에는 없었지만 다행히도 rustup으로는 되더군요. 아니었으면 진짜 포기했을 뻔. (rust 홈페이지에서 다른 플랫폼용 부분을 살펴보시면 복붙할 수 있는 스크립트가 나와요)
  • 빌드를... 하고... 있습니다...
  • 다 되면 systemd 주기적 반복실행으로 넣어놓을거에요.

10. 기억나는 고통

  • 라이프타임. struct의 라이프타임이랑 그걸 impl하는 함수의 라이프타임을 어찌해야할까 고민하다가 빼기도 하고 넣기도 하고 결국은 mammut 코드를 들여다본 뒤 따라하기로 결정합니다.
  • 모르는 채로 쓴 Cow<'static, str> 가 그것입니다. 저게 뭐의 약어인지는 찾아봤는데 (쓸 때 복사 - Copy on Write) 저 (공포의) 스마트 포인터를 어떻게 쓰는지는 몰랐거든요. 넣으니까 되더라구요. 그냥 썼어요. 헤구구 언젠가는 공부해야
  • extern crate하고 use가 있는 곳에서 이상하게도 use self::모듈::모듈; 같이 self가 왜 나오는지 궁금했었죠. 이유는 extern crate 모듈 이 모듈 안의 모든 이름을 현재 이름공간에 들여오는 거라서... [트윗] [스택오버플로우]

 

  • 아직도 모르겠는 거는 enum 을 match 하는 코드에서 변종 => 으로 쓰면 unreachable 매치가 생기고 &Enum이름::변종 => 으로 쓰면 잘 된다는 거에요. &하고 관계있을 거 같은데  대체 왜 전자가 되는지 모르겠어요. 저런 이름이 있던가?

11. 소감

  • 싸우자 컴파일러
  • 한 때 머리가 타오를 것 같았습니다.
  • 차라리 초보적인 C++로 에러를 발생시키는 코드를 짜는 게 더 빠를 거 같아
  • 그거보단 노드자살이 덜자살이다...
  • 스크립트 언어 하나는 확실히 익혀야겠네요. 생산성의 상태가... 이거 nodejs로 했으면 훨씬 짧았을텐데.
  • 로우레벨에 가까워질수록 고민할 부분이 많이많이많이 늘어나는 것 같습니다. 제가 아니라 라이브러리 제작자들이요. 소스 뜯어서 구경해보면서 저 복잡도를 왜 나한테 떤지는거야 싸우자 뎀벼 으아아아 뭐 그렇습니다. 멀티스레딩을 지원할거냐 커넥션 풀을 지원할거냐 네트워크 라이브러리는 뭘 쓸거냐 그 선택을 유저한테 위임할거냐 등등등등 너무 생각할 게 많은 것 같아요.
  • 그거 다 고민하다가 언제 짜냐 일단 대충 짜고 보자 나중에 후회할 것이다
  • 그에 반해 go는 표준 라이브러리로 다 한다면서요. 부럽다
  • 아직 rust가 네트워크 프로그램을 짜기에는 생산적이지 못 한 것 같기도 해요
  • 아무튼 각설하자면 rust 잘하려면 헬지옥에서 헬공부하고 헬수련해야할듯

 

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/03   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함