오랫동안 지속되었던 코로나 팬데믹이 어느정도 마무리 되어가는 분위기가 형성되자, IT 관련 분야에서도 오프라인 행사가 조금씩 진행되기 시작했습니다. 저는 그 중에서 해커톤 행사에 많은 관심을 가졌고 GDG Campus Korea 에서 주관하는 오프라인 해커톤 행사에 참여하게 되었습니다.
이전 해커톤 참여 경험
저는 개발 공부를 시작할 때 이미 코로나가 유행 중이었기 때문에 각종 오프라인 행사에 참여한 경험이 거의 없었습니다. 대외 IT 창업 동아리인 SOPT, Mash-Up 에서 한 기수 씩 활동을 해보았으나 대부분의 프로그램이 비대면으로 진행되었습니다. 그러다보니 오프라인 해커톤 또한 두 번밖에 경험하지 못했습니다.
해커톤이라는 행사가 정형화된 룰이 있는 건 아니지만, 이전에 경험해보았던 해커톤은 동아리 내에서 진행되어 "함께 공부했던 것들을 기반으로 결과물을 만들어보는", "네트워킹 및 친목 위주" 느낌이 강했습니다. 따라서 팀 빌딩 이후 개발 기간이 1개월 이상 주어졌고, 팀 별로 자유롭게 사전 개발을 해둔 다음 해커톤 당일에 한 공간에서 모두 만나 프로젝트를 마무리하는 프로세스로 진행되었었죠.
많은 기수들의 피드백으로 유지되고 있는 동아리 내의 시그니처 행사인만큼 이런 프로세스에 만족하는 사람들도 굉장히 많았습니다. 하지만 저는 다음과 같이 아쉬운 점이 조금 있었습니다.
1. 다소 긴 개발 기간
지난 일이라 기억이 잘 나지 않지만 팀빌딩 이후부터 약 3개월 정도 프로그램이 진행되었던 것 같습니다. 실제로 오프라인으로 만나 무박 2일간 개발을 하는 해커톤은 1차와 2차가 나뉘어져있었구요. 시간적으로 여유가 많다고 느껴지니 기획 단계에서 프로덕트의 볼륨이 자연스레 커졌습니다. 또한 개인으로나 회사에서는 도전해보지 못했던 새로운 기술을 과감하게 도입하게 되었습니다. 저희 팀 같은 경우에는 안드로이드 멀티 모듈과 Flow 를 사용해보았는데요, 물론 이미 다뤄본 팀원들도 있긴 했지만 그렇지 못한 팀원(제가 포함됩니다.)도 존재했습니다. 이는 분명 장점으로 작용하였지만, 개발 속도 및 완성도가 현저히 떨어지는 요인이기도 했습니다. 그리고 이런 요인들로 인해 3개월 동안의 마라톤 개발은 상당히 길고 루즈하게 느껴졌으며, 저 뿐만 아니라 대부분 뒷심이 부족해지는 분위기였습니다.
2. 친목 도모
동아리라는 특수한 모임이기 때문에, 동아리 자체에서 친목활동을 권장했습니다. 물론 동아리의 목적에는 친목이 빠질 수 없다고 생각하나, 해커톤 때에도 프로젝트의 완성보다는 1박 2일 오프라인 모임에 조금 더 초점이 맞춰져있었던 것 같습니다.
해커톤의 정답은 없습니다. 하지만 저는 개인적으로 단기간에 얼른 해치울 수 있는 해커톤을 원했고, 친목보다는 프로젝트 완성도에 집중하고 싶었기 때문에 이전 해커톤 경험은 약간 아쉬움으로 남아있었습니다.
GDG 오프티벌 해커톤
그러나 이번 GDG 오프티벌 해커톤은 달랐습니다. 아무런 사전 개발 기간 없이 공식 행사 기간이 무박 2일이었습니다. 게다가 팀 빌딩 결과 또한 당일 오전에 공지되었고, 오프닝 행사 때 주제가 공지되었습니다. 미리 준비해온 코드를 사용하는 것은 어뷰징으로 처리하겠다고도 하시더라구요. 즉, 행사 이전에는 아무런 준비를 할 필요도 없고 할 수도 없으며 깔끔하게 22시간동안 개발 후, 공식적인 사후 디벨롭도 없는 것입니다. 최소한의 시간만 들여서 바짝 집중할 수 있어서 무척 좋았습니다.
각 팀은 디자인 1명, 백엔드 2명, 프론트엔드 2명으로 총 5명으로 구성되었습니다. 인원도 많지 않고 시간도 짧았기 때문에 자연스럽게 친목보다는 프로젝트에 집중하게 되었던 것 같습니다. 특히 제가 속해있던 팀은 백엔드 1명이 사전 공유 없이 행사에 참여하지 않아서 4명으로 진행되었기 때문에 더욱 집중할 수 밖에 없었습니다. 그리고 프로젝트에 집중할수록, 오히려 소규모 팀원들과 전우애가 생기며 별다른 사적 대화 없이도 많이 가까워졌던 것 같습니다.
공간
해커톤은 밤새 진행되기 때문에 작업 장소에 간단히 의자와 책상만 있어서는 부족합니다. 커뮤니케이션을 위해 잠깐 바닥에 앉기도 하고, 쇼파 같은 곳에 편히 앉아 쉴 수도 있어야하며 충분한 물과 음식 등이 모두 마련되어 있어야합니다. 그런 의미에서 이번 해커톤의 장소는 아주 만족스러웠는데요, 무려 마켓컬리 라운지에서 진행되었습니다. 20팀을 모두 수용하고도 여분의 로비가 남아도는 큰 공간이었고 다양한 형태의 쇼파와 테이블들이 있어서 각자 편안한 자리에서 작업할 수 있었습니다. 저는 중간에 위치한 책장 같은 곳 위에 노트북을 올려두고 서서 작업을 하기도 했습니다.
로비 가운데 빔 프로젝터가 설치되어 있어서 오프닝 행사 및 발표, 시연 때에도 잘 활용할 수 있었고 고품질의 스피커 덕분에 작업 내내 자연스럽게 음악을 들을 수도 있었습니다. 회사 건물이기 때문에 화장실 또한 아주 쾌적했구요. (18층이다 보니 화장실에서 보이는 시티뷰가 끝내줍니다 ..)
사육
팀원 중 한 분이 해커톤은 마치 사육당하는 것 같다는 말씀을 하셨습니다. 저는 이전 해커톤 경험을 떠올려봤을 땐 공감하지 못했지만, 이번 해커톤이 진행되면서 그 말에 강하게 공감할 수 있게 되었습니다.
로비 한구석에 각종 과자, 젤리, 믹스커피, 차 등이 쌓여있어서 자유룝게 가져갈 수 있었습니다. 저는 개인적으로 빈츠와 쿠엔크를 좋아해서 집중적으로 먹었던 것 같습니다. 그리고 가운데에 있는 냉장고에는 캔맥주가 종류별로 가득 진열되어 있었고, 포카리스웨트, 콜라, 사이다 등의 음료들도 있어서 컵에 담아갈 수 있었습니다. 아 그러고보니 몬스터, 핫식스 등 고카페인 음료들도 있었던 것 같네요.
저녁 시간에는 도시락을 하나씩 배분받았고, 11시 쯤이 되자 야식으로 치킨을 나눠줬습니다. 무려 팀당 2마리였는데요, 양념 후라이드 각 1마리 씩 황금비율이었습니다. 저희 팀은 1명이 부족해서 아쉬웠는데, 이때 만큼은 입이 줄어서 오히려 좋았습니다.
스태프
확실히 GDG 스태프 분들이 해커톤 행사 진행을 위해 힘써주고 계시다보니, 그에 맞게 쾌적하고 원활했던 것 같습니다. 그도 그럴 것이, 대충 세어봐도 10명이 넘는 스태프 분들이 각자 역할을 맡아서 잠도 주무시지 않고 신경써주시더라구요. 뭔가 궁금한 게 있거나 불편한 게 있다면 아무나 붙잡고 물어봐도 되었습니다. 혹시 직접 물어보는 것이 불편하거나 개발 흐름을 깨고 싶지 않을 수 있으니, 디스코드 채널을 통해 문의해도 된다고 하셔서 종종 이용했는데요, 이 부분이 정말 편리했던 것 같습니다.
개발한 프로젝트
행사에 대한 이야기는 여기서 마무리하고, 이번에 제가 개발한 프로젝트에 대해 이야기해볼까합니다.
저희 팀은 네트워킹을 통해 습관을 유지하고 동기를 강화할 수 있는 서비스를 계획했습니다.
최근들어 자기계발에 대한 욕구 실현이 유행처럼 번지고 있습니다. 미라클모닝, 운동, 금연 등 많은 사람들이 만들고자, 해내고자하는 습관들이 있죠. 물론 예전부터 이런 습관에 대한 욕구는 꾸준히 있어왔으나, 코로나 팬데믹 이후 외부 활동이 줄어듬에 따라 혼자서 스스로를 가꾸고 되돌아보는 시간이 많아졌고 이런 욕구가 더욱 강화되고 실현될 수 있는 기회가 많지 않았나싶습니다.
물론 습관을 유지시켜줄 수 있도록 동기부여를 도와주는 서비스는 시중에 많이 나와있습니다. 챌린저스, 루빗 등이 그 예입니다. 챌린저스는 사람들과 함께 공통 목표를 가질 수 있고, "벌금" 이라는 체벌성 동기부여 시스템을 갖고 있습니다. 그에 비해 루빗은 혼자서 귀여운 토끼를 키워가며 관리하는, 알람이 포함된 Todo 리스트에 가깝구요. 저희는 가까운 친구들과 소소하게 서로를 자극해주며 습관을 유지할 수 있는 서비스를 만들고자 했습니다.
챌린저스와 같이 다른 사람들과 공통된 목표를 갖는 것은 동일하지만, 마감 기한이 정해져있지 않고 별도의 퍼니쉬가 없습니다. 위와 같이 함께 유지하고자 하는 습관이 무엇인지와 규칙만을 간단하게 설정하면 됩니다. 그리고 해당 습관에 초대된 구성원들은 각자 규칙대로 습관을 실행하고, 인증사진만 올리면 됩니다.
그렇다면 어떤 방식으로 동기를 부여할까요? 친구들과 함께 있는 단체톡방에서 습관을 인증하는 모습과 크게 다르지 않습니다. 누군가가 인증사진을 올리면 친구들이 칭찬을 해주거나 인정해주지 않을 수도 있죠. 이걸 명확하게 기능으로 제공하고, UI로 보여주고 있습니다.
이렇게 누군가가 인증 사진을 올리면 다른 구성원들은 "칭찬해" 혹은 "다시해" 의견을 남길 수 있습니다. "칭찬해" 의견이 과반수를 넘기지 못하면 해당 인증은 인정받지 못하고 습관을 유지하지 못한 것으로 처리됩니다. 이는 "습관 유지 콤보" 에도 영향을 줍니다.
이런식으로 기존의 습관 유지 서비스와 다르게 친구들과 소소하게 서로를 자극시켜주는 서비스를 기획했습니다.
개발 방식
그렇다면 이 서비스는 어떻게 개발되어 어떤 결과물을 만들었을까요? 우선 저는 이전에 참여해본 해커톤에서는 제대로된 결과물을 만들지 못했습니다. 그 이유는 다음과 같다고 생각합니다.
1. 익숙하지 않은 기술 사용
앞서 언급한 것처럼 다양한 기술을 시도하다보니 공부를 병행하게 되었고, 개발 속도가 현저히 느려졌습니다. 게다가 시간은 흘러가지만 잘 몰라서 막히는 부분이 생기면 자주 의욕을 잃기도 했습니다. 좋은 퀄리티로 실제 서비스를 하는 것이 목적이 아니었는데 이렇게 공을 들이보니 회의감이 든 것 같습니다.
2. 체계적인 협업 구조
체계적으로 협업을 하는 것이 무엇이 문제이냐고 반문할 수 있지만, 해커톤이라는 특수한 환경에서는 오히려 독이 될 수 있습니다. 예전에는 팀원들과 Git-flow 에 맞춰 개발을 진행했고, 코드리뷰 또한 엄격하게 진행했습니다. 최소 몇 명 이상 Approve 를 줘야만 merge 할 수 있었죠. 실제 프로덕트 개발에서는 당연한 절차이지만 이는 앞으로의 유지보수를 가능하도록 하고, 배포 이후 발생할 수 있는 잠재적인 위험을 막기 위함이 큽니다. 해커톤 또한 앞으로 계속 유지보수를 할 수도 있고 실제로 배포를 할 수도 있죠. 하지만 98%의 개발자들이 해커톤 이후 프로젝트를 전혀 열어보지 않는다고 합니다. (출처 미상) 따라서 유지보수 및 잠재적 위험 요소 등은 어느정도 무시하고, 기획한 서비스를 시연가능한 수준의 프로토타입으로 만드는 것에 더욱 집중하는 것이 옳다고 생각합니다.
그래서 저희는 이번에 가장 익숙한 방법으로, 협업 룰과 같은 것들은 과감하게 버린 채로 개발을 했습니다.
- develop 브랜치에 바로 push 하기
- commit 메시지는 대충 쓰기
- 코드리뷰 생략
- 아키텍처 구조 신경쓰지 않기
- 중복 코드 환영
- 필요한 경우가 아니라면 Activity 로 작업하기
같이 안드로이드 작업을 한 팀원과 필요한 경우에는 논의를 했지만, 그 외에는 각자가 가장 편한 방식으로 작업을 했습니다. 저 같은 경우에는 그래도 MVVM 구조 + 상태 홀더 (UiState) 가 손에 익어 있어서 그대로 진행했고, 팀원 분께서는 MVC 가 가장 편했기 때문에 그렇게 작업했습니다. 무언가 방식을 맞추려고 하지도 않았고, 서로의 방식에 피드백을 주지도 않았죠. 다만, 팀원분께서 경험이 많지 않은 학생이셨기 때문에 가끔 개발 팁이나 몇 가지 궁금한 것들에 대해서는 조언을 해주기도 했습니다. (실제 서비스에서는 이렇게 개발하지 말아라, 이런식으로 하면 좋다 등..) 만약 이런 상황에서 뭔가 방법을 통일하려고 했다면 저도, 팀원분도 본인의 능률을 절반도 끌어올리지 못했을겁니다. 팀원분께서는 갑자기 왜 이렇게 해야하는지 모르는 상태로 제 방식을 따르다 보면 구현하고자 하는 것에 대한 고민보다 코드 작성 방식에 대한 고민을 더 많이 했을겁니다.
물론 이렇게 하다보니 Conflict 도 굉장히 많이 났습니다. 그냥 어디 작업하겠다는 간단한 통보(?)를 끝으로 어떤식으로 작업했는지 딱히 공유하지 않았기 때문입니다. 그래도 나름 화면단위로 역할을 주워가다보니 심각한 충돌은 없었고, 금방금방 해결할 수 있었습니다. 확실히 충돌을 피하기 위해서 매번 논의하고 인터페이스를 나누는 등의 작업을 하는 것보다 "시간"만은 확실히 절약이 되더라구요.
사실 해커톤에서 많이 하는 건, 서비스 기획 명세와 서버와의 통신 인터페이스 논의입니다.
서버와의 협업
개발이 시작되고 몇 시간 동안은 서버 api 가 나오지 않습니다. 그 동안은 어떤걸 했냐면요
- 레포지토리 생성
- 프로젝트 초기화 및 push
- Retrofit 환경 세팅
- 각종 필요한 라이브러리 세팅 (Glide, lifecycle, Coroutine 등)
- 유용한 확장함수 및 클래스 추가 (토스트, EventLiveData 등)
- 와이어프레임을 토대로 액티비티 및 레이아웃 생성 + 패키지 정리
위 작업만 모두 하는데에는 생각보다 얼마 걸리지 않습니다. 그러다보면 서버 api 명세서 작성이 완료됩니다. 물론 저희끼리 기획한 것들과 와이어프레임만 보고 대충 작성한 것이기 때문에 얼마든지 바뀔 수 있고 빠트린 게 있을겁니다.
그럼 API 명세서를 바탕으로 기능들이 동작할 수 있게 코드도 작성합니다. 최종적으로 API 를 호출하는 부분은 함수로 비워두고 로그만 찍어두었습니다. 그 과정에서 저희는 UI 관련 로직들이 정상적으로 동작할 수 있는 것에 집중하여 고민하고 검증합니다.
fun onDoneProfileEdit() {
Log.d(javaClass.simpleName, profileUiModel.value.toString())
if (metaRegisterModel != null) {
// Todo: 회원가입 요청
Log.d(javaClass.simpleName, metaRegisterModel.toString())
} else {
// Todo: 프로필 정보 수정 요청
}
}
또 그러다보면, API 가 하나씩 완성되기 시작합니다. 그럼 그때부터 본격적으로 비워두었던 함수에서 API 를 실제로 호출하기 시작합니다. 요청이 정상적으로 되는지, 알맞은 응답이 오는지만 확인하면 얼추 동작을 하게 됩니다. 이때 문제가 있다면 서버와 이야기하고 원인을 파악합니다. 그리고 필요한 필드 값이 있다면 요청하고 반영하는 작업을 계속 반복합니다.
서버와의 협업 중 겪은 실수
이번에 가장 아쉬웠던 실수가 하나 있었습니다. 바로 인증 사진을 촬영하고 서버에 보내는 과정에 문제가 있었던 것인데요, 분명 사진을 잘 보내고 성공 응답이 떨어졌으나, 해당 인증을 칭찬할 수 있는 상세 화면으로 들어가면 조회 API 에서 에러가 발생했습니다. 저는 온전히 서버 쪽의 이슈인줄 알고 에러만 공유한 뒤, 다른 것들을 작업했습니다. 서버 쪽에서도 예상가는 원인이 있으니 발빠르게 움직이지 않았습니다. 그러나 발표 자료 제출 직전까지도 이슈가 해결되지 않았고, 막상 들여다보니 원인을 알 수 없었습니다. 그런 와중에도 저는 가만히 기다리기만 했고 발을 동동 구르고만 있었죠.
그러다 알고보니, 제가 사진을 잘못 보내고 있었습니다. 분명 Uri 및 File은 잘 추출이 되었고 Multipart 로 잘 감싸서 보냈는데, 서버 쪽에서 이 파일에 접근하려고 하면 에러가 발생했습니다. 혹시나 싶어서 ImageView 에 해당 사진을 그리도록 한 뒤에 Bitmap 으로 추출해보니 에러가 발생했습니다. 클라이언트에서 뭔가 잘못 처리하고 있었던 것이죠. 그러나 발표 자료 제출 시간이 다 되어서 결국 앱의 핵심 기능 중 하나인 인증 사진 업로드 기능을 완성하지 못한채로 제출할 수 밖에 없었습니다.
정신없이 바쁜 것이 당연한 해커톤이지만, 서버 이슈라고 해서 반드시 서버 쪽의 실수만 있는 것은 아닙니다. 클라이언트 쪽에서도 값을 정상적으로 잘 보내고 있는지, 정상적인 경로인지 등을 함께 확인하여야합니다. 끝까지 서버 분께 얼른 고쳐내라고 닥달했던 것에 큰 반성을 했습니다.
디자인과의 협업
서버 API 가 하나씩 나올 무렵, 확정된 디자인 가이드도 하나씩 공유가 됩니다. 저희 팀은 피그마를 사용했습니다. 요즘 베타 버전임에도 스캐치, 제플린 등의 디자인 프로그램들을 모두 제치고 점유율 1위를 자랑하고 있는 괴물 프로그램이죠. 작업하는 과정이 실시간으로 공유되기때문에 꼭 완성되지 않았더라도 대충 어떤 UI 를 가지고 있을지 예상이 가기 때문에 개발자들에게도 아주 편리합니다. 또한 제플린에서는 에셋을 디자이너가 명확하게 그루핑 지어줘야 올바르게 다운로드 받을 수 있었지만, 피그마는 개발자가 직접 그루핑하여 에셋을 다운로드 받을 수 있습니다.
이런식으로 작업된 디자인 가이드에 따라 안드로이드에서도 레이아웃을 작성하는데요, 그 과정에서 반드시 뭔가 엣지 케이스가 떠오르게 됩니다. 개발자는 해당 UI/UX 가 동작할 수 있는 코드를 작성하는 과정에서 모든 케이스를 떠올리기 때문입니다. 이 버튼을 누르면 어디로 가는지, 이 이미지가 노출되는 조건이 무엇인지, 만약 사용자가 이 화면에서 이탈하면 어떻게 되는지 등 말이죠.
이런 것들은 바로바로 논의를 해야합니다. 조금이라도 디자인이 완성되기 전에 결정되어야 불필요한 작업을 하지 않을 수 있습니다. 게다가 디자이너의 경우, 개발자에 비해서 비교적 개발 쪽 지식이 부족하기 때문에 너무 개발자의 언어로 이야기하지 않도록 주의해야합니다.
- onCreate() 에서는 이 값이 아직 null 일텐데 이걸 바로 보여줄 수가 없어요 (X)
- 데이터를 불러오는데 약간 딜레이가 있는데, 그 동안은 화면에 어떤 걸 보여주면 될까요 ? (O)
다행히 저희 팀 디자이너께서는 프론트엔드 및 각종 개발 경험이 있으셔서 이 부분에 대한 불편함은 거의 없었습니다. 오히려 기획 단계에서 저희도 생각못한 개발 쪽 리스크를 먼저 고려해주시기도 했죠.
결과
아쉽게도 처음에 생각한 모든 기능을 구현하지는 못했습니다. 아래는 구현하지 못한 기능들입니다.
- 인증 글을 올린 경우 발생하는 푸시 알림
- 과반수 이상 칭찬하여 습관 콤보 계산 및 노출
- 아직 칭찬하거나 다시하라는 의견을 남기지 않은 게시물을 모아보는 기능
- 인증 사진을 올린 후 바로 해당 상세 페이지로 넘어가는 기능
푸시 알림을 구현하기 위해서 조금 시간이 들더라도 회원가입 기능을 넣었던 것인데, 정작 푸시 알림은 하지 못해서 많은 아쉬움이 있었습니다. 그 외에도 시연 중 꼭 보여줘야할 기능들이 몇 개 빠져있었던 것도 아쉬움이 남았습니다.
심사 위원들께서도 이런 아쉬움이 있었는지, 수상은 하지 못했습니다.
배운 것
그래도 물론 배운 것이 있습니다. 위에서 언급했듯이 해커톤이라는 특수한 개발 환경에서 어떤 것들을 중점으로 둬야하는지 알게 되었습니다. 그리고 매번 딥링크를 활용해보고 싶었는데 이번에 딥링크를 통해 습관 방에 초대할 수 있도록 하는 기능을 추가하면서 처음으로 딥링크를 직접 다뤄보았습니다. 생각보다 어렵지 않았고 개발자가 직접 어떤 도메인으로 딥링크를 수신할지 결정할 수 있다는 것이 흥미로웠습니다. 그로인해 다른 앱들과 중복되는 문제점이 있고, 그에 대한 대안들도 이미 나와있다는 것도 알게 되었습니다.
얻은 것
그리고 얻은 것들도 굉장히 많습니다. 우선 오랜만에 이렇게 직접 서비스를 기획하고 처음부터 코드를 작성하면서 많은 개발 욕구들이 충족되었습니다. 많은 개발자들이 공감하다시피, 대부분은 기존 코드를 유지보수하는데에 시간을 보냅니다. 뭔가 하고싶은 게 있어도 레거시들의 강력한 존재감 덕분에 자유롭게 하지 못하고 수정에 수정을 거듭할수록 코드는 프랑켄슈타인이 되어가죠. 가끔 이렇게 마음대로 처음부터 개발하는 즐거움을 느껴주면 의욕을 잃지 않을 수 있습니다.
또한 이번에 함께 한 팀원분들이 개인적으로 정말 잘 맞았다고 생각했습니다. 단 한 분도 튀지 않고 팀에 녹아들었고, 서로가 생각한 방식들이나 제안한 의견들을 받아들이는데에 큰 노력이 필요하지 않았습니다. 그만큼 사고 방식에서 큰 차이가 없고 결이 비슷한 사람들이었던 것 같습니다.
뿐만 아니라 중간중간 오가는 사담에서도 부담스럽지 않고 편안한 분위기가 자연스럽게 조성되었고, 개그 코드도 맞는지 시덥잖은 이야기에도 많이 웃었던 것 같습니다. 아무래도 해커톤에서 가장 중요한 건 이런 즐거움이 아닐까요 ?
마치며
이렇게 정말 만족스러운 무박 2일간의 해커톤이 마무리 되었습니다. 비록 수상은 하지 못했지만 그 과정에서 정말 즐거웠고 많은 것을 얻었기 때문에 아쉽지가 않았습니다. 앞으로도 오프라인 해커톤 행사가 있다면 꼭 참여하고 싶고, 이 글을 읽으시는 많은 분들께도 해커톤을 권하고 싶습니다.