종 울리는 시간표 개발 포스트모템

RanolP·2020년 8월 31일
4

개요

8/28 ~ 8/30 동안 Rust를 사용해 시간에 맞춰 종이 울리는 시간표 데스크톱 앱 timer-table을 만든 후기.

동기

1학기 때는 시정표와 관련 없이 하루 안에 과제를 완료하면 돼서 이런 게 필요 없었지만 시정표에 맞춰서 스케쥴을 편성하길 학교에서 강제했기 때문에 만들게 되었다.

1학기 때는 이런 이미지를 만들어서 사용했었다.

목표

가장 중요한 목표는 종을 제 시간에 울려주는 기능이다. 그 다음으로는 데스크톱 앱일 것을 목표로 잡았고 (웹 앱이면 탭을 많이 열어두는 나로서는 중요도가 떨어지게 된다), 같은 과목을 같은 색으로 칠하는 기능이나, 다음 교시 알려주기, 남은 쉬는 시간 길이 알려주기 등의 소목표도 잡았다.

기술 스택 방황

데스크톱 앱을 만들기 위해 reverytauri, electron 등의 솔루션도 고려했지만 revery는 빌드에 실패해서, tauri는 MSHTML로 동작할까봐(...), electron은 너무 무거워 보인다는 이유로 반려하고 Rust 기반 프레임워크를 찾아다녔다. orbtk, moxie, fltk, druid, relm 등 다양한 프레임워크를 찾아봤고 iced가 가장 괜찮은 듯 해서 이 프레임워크를 바탕으로 작업에 착수했다.

개발하며 당황한 점

한글 렌더링

iced는 기본적으로 한글을 렌더링해주지 않는다. font fallback 기능이 미흡하기 때문인데 (Text shaping and font fallback #33), 나는 어차피 한글과 영문자, 숫자 정도만 잘 그려지면 되기 때문에 IBM Plex Sans KRinclude_bytes! 매크로를 통해 바이너리에 때려박았다. 그런데 맨 처음에 *.otf를 넣어보고 렌더링이 안되길래 당황했는데, Does not support chinese? #213을 보니 당장은 *.ttf만 지원한다길래 그쪽으로 우회했다.

GeForce Experience

iced에 따로 설정을 하지 않으면 기본적으로 wgpu가 기반인 렌더러를 사용하기 때문에 Vulkan으로 그리게 되는데, Vulkan API의 사용을 감지해서 GeForce Experience에 대한 알림이 나오게 된다.

표 그리기

iced는 Table 컴포넌트를 제공하지 않는다. 대신에 레이아웃을 위한 Row, Column 컴포넌트를 제공하고, Style에 border를 추가하는 게 가능하다. 근데 이 Style을 추가하는 방법도 되게 요상한데, 내가 코드를 뜯어가며 개발해서 그런 걸지도 모르겠다.

구조체를 하나 만들고 StyleSheet를 구현하게 만들어서 구현 대상 함수에 Style을 반환해야 한다. 아니 어차피 Style도 구조체면서 Style 받아주면 안 되는 건가...

하여튼, 이를 통해 그린 표이다. 자세히 살펴보면 안쪽 테두리는 겹치기 때문에 살짝 두껍다. 사용에 별 문제는 없기 때문에 무시하기로 했다.

색 칠하기

시간표에 색을 칠해야 하는데 난 이걸 사용자 테마로 만들고 싶었다. 그래서 그냥 iced::Color를 json으로 불러오려고 했는데 이게 serde::Deserialize를 구현하지 않았다. 그래서 iced에서 palette 기능을 켜고 palette에서도 serializing 기능을 켜주는 것으로 json으로부터 색을 불러올 수 있었다.

소리 재생하기

가장 중요한 목표였지만 옆길로 많이 샜다... 소리를 재생하기 위해 이것저것 기웃거리다가 가장 유명하고 믿음직스러운 rodio를 통해 재생하기로 했다. 물론 여기서도 당연히 문제가 생겼는데, 소리를 내고 바로 죽는 것이었다!

그런다고 멈추면 안 된다. 이슈 트래커를 살펴보니 Panics when finish playing MP3 on Windows in debug mode #229라는 이슈가 있다. 살펴보니 Fix mp3 decoder bug: only reset offset after new frame #297라는 PR이 머지됐지만 아직 릴리스가 나오지 않는 모양이다. Cargo는 git 저장소를 바로 의존성으로 잡을 수 있기 때문에 커밋 하나를 잡아서 rev을 고정하고 진행했다.

그런데 하필 api breaking change가 있어서 (...) 코드를 좀 손봐야 했다.

제 시간에 재생하기

이 프로그램이 인식해야 하는 시간의 종류는 총 다섯 가지가 있다. 하지만 실질적으론 아직 판단하지 않은 초기 상태까지 포함해서 여섯 가지를 사용했다.

  • 초기 상태
  • 휴일
  • 전체 수업 시작 전
  • 수업 중
  • 쉬는 시간 및 점심 시간
  • 전체 수업 종료

이 중 전체 수업 시작 전, 수업 중, 쉬는 시간 및 점심 시간은 종소리를 재생하는 데에 필요한 수업 정보를 담아야 했다.

구조를 짠 이후에 생각해보니, 여태까지의 개발이 일요일에 진행되어서 종을 칠 수 없었다! 그래서 now()를 감싸는 함수 하나를 만들고 거기서 18 시간을 더하고 반환하게 했다.

그리고 나서 열심히 코드를 짜고 테스트를 해보니...

오전 10시인데 마지막 교시를 하고 있었다. 이유를 찾아보니 이분 탐색을 할 때 Less와 Greater를 뒤집어서 반환하고 있었다. 🤣🤣🤣

이제 시간 종류는 제대로 판단한다. 이후에 제 시간에 종을 치게 만들고 수업 진행도 및 남은 쉬는 시간을 보여주는 UI도 넣었다.

지금 듣는 수업 강조

짜고 보니 오늘 듣는 수업이 뭔지, 지금 듣는 수업이 뭔지 아는 게 귀찮다고 생각했다. 원래 상정한 기능은 다 구현했지만 어차피 시간도 남겠다 하고 추가적으로 구현했다.

오늘 수업이 아니면 배경/글자 투명도를 80%로, 지금 듣는 수업은 테두리 굵기를 올렸다.

만들면서 느낀 점

  • 웹하는 게 디자인하기 쉽다...
  • 하지만 Rust로 짠 GUI 최고다, electron 따위와 달리 램 6MB 먹는다.
  • 지뢰 밟기 쉽다, 당신이 이상한 환경을 쓰면 쓸수록 더. (나는 보통 WSL2 + Arch인데 이거 개발하면서 순수 Windows로 잠깐 갈아탔다. 그러니 이슈 해결이 쉬워졌다)
  • 힙스택이 밥 먹여주지는 않지만 기분이 좋다.
profile
사람과 컴퓨터 사이를 이어주는 소프트웨어를 만듭니다

0개의 댓글