조각들

국회에서 진행됐던 데모데이, 우측은 우리 팀 부스

 
드디어 앱잼이 끝났다.
 
나는 앱잼에 대해 어떤 특별한 기대가 있지는 않았는데 정말 순식간에 지나갔다.
데모데이 직전에 이르러서는 너무 바빠서 일만 하느라 더 그랬던 것 같다.
 
이번 앱잼 기간동안 느꼈던 것들이 많은데 지금의 생각이 날아가기 전에 작업기를 남기려고 한다.
 
 

팀빌딩

 
나는 팀빌딩 단계에서 여러 기획들을 보고 "내가 이 팀에 개발자로 합류해서 제 역할을 충분히 해낼 수 있는가?"를  중요하게 따졌다.
 
여기서 제 역할이라는 건, 맡은 화면과 기능을 기간 내에 성공적으로 구현해낼 수 있는지를 의미한다.
나는 러닝 코스 그리기 서비스인 '러넥트'에 합류하게 되었는데 처음 팀에 들어왔을 때는 기대보다 우려가 앞섰다.
 


프로젝트 초반

 
'지도에 러닝 코스를 그린다'는 미션은 뚜렷했는데 '어떻게' 그릴지는 논의된 바가 없어서 막막했다. 그리고 마감 기간이 굉장히 짧았는데 안 해본 기능을 공부해가면서 구현했어야 해서 부담이 됐다. 릴리즈를 너무 해보고 싶은데 안개가 낀 느낌이었다.
 
이전에 무턱대고 기획, 디자인부터 했다가 나중에 구현을 못해서 프로젝트를 엎었던 적이 있다.
그래서 이번에는 그때의 아쉬움을 반복하지 않고자 사전 기술 리서치를 꼼꼼히했다.
 
시중에 있는 러닝 어플을 모두 깔아서 '그리기' 기능이 있는지, 있다면 어떻게 구현했는지 래퍼런스를 조사했다. 또한 참고 자료는 충분한지, API 가이드는 자세히 설명돼있는지도 꼼꼼히 알아봤다.
 
이후에는 기술적으로 어떤 것들이 어디까지 가능한지를 최대한 빠르게 기획, 디자인 분들에게 전달했다.
그래야 기획, 디자이너 분들이 기껏 작업해놓은 걸 날리는 경우를 최소화할 수 있고 빠르게 작업을 시작할 수 있기 때문이다.
 
그림판처럼 연속적으로 그리는 건 어렵고 마커를 찍고 그것들을 선으로 연결하는 정도가 최선일 것 같다고 내용을 전달했다. 다행히 상황을 잘 이해해주셨다. 우려했던 상황은 일어나지 않았다.
 
맵 API는 여러 선택지가 있었는데 가이드가 잘 써져있는 네이버 맵 API를 사용하기로 했다.
 
이후에는 기획, 디자인 분들이 "이거 가능한가요?" 질문 주시는 것들에 답변을 하고 프로토타입이 나올 때까지 기다렸다.
 
그런데 이 과정이 생각보다 길었다. 우리 서비스가 어떤 걸 하는 서비스인지, 서비스 컨셉이 불명확하다고 느꼈고 
이로 인해 같은 맥락 안에서 의견이 더해지고 정리되기보단 뒤죽박죽 섞이면서 산으로 가는 느낌이었다.
 
뷰가 빨리 나오면 개발 기간이 하루라도 더 생기니까 빨리 정리가 됐으면 좋겠는데 쉽지 않아보였다.
 


프로젝트 중반

 
우리가 처음에 정해놨던 스케줄 표를 봤는데 계획했던 것보다 일정이 밀리고 있었다. 그런데 다행히 기획이 빠르게 정리되었다.
 
기획이 얼추 정리되고 나서는 디자인을 기다렸다.
 
디자인 파트와 소통이 부족했다.
 
데모데이를 2주 반 정도 남긴 시점에서 와이어프레임 정도는 웬만큼 나온 줄 알고 와이어프레임을 요구했다. 그런데 아예 작업이 안 됐다고 해서 당황스러웠다.
 
당장 개발을 시작해도 안드 파트는 2명이라 시간이 빠듯했지만 디자인 파트도 기획 정리가 늦게 끝나서 작업 시작이 늦어진 만큼, 또 우리가 언제까지는 어떤 것들이 필요하다고 디자인 파트에게 전달을 안 했던 만큼, 우리에게도 책임이 있어서 그냥 기다리기로 했다.
 


프로젝트 후반

 
눈 떠 있는 모든 시간에 코딩을 했다고 봐도 무방하다.
특히 데모데이 일주일 전부터는 하루 12시간 넘게 매일을 코딩했다.
알바와 병행하면서 체력적으로도 부담이 많이 되었다.
이 과정에서 위염이 생겼다. 컨디션이 바닥으로 떨어졌는데 작업을 쉴 수가 없었다.
데모데이 당일 아침까지도 코딩을 했다.
 
딱 봐도 시간 좀 쓰겠다 싶은 작업이면 괜찮은데 금방 넘길 수 있을 것 같았던 곳에서 시간을 많이 썼다.
 
