jangjunha blog

HeekTime 프로젝트 히스토리

발행

시간과 노력을 많이 들였던 프로젝트여서 때마다 어떤 변화를 주었는지 한번쯤 기록으로 남겨놓고 싶었다. 진작 어디라도 적어뒀어야 하는데 많이 늦었다. 만날 써야지, 써야지 생각만 하다가 모든 게 재밌어지는 시험기간을 맞아 적는다.

🔗 계기

HeekTime 프로젝트를 시작하게 된 결정적 계기는 두 가지였다. 대학교 입학 후 전공 필수 과목으로 C언어 수업을 들었다. C언어 기초 수업은 이미 많이 들었다. 때마침 교수님이 “개인 프로젝트를 해서 발표하면 출석과 과제, 시험을 전부 대체해주겠다”고 선언하셨다. 그렇게 나를 포함한 몇몇 친구들이 대체과제를 했다. 그 때 나는 동아리 iOS 스터디에서 선배들로부터 Swift 기초 문법과 UIKit으로 뷰를 만드는 법을 배우고 있었다. 슬슬 배운 것을 응용해서 무언가 만들거리가 필요했다. 이 두 가지 계기가 겹쳐서 프로젝트를 시작하게 됐다.

그래서 다른 플랫폼이 아닌 iOS 앱을 만들었다. 따라서 이 프로젝트에서 가장 집중할 부분은 iOS 앱 개발에 익숙해지는 것이었고 그 밖의 일들은 최대한 간단하게 하길 바랐다. 그래서 백엔드는 가장 빨리 만들 수 있으면서 유지비가 적게 나오도록 Python Flask 베이스의 서버를 작성해서 Google App Engine에 올리고, 데이터베이스는 Cloud Datastore를 사용하는 것으로 결정했다.

여러 아이디어 중에 시간표 짜는 앱을 만든 이유는 단순히 내가 시간표 짜는 게 어려워서였다. 대학교에 입학하고 첫 수강신청을 앞두고 나니 도대체 강의를 어떻게 골라야 할 지 모르겠더라. 대체로 한 강의당 3학점씩 총 6개 강의로 18학점을 듣는다. 다행인지 우리 학과 1학년은 학과 커리큘럼에 정해진 12학점치 과목이 자동으로 수강신청되기 때문에 나머지 6학점만 3학점짜리 2개 과목으로 채우면 됐다. 그런데 수많은 과목 중에 이 2개 과목을 고르는 게 문제였다. 5천 개가 넘는 강의 중에서 다른 강의 시간과 안 겹치고, 적당히 재밌어 보이면서, 우주공강을 만들거나 피같은 금공강을 날리지 않는 강의를 찾아야 했다. 그리고 수강신청은 티켓팅 전쟁이므로 실패했을 때의 대안도 마련해야한다.

요즘은 에브리타임의 검색 기능이 강력해졌는데, 당시에는 필터링 옵션이 다양하지 않아서 시간표를 짤 때 쓰기엔 아쉬움이 있었다. 그래서 그 땐 다른 분이 개발해주신 KUTime이라는 윈도우 애플리케이션으로 시간표를 짰었다. KUTime으로 조건을 만족하는 강의들을 리스팅하고, 재밌어 보이는 강의명이 있으면 KLUE에서 강의평가를 찾아보는 식으로 골랐었다. 결과적으로 첫 학기 수강신청은 꽤 만족스러웠다. 내가 맥을 써서 시간표를 윈도우에서 짜야 한다는 점은 좀 불편했었지만 매일 쓰는 것도 아니니 큰 불편함은 아니었다. 그래서 그냥 맥버전이나 모바일 앱이 있으면 좋겠다고 생각만 하고 있다가 교수님이 과제하면 수업+시험 대체해주신다길래 덥썩 물어서 시작했다.

🔗 Changelog

🔗 iOS 첫 버전 (2016-07 릴리즈)

시간표 생성 화면
시간표 탭, 검색 탭
(검색한) 강의 상세보기 화면
시간표 구성 화면 예시
시간표 복제, 삭제
강의 필터링
강의 정보 수정

