Project/Meal-To-Meal

Meal To Meal 프로젝트 회고

노프Nope 2021. 12. 30. 00:43

https://user-images.githubusercontent.com/83822798/147181108-e17903b3-8c7a-4878-88a6-9d79113dd641.png

프로젝트 소개

아이디어가 프로젝트의 반이다

퍼스트 프로젝트 아이디어를 준비할 때부터, 즉 파이널 프로젝트 시작하기 한 달 전부터 주 1회 회의를 3주 정도 했다. 그 과정에서 정말 온갖 분야의 아이디어가 나왔고, 이를 노션에 정리하면서 가지치기를 해나갔다.

일단 아무리 괜찮아보이는 아이디어라도 비슷한 서비스가 존재한다면 아쉽지만 제외했다. 이 과정에서 대부분의 아이디어가 제외됐다. 두 번째로 구현에 대한 그림이 잘 안 그려지거나, 현재 우리의 수준에 맞지 않는 너무 어려운 기획도 제외했다. 셋째로 기획에 품이 많이 드는(공부가 많이 필요한) 아이디어도 제외했다. 나는 퍼스트 때부터 학습 관리 툴을 만들고 싶었는데, 내 기획 역량이 부족해서 기능 구체화를 하기가 어려웠다. 공부해서 구현하기에는 시간이 부족했기 때문에 팀원들을 설득하는 데 실패했고, 이 과정에서 나 스스로도 자연스레 포기하게 되었다.

사실 이렇게 많은 아이디어를 제외하고나니 우리에게 더는 남은 총알이 없었다. 그렇다고 미워도 다시 한 번, 제외한 아이들을 보고 있자니... 100퍼센트 마음에 들지 않은 기획으로 프로젝트를 시작해도 될까? 하는 의구심에 사로잡혔다. 이때부터 나는 주변의 친구들에게 미친듯이 조언을 구하기 시작했고, 최대한 많은 사람들을 만나 전혀 다른 분야의 이야기를 들으며 기존에 넘쳐나는 토이 프로젝트가 아닌 새로운 무언가를 찾아보려고 애썼다. 이때부터는 거의 시간과 에너지의 싸움이었던 것 같다. (물론 그 와중에도 퍼스트 프로젝트는 진행되고 있었다....)

내가 해결하고 싶은 문제에서 시작한 프로젝트

어느 날, 나는 저녁을 먹고 엄마와 한가롭게 수다를 떨고 있었다. 엄마가 꺼낸 이야기는 다음과 같았다.

“오늘 이상한 일이 있었는데 말야. 가게에 어떤 젊은 여자가 왔거든. 안색이 아주 창백해가지고. 나이는 너랑 비슷하거나 조금 더 많아보였는데, 아무튼 네 또래였어. 근데 아무것도 안 들고 계산대 앞에 와서 갑자기 그러는 거야. 정말 죄송한데, 너무너무 배가 고파서 그러는데, 우유 하나만 사주실 수 있냐고.”

엄마는 아무것도 묻지 않고 우유와 삼각김밥을 사주었다고 했다. 그 이야기는 그날 밤 잠들기 전, 다음날 아침, 그리고 그 이후에도 나를 계속 따라다녔다.

그날부터 나는 팀원들을 설득하기 시작했고, 내 설득의 주요 포인트 중 하나는 “누구나” 인증 과정 없이 한 끼를 먹을 수 있었으면 좋겠다는 것이었다. 기술적으로도, 철학적으로도, 그게 나았기 때문에 합의가 됐다. 그렇게 우리 서비스는 하루에 한 번, 리뷰 작성 필수라는 약간의 제약 조건과 함께 누구나 먹기 서비스를 이용할 수 있게 되었다.

