Final Project를 마무리하였다.
코드스테이츠의 수강생들 4명이 팀으로 모여 한달간 진행했던 프로젝트였다. 나는 백엔드로서 팀에 참여하였는데, First Project에서는 프론트였기 때문에 다양한 경험을 해보고 싶은 생각에 선택했다.
이 글은 프로젝트가 마무리되고 리팩토링을 거친 후에 작성하는 회고록이다.
프로젝트 '퍼즐' 바로가기
∘ 처음에 팀에서 나온 아이디어는 '희귀템 알리미'였다. 현상수배를 컨셉으로 찾기 어려운 물건들(ex- 예전의 허니버터칩)을 등록하면 다른 유저들이 그 물건 위치를 공유할 수 있게 하자는 아이디어였다. 하지만 커뮤니티 기반의 서비스는 실제 유저들이 있어야 제대로 돌아가는지 알 수 있다는 의견에 따라서 그동안 짰던 와이어프레임을 뒤엎고 다시 발상단계로 돌아갔다.
∘ 그래서 다음에 나온 아이디어가 바로 유저가 업로드한 이미지로 만들어진 퍼즐로 진척도를 알 수 있게 하는 협업툴이었다. Forest라는 시간관리 어플이 있다. 타이머를 켜면 다른 어플들이 잠겨서 할일에 집중하게 만들고 정한 시간동안 집중을 했다면 유저의 개인 정원에 나무를 심을 수 있는 보상을 주는 어플이다. 우리 팀은 Forest 어플의 아이디어 중에서 '업무를 진행시키면 시각적인 보상을 주자'는 부분을 협업툴에 접목하는 것이 괜찮은 아이디어라고 생각했다. 그리고 그 '시각적인 보상' 으로서 같이 완성한다는 느낌을 주는 데에는 퍼즐이 협업툴과 어울렸기 때문에 해당 아이디어가 채택되었다.
그렇게 기획단계를 마무리하고 실제 구현에 들어가게 되는데...
(기획단계의 기능 플로우, 와이어프레임)
∘ 나는 프로젝트 기간동안 백엔드로서 주로 이미지 처리와 관련된 api 엔드포인트 기능 (이미지 업로드, 프로젝트 진행도와 조각난 이미지 동기화 등)을 만드는 데 주력했다. 이 프로젝트의 중요한 부분은 이미지 처리라고 생각해서 꼭 해보고 싶었기 때문이었다.
∘ 유저가 프로젝트 이미지를 업로드하면 그 이미지를 쪼개어서 프로젝트가 진행될 수록 더 많은 조각을 볼 수 있게 처리해야 했다. 처음에는 프로젝트 내의 업무(=태스크 카드) 하나당 이미지 한 조각을 연동 시키려고 했었다. 즉 프로젝트가 전체 퍼즐이라면 하나의 업무는 퍼즐 한조각인 셈이었다. 프로젝트 내의 모든 업무를 완료하면 이미지는 완성된 퍼즐이 되는 것이다. 이미지를 나누는 것자체가 큰일이었지만 그보다 더 큰 문제는 프로젝트 진행 중에 새로운 업무를 추가시켰을 때, 퍼즐 한 조각의 크기가 달라지는 것이다. 새 업무를 추가시키는 건 협업을 하다보면 반드시 필요한 기능이었기 때문에 프로젝트 생성할 때 전체 퍼즐의 갯수를 정하는 것은 의미가 없었다.
(업무 개수가 늘어나면 하나의 퍼즐 크기가 달라진다. 더불어 퍼즐조각 개수가 NxN개가 아닐 때 어떻게 처리해야할지에 대한 문제도 있었다)
∘ STEP1 : 유저가 전체 프로젝트 이미지 한장을 업로드하면, 서버에서 (업무 하나) / (전체 업무 개수)의 크기만큼 이미지를 잘라서 다시 응답해보자!
∘ STEP2 : 업무 개수가 늘어날 때마다 새로운 비율로 이미지를 잘라서 S3에 저장하면 업로드 횟수가 너무 많아진다. 10조각인 프로젝트에 업무를 추가하면 이미지를 다시 11조각으로 자르는데 10조각일 때와 조각 크기가 다르기 때문에 새로 자른 11조각 모두를 업로드해야되기 때문이다.
∘ STEP3 : 그럼 서버에서 이미지를 자르는 작업을 수행하고 DB에 좌표값만 업로드하면 되지 않을까? 가능하기만 하다면 가장 이상적인 방법이겠지만 문제는 그렇게 이미지를 세밀하게 자르는 복잡한 연산을 설계할 능력이 나에게 없었다.
∘ 이쯤 되어서 프로젝트 마감기간이 다가왔고, 프론트엔드를 맡으신 팀원분이 이미지 자르는 것은 프론트엔드에서 어떻게든 할 것이니 전체 이미지 업로드 기능만 구현해달라고 하셨다. 그래서 multer와 multerS3로 이미지를 S3에 업로드하고 이미지 경로를 클라이언트에 응답하는 식으로 처리를 했고, 이미지 슬라이스는 팀원끼리 머리를 싸매었지만 끝내 뾰족한 수가 없이 프로젝트 기간이 마무리되고 말았다. 프로젝트 이름이 Puzzle인데 퍼즐기능이 완벽하지 않다니! 너무 분했다.
(고민의 흔적)
∘ 리팩토링 기간동안 나는 프론트엔드를 맡았다. 내가 백엔드에서 마무리 짓지 못한 이미지 자르기 기능을 프론트사이드에서 꼭 설욕하고 싶었다. 일단 먼저 나는 지금 나의 능력의 한계를 인정하는 데서부터 시작하기로 했다. 업무가 추가될 때마다 적절한 크기로 이미지를 자르는 것은 포기하였다. 퍼즐 한 조각의 크기는 고정되어야 한다.
∘ 그런데 생각해보면 우리 프로젝트는 실제 퍼즐게임을 하는 것이 아니라, 프로젝트가 진행되면서 이미지의 일부가 퍼즐이 맞춰지는 것처럼 보여지기만 하면 된다. 직소퍼즐처럼 조각들이 뒤섞여있는 것이 아니기 때문에 실제 이미지를 자를 필요가 없다!
∘ 그래서 떠올린 것이 css grid로 10x10 그리드를 만들고, 서버에서 넘겨준 프로젝트 진행 %에 대응하여 grid를 이미지 뒤로 숨긴다는 아이디어였다. 즉, 퍼즐 조각 하나가 1%인 셈이다. 퍼즐 전체 개수에 따라서 퍼즐 하나의 크기 비율을 계산하는 것은 어렵지만 퍼센트는 계산하기 간단하기 때문에 문제가 더 쉬워졌다. 그렇다고 하더라도 마냥 간단한 것은 아니었다. 이미지를 자를 필요는 없었지만 업무 하나를 추가하거나 삭제할 때 전체 업무 개수가 달라지고, 그에 따라 새로 %를 계산해야했기 때문이다.
(진행도 20%)
(진행도 80%)
∘ 이번에는 아이디어대로 기능을 구현할 수 있었다. 프로젝트 동안 내가 작성한 백엔드 코드가 ajax 요청 후에 작동하는 것을 확인하는 것이 즐거웠다. first-project에서 프론트엔드를 맡으면서 CSS가 부족했는데 그 부분을 조금이나마 더 공부할 수 있어서 또 좋았다. 한편으로는 react의 단방향 데이터 플로우에 대해서는 더 많은 이해가 필요하겠다는 생각을 했다. SPA라는 이름에 더욱 걸맞게 새로고침 없이 렌더될 수 있을텐데. CSS로 퍼즐이 맞춰질 때 애니메이션도 적용하고 싶다. 모바일 대응까진 아니더라도 미디어 쿼리로 반응형도 구현하고 싶다. 기타 등등 개선의 여지가 많이 남아있다고 생각하며 리팩토링을 마무리 하였다.
∘ 나는 프론트엔드로서 작업을 하면서 프론트엔드에 대해 새로운 관심이 생겼다. 나는 final-project를 마무리할 당시까지만 해도 백엔드 개발자로서 구직을 하려고 계획했었다. 데이터를 다루고 저장하는 기능은 백엔드의 역할이고 그게 실제 기능을 구현하는 것이라고 (엄밀한 근거는 없이) 생각했기 때문이다. 하지만 리팩토링 과정 중에 역으로 API 서버를 실제 view에 구현하는 게 아주 매력적인 작업이라는 것을 알게 되었다.
∘ 코드스테이츠에서 기초적인 javascript 문법을 배우고, react, node.js 등을 차근차근 배우면서도 이것으로 뭘 만들 수 있는 걸까라는 질문을 항상 해왔었다. 전체 그림이 보이지 않았다. 하지만 파이널 프로젝트와 리팩토링을 하면서, 배운 것들을 어떻게 활용되는지 알 수 있었다.
∘ 또 한가지 느낀 점은 커뮤니케이션에 관한 점이다. 개발자는 협업을 해야하기 때문에 좋은 커뮤니케이션 능력을 함양해야 한다고 말로만 들었었는데, 실제 프로젝트를 진행하면서 알게된 점은, 그 말이 '커뮤니케이션은 어렵다' 는 것이다. 나의 생각이 팀원 분들에게 손쉽게 그리고 온전하게 전해지지 않고 그 반대도 마찬가지였다. "프론트엔드 분들이 더 활용하기 쉽게 API 문서를 어떻게 더 전달력있게 작성했으면 좋았을걸", "기획 단계에서 더 많이 고민을 했었으면 구현 단계에서 더 수월했을텐데"이라는 생각을 리팩토링을 진행하면서 계속 했었다. 커뮤니케이션은 어렵기 때문에, 내가 생각하는 것보다 훨씬 더 많은 공을 들여야한다는 것을 알았다. 또 git workflow나 네이밍컨벤션의 목적, 깔끔한 코드를 구사해야하는 이유 등에 대한 고민이 바로 그런 노력의 일환이라고 생각했다.
(프로젝트를 진행해나가면서 간략해진 기능 플로우, 처음 계획한 의도대로 일이 흘러가지 않았다)
∘ 프로젝트를 진행하면서 해결해야하는 문제에 맞딱뜨렸을 때 나는 항상 다음과 같이 생각하려고 애를 썼다
지금 이 문제를 해결하는 방법은 분명하게 있다. 어쩌면 단 몇줄의 코드만 치면 해결될 문제일 수도 있다. 그리고 그 단 몇줄의 솔루션을 찾는 과정은 분명 도전적이지만 그만큼 흥미롭기도 한 일이다!
∘ 이런 생각을 가지고 앞으로 꾸준히 발전해서 문제해결능력을 갖추고 같이 일하기도 좋은 개발자가 되고 싶다.
감사합니다.