핵심 기능은 강력한 필터링 기능(겹치는 시간대 강의 제외, 요일/시간/학점/강의분류 필터링, 검색)과 시간표 복제 기능이다. 전자는 수많은 강의 중 어차피 안들을 강의를 걸러내기 위해서, 후자는 수강신청 실패에 대비해서 필수과목을 고정으로 둔 상태로 여러 안을 만들기 위해서 필요하다.

사실 이거 만들 때 아이폰 나오면 사겠다는 생각만 있었고 아이폰은 써본 적도 없었다. 그래서 시뮬레이터에만 의존해서 만들긴 했었는데 그 땐 그냥 안드로이드로 만들 걸 후회했었다..😂 안드로이드 유저인 내가 생각하는 UI/UX와 iOS에서 자연스러운 것이 다르다는 것이 가장 어려웠던 기억이 난다. “햄버거메뉴 두고 Drawer 만들어서 프로필이랑 시간표 목록 넣어놓고 메인화면에 시간표 띄우면 되지 않나?” 생각했는데 나중에 보니 iOS에선 이럴 때 기본은 네비게이션이더라. 당시엔 다른 iOS 앱은 써본 적도 없으니 이해하지 못했었던 기억이 난다.

서버는 Python + Flask로 개발한 서버를 GAE + Cloud Datastore 위에서 돌렸다.

🔗 iOS v2 (UI 위주 개편, 공동개발, 2017-02 릴리즈)

iOS 개발은 커녕 아이폰 앱조차 안 써본 상태에서 처음 한 프로젝트라 UI부터 코드까지 정말 “돌아가게만” 만들어뒀었다. 코드를 계속 만지다보니 좀 더 잘 만들고 싶다는 생각이 들었고, 그래서 두 번째 버전은 iOS 개발 경험이 있는 고등학교 선배 한 분과 같이 만들었다. 프로젝트 구조나 기본적인 UI 틀은 선배가 만들고 뒤이어 함께 작업했었다. 이후에 또 갈아엎긴 했지만 이 때 했던 선택들은 여전히 많이 남아있다. 코드는 남아있는데, 스크린샷이 있는지 모르겠다... 그렇다고 실행시켜서 찍긴 귀찮다..

TreeSelectorView 사용 예시

이 때쯤 커스텀 컴포넌트 만드는 것도 익숙해져서 카테고리(대분류 / 중분류 / 세분류) 필터에 요런 요소도 만들어서 적용했다. 당시에 만들어놓고 뿌듯해서 SNS에 올려뒀던 덕분에 찾아서 가져왔다.

🔗 Web v1 (Vue, 2017-10 시작)

사실 시간표 짜는 건 컴퓨터로 하는 게 편하다. 개인적으로 언젠가 Vue를 써보고 싶기도 했고, 회사에서 약간의 웹 프론트엔드 일을 하게 되면서 시작했던 것 같다.

기능은 기본적으론 iOS 버전의 서브셋이다. 검색만 가능하고, 요일이나 시간 필터 같은 기능은 구현하지 않았다. 다만 오른쪽에서 검색한 강의에 마우스를 hover 하면 왼쪽의 시간표 위에 해당 강의가 오버레이되어 보이도록 하는 기능이 웹에 먼저 들어갔다. (이후 iOS에서도 강의를 누르고 있는 동안 시간표에 오버레이되어 보이는 기능을 추가했다.)

heektime-web-v1 GitHub

🔗 iOS v3 (UI 개편, 여러 패턴 적용, 2018-09 릴리즈) (live)

시간표 화면 : 강의를 쉽게 검색하고 확인할 수 있어요.
강의 검색 화면 : 안겹치는 강의만 간편하게 검색. 불필요한 결과는 그만, 내게 필요한 강의만 찾아보세요.
필터 화면 : 원하는 강의만 골라주는 강력한 필터. 1교시 없는 시간표! 금공강! 찾고싶은 강의만 찾아보세요.
시간표 관리 메뉴 : 시간표를 복제해서 여러 안을 만드세요.
강의 상세 화면 : 자세한 강의 정보도 꼼꼼히 확인