나는 정말 서비스를 출시할 것처럼 열심히 했다. 새벽 2~3시까지는 기본이었고, 어떤 때에는 퇴근하고나서 잠깐만 더 볼까? 하다가 5~6시가 되어서야 잠들곤 했다. 그렇게 할 수 있었던 이유는 내가 해결하고 싶은 문제의 이미지가 너무 선명했기 때문이었다. 어느 정도 운이 따라주었기 때문에 가능했던 일이기에, 앞으로도 이렇게 목숨걸고 할 프로젝트가 있을까 싶긴 하다. 그렇지만 앞으로도 내가 정말 해결하고자 하는 문제에서부터 시작하려 애쓸 것이라는 점은 확실하다. 프로젝트를 해야하기 때문에 아이디어를 찾아야하는 상황이더라도, 조금이라도 내게 와닿는 문제를 발견하고자 분투할 것이다. 문제 의식의 깊이가 다르면 결과물도 다르다는 걸 체험했기 때문이다.

기술적인 도전 보다는 완성도를

우리 팀은 기획 단계에서 구상한 최소 기능(기부, 예약/먹기, 가게 관련 crud)이 명확했기 때문에, 기술 스택을 정하는 데 있어 다소 보수적으로 접근했던 것 같다. 다른 팀에서 많이 쓰는 타입스크립트, 리덕스 등을 도입하지 않고 최소한의 기술 스택만 사용했던 것은 우리가 구현해야 할 기능이 꽤 많아보였기 때문이었다(그리고 실제로 해보니 정말 많았다). 기술적 도전이냐, 완성도냐의 문제는 많은 것이 그렇듯 trade-off 관계에 있다. 시간 관계상 docker를 추가하거나 서버 로깅을 제대로 하지 못한 것 등등 아쉬움이 남는 부분이 많지만, 결과적으로 완성도를 우선시했기 때문에 후회는 없다. 우리가 ‘완성도’를 추구했다고 말할 때에는 마감에 맞춰 기능을 구현했다는 의미가 있고, 이것만으로도 소중한 경험이라고 생각한다.

기능이 많았기 때문에 더욱 더, 2~3개의 70%짜리 기능보다 하나의 100%짜리 기능이 낫다는 이야기를 마음에 새기려 노력했다. 그래서 마지막에 구글 소셜 로그인이나, 랭킹 시스템 같은 기능을 과감히 제외했다. 그것들에 집착했다면 마지막에 사장님 가게 페이지 수정과 삭제 부분에서 에러 핸들링을 하다가 일정을 못 맞췄을 게 뻔하다. 기술 부채도 자산이라면 우리는 이제 어엿한 자산가가 됐다... 이제부터 하나씩 갚아나가보려고 한다.

팀워크를 위한 시도: 따로 또 같이

우리는 퍼스트 프로젝트를 시작하기 전부터 함께 스터디를 해와서 어느 정도 친분이 있었다. 덕분에 분위기만큼은 어느 팀보다 좋았을 거라고 자신한다. 하지만 프로젝트가 진행될수록 너무 쉽게 도움을 요청하는 분위기가 오히려 팀의 효율에 방해가 된다고 느꼈다. 그래서 2주차 KPT회고 때 팀원들과 회의해서 ‘찬스’ 제도를 도입했다. 찬스란 하루에 한 번 모든 팀원을 소집해 함께 디버깅을 요청할 수 있는 기회다. 각 찬스당 시간 제한은 1시간이다. 찬스 사용은 밤 10시 전까지만 신청할 수 있다.

https://user-images.githubusercontent.com/73627443/151695592-43b87981-71d9-4e2a-945d-a62d26e37a9b.png

이 제도를 제안할 때까지만 해도 나는 도움을 주로 청하는 입장이 아니었지만, 공교롭게도 찬스를 도입한 후에는 나도 꽤 자주 사용했다. 취지는 도움을 청할 기회를 제한함으로써 최대한 혼자 힘으로 문제를 해결하려고 노력해보고, 안 된다면 문제를 사전에 잘 정리하고 설명해서 다른 사람의 시간을 아끼자는 거였다. 찬스가 반드시 문제를 해결해주지 못하더라도, 팀원들에게 설명하면서 문제를 새롭게 본다는 측면에서 도움이 되었다. 물론 모든 규칙이 그렇듯 완벽하게 지켜지지는 못했지만, 한 명 한 명이 더 자주성과 책임감을 가지고 프로젝트에 임하게 된 계기가 된 것 같았다.