어떤 이슈가 있었냐면,
 

1) Intent
 

Activity 간 data 전달을 할 때는 Intent를 사용해야 한다. 
분명 putExtra, getExtra까지 잘 써줬는데 data가 넘어오질 않았다.
팀원에게 물어보니 intent가 한 키워드로 getIntent, putIntent 2가지 다 쓰일 수 있는데
내 코드에서는 putIntent가 아니라 getIntent로 적용이 되고 있었다는 것이다.
 
따라서 Intent를 별도의 변수로 선언해준다음 사용해야 putIntent를 쓸 수 있다고 했다.
 
마우스를 올려보면 어떤 타입인지, 내가 어떤 걸 쓰고 있는지 볼 수 있는데 이를 잘 확인해야겠다고 느꼈다.
 
 

2) bitmap -> uri 변환 함수
 

그린 코스 이미지를 서버에 멀티파트로 보내야 한다.
이때 이미지는 RequestBody 타입으로 가공이 돼야하는데 uri가 필요하다.
 
네이버 맵 api에서 지원하는 snapShot 메서드는 캡쳐 이미지를 bitmap 타입으로 반환한다.
따라서 bitmap을 uri로 변환하는 작업이 필요했다.
 
구글링을 통해 해당 변환을 도와주는 함수를 찾았고 
이걸 사용해서 성공적으로 서버 통신을 해냈다. 
 
그런데 데모데이 전날 갑자기 그 함수에 문제가 생겼다.
정확히 어떤 문제인지는 모르겠으나 분명 잘 돌아갔었는데 로그를 찍어보니 null이 떴다. 
 
bitmap을 uri로 변환하는 다른 방법이 필요했는데 구글링을 해봐도 자료가 잘 나오지 않았다.
그러다 결국 방법을 찾아냈다.
이전에는 캡쳐로 받아온 bitmap을 별도의 저장 과정 없이 바로 uri로 변환하는 방법이었다면
이번에는 캡쳐 이미지를 local에 저장한 후 그 local 저장 path를 받아와서 uri로 변환하는 방법이었다.
 
이 방법으로 uri를 변환하니 null이 아닌 uri가 정상적으로 반환되었다.
 
 

3) 이미지 타입 미스매치
 

서버에서 요구하는 형식에 맞춰서 request를 잘 보냈는데 계속 response로 500이 날아왔다.
뭐가 문제인지 이해를 못하고 있었는데 마침 옆에 서버 개발자가 있어서 크게 도움을 받았다.
서버 쪽에서 확인을 해보니 이미지가 잘 날아오긴 하는데 서버에서 처리하는 이미지 type과 달라서 문제가 생긴 것 같다고 했다.
 
이전에 bitmap을 바로 uri로 변환할 때는 uri의 맨앞 문자열이 http로 시작했는데
새로운 방법으로는 맨앞 문자열이 file로 시작이 됐다. 우리는 이것이 문제가 된 것으로 생각하고 방법을 찾아봤다.
fileProvider라는 것이 있는데 우리의 상황에 딱 맞았다. 맨앞 문자열을 file에서 content로 바꿔주는 것이었다.
한 번도 안 써본 것이라 이걸 사용하는데도 시간이 좀 걸렸는데 cache-path를 설정해주니 해결이 되었다.
서버 통신 문제도 해결이 되었다.
 
위염 탓에 체력적으로 너무 힘들어서 고개를 들고 있기도 어려웠는데 옆에 팀원도 고생하고 있는데 내가 뭐라도 도움이 되어야겠다는 생각에 고개를 떨군채로 핸드폰으로 구글링을 이어나갔다. 팀원이 처음에 fileProvider를 잘 쓰지 못했는데 내가 옆에서 정보를 보탰고 결국 같이 문제를 해결해낼 수 있었다.
 
 

4)  List를 Json으로 변환
 

이전 세미나 과제에서 멀티파트 통신을 처음 해볼 땐 서버에서 요구하는 게 이미지랑 String 타입 변수 2개가 들어간 Json이었다. 그런데 이번에는 Json 안에 List를 넣어서 보내야 했다. 전에 했던 방법대로 JsonObjectBuilder 안에 있는 put 메서드를 써서 변환을 하려고 했는데 이 put 메서드가 List 타입은 지원을 안 했다. 그래서 방법을 찾느라 고생했다.
 
별 방법을 다 써봤다. 
사용법을 잘 못 익힌 건진 몰라도 현우 형이 putJsonArray 샘플 코드들 찾아줘서 그걸 따라 썼는데도 잘 안 됐다.
 
그러다 put 메서드가 JsonElement type을 지원하길래 encodeToJsonElement를 써서 list를 JsonElement type으로 변환하니까 기존의 put 메서드를 쓸 수 있어서 해결했다. 
 
 

5) 네이버 맵 정보창
 

구글링 하면서 커스텀까지 해봤는데도 한계가 있었다. 여기서 시간을 꽤 많이 썼는데
이러다 마커 이미지를 svg로 뽑을 때 마커까지 포함해서 뽑아쓰는 방법을 생각해냈다.
 