현업에서 iOS 개발을 하게 됐다. 그러면서 정말 많이 배웠다. 동시에 iOS 사용 경험도 많이 쌓이기도 해서 이 때쯤부터 슬슬 만들고 싶다고 마음먹었음에도 어떻게 할 줄 몰라서 포기하는 일은 줄어들었다. 눈이 높아지다보니 기준도 높아지고 또 시도해보고 싶은 것들도 많아졌다. 사이드프로젝트니까 부담없이 고쳐나가는 것보단 다시 만드는 것을 선택했다. 회사에서 사용하는 기술 결정의 영향을 많이 받았다. 익숙해서 그렇기도 하고, 반대로 개인 프로젝트에 적용하면서 더 익숙해지기도 했다. 부담 없이 새로운 시도를 해보고 괜찮으면 현업으로 가져가기도 했다. 좋은 건진 잘 모르겠다.

웹 버전을 함께 만들면서, 이 때부터 시간표를 온라인에 저장하기 시작했다.

전체적인 구조를 잡는 데 https://github.com/devxoul/Drrrible 을 참고하고 ReactorKit, Pure DI 등 전수열님이 공개하신 도구들을 많이 사용했다. 이외에도 RxSwift, RxMVVM을 적극 사용했다. 이 때 만든 코드베이스는 계속 유지되고 있다. 지금 보니 v2 커밋 수가 99개, v3 커밋 수가 120개쯤 된다. 이번에 Firebase로 옮기는 작업도 무리없이 마쳤다.

🔗 iOS v3.3.0 — Widget (2020-09 릴리즈)

현재 시간표 위젯 추가 화면
다음 시간표 위젯 추가 화면

복학을 하면서 개밥먹기를 다시 시작했다. 복학 후 수업은 코로나19로 인해 비대면 수업으로 이루어졌다. 집에 있다보니 시간관리가 더 중요해졌다. 공강 때 쉬다보면 다음 수업이 언제였는지 종종 헷갈렸다. 그래서 몇분 후에 수업이 시작하고, 시작한 수업이 끝날 때까지 몇 분 남았는지 보여주는 위젯을 만들었다. iOS 위젯 한번 만들어보고 싶어서 만든 것도 있다.

🔗 iOS v3.5.0 — Watch App (2021-09 릴리즈)

Watch 앱 시간표 보기 화면
Watch 컴플리케이션 예시 - 모듈
Watch 컴플리케이션 예시 - 만화경
Watch 컴플리케이션 예시 - 그라디언트
Watch 컴플리케이션 예시 - 인포그래프
Watch 컴플리케이션 예시 - 프라이드-우븐

애플워치를 쓰기 시작하면서 만들었다. 생각보다 만들기 어려웠고 시간도 많이 썼다. Watch App은 더이상 만들지 말아야겠다고 다짐했다. 그보다 워치 컴플리케이션을 열심히 만들었는데 생각보다 사용자가 원하는 곳에 갖다 쓰기 어려워보였다. 본인이 쓰고 있는 페이스가 지원하는 유형의 컴플리케이션을 써야 하는데, 비슷한 유형처럼 보여도 다른 유형인 것들이 있다. 난 하도 봐서 구분하겠는데 일반 사용자가 구분하기는 어려울 것 같다. 그래서 결국 샘플 페이스를 만들어서 제공하기로 했다. 위에 있는 페이스 갤러리 링크가 그것이다.

🔗 인프라: AWS (EC2 + ELB + RDS)

지금 생각하면 약간 웃길 수도 있는데, 포트폴리오에 AWS 써본 적 있다고 어필하고 싶어서 옮겼던 걸로 기억한다. PaaS에서 옮기는거라 귀찮은 작업이긴 했지만 써본 적 있는 환경이라 옮기는 게 크게 어렵진 않았다. 아마 이 때 $50/월에 가까운 비용이 나갔던 것 같다. 이 때는 포트폴리오가 중요했고, 일을 하던 때라 감당할 수 있었어서 옮긴 선택을 후회하지는 않는다.