아쉬움도 있다. 어느 날 새벽까지 프론트쪽 에러를 열심히 함께 디버깅하고 퇴근하고 뿌듯한 마음으로 데브로그를 쓰려다가 다른 팀원의 데브로그를 읽었는데, 거기에는 “며칠간 고민한 문제를 팀원의 도움을 받아 해결했다. 혼자 끝내지 못해 아쉽다”고 적혀 있었다. 나는 왜 문제가 문제가 해결되었으니 당연히 기쁠 거라고 짐작했을까? 그 글을 읽고 ‘어떻게 해야 도움을 주는 사람도, 받는 사람도 함께 성장할 수 있을까?’에 대해 고민하게 됐다.

사람마다 더 나은 퍼포먼스를 낼 수 있는 방법은 다르다. 그 다름을 파악하고 끌어올려주는 것도 좋은 팀원의 역할 중 하나일 것이다. 프로젝트 마감일이 다가올수록 더 목표지향적이 되어서 다른 사람들의 기분을 생각하지 못하고 행동한 게 아닌지, 친하다는 이유로 칭찬에 인색하고 지적만 많이 한 게 아닌지... 반성한다.

어려웠던 점

프로젝트하면서 어려웠던 점이 정말 많았지만, 할 말이 많은 것 위주로 정리해보자면 다음과 같다.

  1. RESTful API
  2. 처음에는 RESTful하다는 게 뭔지 잘 몰라서 그냥 엔드포인트에 동사를 넣지 말고, 척추(하이픈) 케이스를 사용하고, 등등 하나하나의 규칙에 집중했다. 그런데 중간 정도 짜다보니 뭔가 이상했다. 리소스가 아니라 view를 중심으로 설계하고 있던 거였다. 와이어프레임을 보면서 클라이언트 측에서 필요한 정보를 서버에서 다 넘겨주는 방식으로 짜다보니 하나의 요청에 담아주어야 하는 데이터가 너무 많았다. 그래서 다 뒤집고 다시 리소스를 중심으로 그 리소스에 대한 crud를 http method로 구현한다는 개념을 가지고 설계했다. 어느 정도 큰 방향성은 맞지 않았나 싶지만, 사실 지금도 부족한 부분이 너무 많다. rest api에 대해 더 공부하고 싶다.
  3. aws s3 버킷에 이미지 업로드TypeError: Cannot set property name of #<File> which has only a getter
    mdn을 보니 setter를 새로 정의해서 바꿔줘야한다고 해서 따라해보았는데, 생각보다 쉽지 않았다. getter와 setter에 대한 이해가 부족해서 코드를 적용하기가 어려웠다(그리고 새벽 3시쯤이라 이미 너무 지쳐있었다....). 고민하다가 결국 newName이라는 새로운 프로퍼티를 만들어 uuid와 파일 확장자만 조합해 file 객체에 새로 할당해주었다. 그리고 모듈 내부에서 기존에 name을 사용하던 부분을 전부 newName으로 대체했다.정석적인 방법은 아니겠지만, 모듈을 직접 변경한 것은 처음이었기 때문에 이렇게도 할 수 있구나! 라는 면에서 도전적인 경험이었다.
  4. file.newName = `${uuid()}.${file.type.split('/')[1]}`
  5. 일단 어떤 모듈을 사용해야할지 몰랐다. 처음엔 aws-sdk를 썼는데 팀원들이 이걸로 해보다가 어렵다고 포기 직전까지 갔었다. 그래서 내가 아예 코드 베이스를 모르는 상태에서 투입이 됐는데 구글링을 해보니 react-s3가 사용이 쉬워보여서 이걸로 모듈부터 바꿔봤다. 업로드를 시도하니 400에러와 함께 accessControlListNotSupported 라는 메시지가 떴다. 버킷 cors 설정을 구글링해서 따라했는데도 해결이 안 됐다. 버킷 권한 설정 페이지를 보다가 acl 설정이라는 게 있어서 그걸 활성화했다. 근데 경고가 뜨면서 권장하지 않는다고 했다. 일단 시도해보자 싶어서 했는데, 보안에 구멍이 뚫리는 게 아닌지 걱정됐다.
    나중에 우아한형제들 기술 블로그 포스팅을 보니 이미지 같은 정적 리소스 파일 서빙용 버킷이라면 cloudfront 설정에서 oai라는 옵션을 넣어주면 버킷에 대한 액세스를 cloudfront를 통해서만 하게끔 제한할 수 있다는 걸 알았다. 이를 적용해서 보안을 강화해보려고 한다(그리고 이 포스팅의 내용을 더 이해하고 싶다!).
    일단 업로드는 성공했는데, 문제가 더 있었다. 같은 파일 이름을 가진 이미지를 업로드 할 때 충돌이 나지 않게 하려면 고유한 키값을 부여해줘야 했던 거다. 하지만 이 모듈에서는 내부적으로 이미 디렉토리 이름과 파일명을 조합해 키를 설정해두었다. 그래서 파일 네임에 바로 uuid를 넣어서 할당하려고하니, 하나의 getter만 갖고 있어서 속성을 바꿀 수 없다는 에러가 떴다.
  6. 네트워크 탭에 뜨는 비밀번호얼마 후 SNS에서 개발자들이 이 주제로 토론하고 있는 걸 발견했다. 궁금했던 부분이라 흥미롭게 여러 스레드를 옮겨다니며 읽어보니, https라면 암호화되어 있기 때문에 괜찮다는 내용이 지배적이었다. 역시 그렇구나! 라고 하기에는... 그럼 왜 대형 포털에서는 암호화를 했을까? 라는 궁금증이 남았다.
  7. 얼마 전 eng 인턴십 면접이 끝나고, 면접관이 나에게 궁금한 것을 아무거나 물어보라고 하였고, 이때다 싶어 이 질문을 던졌다. 사실 처음 듣는 기술 용어가 많이 등장해서 대략 느낌만 이해한 것 같다. 결론은 https로 하면 암호화가 되기 때문에 평문으로 서버에 전송해도 안전한 게 맞았다. 대형 포털에서 전처리 과정을 거치는 이유는 보안을 강화하기 위한 목적이 맞지만, 이것을 오버 엔지니어링으로 볼 수도 있다고 하셨다. 그렇게 하는 이유와 장단점은 차차 내가 공부해나가야 할 영역이겠지.
  8. 로그인 시 아이디, 비밀번호가 네트워크 탭에서 평문으로 조회되는 것을 발견했다. 구글링해보니 https로만 전송하면 문제가 없다는 이야기가 나왔다. 진짜일까 싶어 네이버, 다음, 쿠팡에서 테스트 해봤다. 네이버와 다음에서는 네트워크 탭에 아이디만 조회되고 비밀번호는 빈 문자열이거나 암호화가 되어있었던 반면, 쿠팡에서는 평문으로 전송되어 확인이 가능했다. 더 이상 디깅할 시간도 없었고, 쿠팡에서 할 정도면 문제가 없겠거니 싶어서 우리도 그냥 평문 전송을 했다(^^;) 하지만 왜 네이버와 다음에서는 암호화를 하거나 가렸는지, 혹시 네트워크 탭을 켜놓고 로그인 한 다음 자리를 비웠을 때 누군가 비밀번호를 볼 가능성 같은 것까지 염두에 둔 것인지 궁금했다.

앞으로의 과제

- 서버 로그 추가
- twilio 보안 강화
- aws 버킷 보안 강화
- 소셜 로그인 검증, 종류 추가
- mvc 패턴
- 모바일 결제 추가
- 테스트 코드 추가
- 기부 시드 추가
- 트랜잭션 검증

더 테스트하고 보완해야할 부분을 대략적으로 정리해보니 이만큼이나 된다. 추가적으로 발견될 에러까지 핸들링하고, 좀 더 욕심내서 기능도 추가해본다면, 부지런히 잔디를 심어야할 것 같다. 정말 다행인 건, 직장이 생겨서 한동안 구직(돈) 걱정 없이 공부 + 코딩을 할 수 있다는 거! 행복하다!

매일 조금씩 더 나은 내가 되어야지. meal-to-meal 프로젝트는 계속 발전할 거다. 고생한 우리 팀원들에게 정말 감사하고, 프로젝트를 할 수 있는 발판이 되어준 코드스테이츠에도 감사하다.