나중에 물어보니 iOS 파트원들은 커스텀을 해서 썼다고 했다. 우리가 잘 못 사용한 거긴 한데 결과적으로는 오히려 커스텀 코드를 작성하는 것보다 svg까지 한 번에 뽑는 게 더 효율적이라 좋은 방법이라는 생각이 들었다.
 
 

6) 모든 페이지를 Activity로 구성
 

Fragment를 적절히 활용했으면 수월했을 텐데 모든 페이지를 Activity로 구성하니까 data 공유를 할 때마다 Intent를 써줘야 했고 번거로워서 피로감이 컸다. 
 
 

7) 초기 세팅 및 깃 브랜치 전략 잘못 설정
 

기능 별로 브랜치를 파서 merge하고 pull받고 또 새로운 브랜치를 파는 식으로 작업을 했어야 했는데
처음에 폴더링이랑 코드 컨벤션을 잘해놓으면 굳이 브랜치 여러개 안 파도 conflict 이슈가 별로 없어서
그냥 각자 브랜치 하나 판 다음에 작업 다 해놓고 합치기로 했는데 이게 스노우볼이 굴러갔다.
 
데모데이 당일 새벽에 머지를 하려고 하니 merge conflict 말고 다른 문제가 있었다.
표면적으로 합친다 한들 내부적으로 페이지 간 data 공유 및 수신이 안 돼서 앱을 못돌린다는 문제가 생겼다.
 
아차 싶었는데 대응하기엔 시간이 부족했다. 할 수 없이 우리는 데모데이 당일에 공기계를 2개 돌려서 각자가 작업한 걸 따로 보여줬는데 너무 아쉬운 순간이었다. 
 
또 서로 공유하는 리소스가 있는데 머지하고 pull 받는 식으로 했으면 한 명만 만들어도 됐을 걸,
따로 작업하니까 한 리소스를 두 명이 만들어야 했고 심지어 merge하는 과정에서 이름이 겹치면
한 명껄 삭제해야 했는데 정말 사서 고생하는 식이었고, 그 파일이 삭제됨으로써 기존의 다른 파일들도 영향을 받아서 손을 한 번씩 봐줘야 하는 상황 생겼었다.
 


팀 분위기

앱잼 기간동안 한 마디도 안 해본 팀원이 있는가 하면, 데모데이 전 날 처음 본 팀원도 있었다. 
전반적으로 기획, 디자인을 제외하곤 오피스에 잘 안 나오는 분위기였으며 나와도 시간대가 안 겹쳐서 못 마주쳤다. 
 
이로 인해 나는 우리 팀이 판도라의 상자 같다는 생각을 했다.
접점이 없다보니 다들 팀에 대해 어떤 생각을 가지고 있는지 모르겠고, 혹시나 쌓아두고 있는 것이 있는지 파악이 안 됐다.
 
그런데 데모데이가 다가올수록 오피스에서 마주치는 빈도가 늘어났고 다 같이 모였을 때의 분위기는 좋았고 재밌었다. 데모데이 당일에 칭찬도 많이 받으면서 다들 릴리즈까지 이어가기로 마음을 모았다.
 


소감

우리 작업실이었던 패파

몸과 마음이 너무 힘들었다. 피곤한 건 참을 수 있는데 몸이 아파서 문제였다. 
이 때문에 일 외적인 부분을 잘 챙기지 못했다. 아롱이 밥을 잘 못챙겨줘서 너무 미안했다.
나이가 많은 만큼 좀 더 신경써주고 하루하루 소중히 보내야하는데  앱잼 기간동안 그러지 못해서 마음이 너무 무거웠고 슬펐다.
 
일적으로는 사전 리서치를 꼼꼼히 했던 게 큰 도움이 됐다. 난이도가 높을지언정 지원하는 기술이 없어서 구현 자체가 불가능하다거나 하는 상황이 없었다.
 
데모데이 당일 아침에 내부 logic 연결이 안 된다는 걸 깨닫고는 "망했네" 이 생각이었는데 우리 팀 앱 시연을 구경온 사람들이 생각보다 칭찬을 많이 해줬다.
 
"우와 이거 어떻게 한 거야?", "클라 진짜 갈렸겠네" 이런 반응이 나올 때마다 그동안의 노력을 인정받는 것 같아 마음이 풀렸다. 한 달 정도 일만 하다가 오랜만에 솝트 지인들을 만났는데 다들 나를 너무 반겨줘서, 또 챙겨줘서 너무 힐링했다. 일만 하느라 잠시 까먹고 있던 감정이었는데 되살아났다.  
 
다른 팀들 부스를 돌아보면서 어떻게 구현했는지 기술적인 부분을 많이 봤다. 내가 개발자이다보니 같은 걸 봐도 보이는 게 달랐다. 재밌었다.
 
역설적이지만 비효율적이어서 효율적인 부분도 있었다. 비효율적으로 작업했지만 총 투자한 기간은 2주밖에 안 되기 때문에 기간 대비 좋은 경험을 얻었다고 생각한다.
 
 
 
 
 
 
 
 
 

'Android > 회고' 카테고리의 다른 글

[회고] Runnet 릴리즈  (0) 2023.05.27