🔗 인프라: AWS ECS, IaC 시작 (2019-02?)

현업에서 ECS를 사용하고 도커 컨테이너에 익숙해지면서, 그리고 반대로 익숙해지기 위해서 옮겼다. 슬슬 웹 콘솔에서 인프라 수정하는 게 귀찮아지기 시작하기도 했고, 여기저기서 들어본 IaC를 적용해보고 싶어서 적용했다. 자료가 많기도 하고 내가 AWS만 쓰는 것도 아니라서 Terraform을 선택했다. 리디에서 공개한 https://github.com/ridi/pay-infra 를 많이 참고했다. Local backend로 시작해서 S3 backend를 거쳐 지금은 Terraform Cloud를 사용 중이다. 이 때 HeekTime에 적용해보면서 IaC와 Terraform에 많이 익숙해졌다.

🔗 Web v2 (React, 2019-08) (live)

HeekTime 2번째 버전 스크린샷

현업에서 React를 쓰게 되면서 React로 옮겼다. 옮길 당시 기능은 거의 그대로였고, 이후 몇몇 필터링 기능 등을 추가했다.

heektime-web-v2 GitHub

🔗 인프라: GCP EKS (live, 2020-01)

Kubernetes 써보고 싶어서 옮기기 시작했던 걸로 기억한다. 운좋게(?) 회사일과 맞물려서 또 HeekTime에 적용하면서 배운 점들을 현업에서 잘 썼던 것 같다. 나중엔 반대로 회사일과 동료분들로부터 배운 것들을 여기에 반영하기도 했다.

AWS EKS가 아니라 GCP GKE를 선택한 가장 큰 이유는 클러스터 관리 비용(클러스터당 지불하는 비용)을 지불하지 않아도 됐기 때문이다. 그 외에도 GCP 웹 콘솔에서 기본적으로 제공하는 관리 UI의 편의성이 좋아기도 하다. 하지만 역시 가장 큰 이유는 비용이었다. 이 환경에서는 네트워크 로드밸런서 요금, 작업자 노드 인스턴스 요금(Preemptible 인스턴스를 사용해서 좀 더 줄이긴 했다.)이 비용 중 가장 큰 비중을 차지했다. Kubernetes 클러스터를 유지하는 것 자체에는 직접적인 비용이 들지 않았는데, Ingress를 붙이려면 로드밸런서를 사용하지 않고는 어려워서 로드밸런서 비용이 예상외로 들었다.

여기서 더 많은 것들을 시도해보고 싶었는데 생각보다 잘 되지 않았다. 환경 분리나 개발 버전 배포, Spinnaker을 사용해서 Continuous Delivery를 적용하는 것 등을 해보고 싶었는데 생각보다 비용이 더 들 것 같아서 포기했다.

🔗 서버: 강의 서비스 분리 (2020-07)

Protobuf와 gPRC를 써보고 싶어서 강의 서비스를 별도 서비스로 분리했다. 아예 HTTP API도 gRPC로 바꿔볼까 했었는데 TypeScript 스키마 생성이 복잡해서 그만뒀다.

heektime-schema GitHub

heektime-schema-python GitHub

🔗 인프라: Firebase (2022-07)

Firebase 기반으로 옮겼다. 이 결정을 하기까지 고민을 많이 했다. 그대로 두자니 비용이 너무 많이 나가고, 옮기자니 시도해보고 싶었던 CD나 쿠버네티스 클러스터 운영을 할 수 없었다. 고민하다가 결국은 옮겼다. 사용자 입장에서는 변화가 거의 없는데 유지비를 월 500원 수준으로 줄였다.

옮기는 과정에서는 순조로운 부분도 있었고 예상치 못한 문제들도 있었다. 있었던 일들을 블로그에 〈잠자는 서비스 만들기〉라는 글을 시작으로 짬짬히 올릴 예정이다.

heektime-web-v3 GitHub


2022-11-16에 마지막 수정