KiCK OFF 프로젝트 회고

1. KiCK OFF

배포 링크 : http://kick-off.tech

 

시연 영상

 

편집이 허접하지만 이런 기능들이 있다 이정도로만 봐주세요.

 

어드민 시연 영상

 

 

1-1) 프로젝트 소개 및 선정이유

"KiCK OFF"라는 프로젝트는 축구를 즐겨보는 사람들이 서로 축구 관련 정보를 공유하고 해외 축구 경기 일정이나 경기 정보들을 얻을 수 있으며 실시간으로 사용자끼리 응원할 수 있는 서비스를 제공하는 커뮤니티 프로젝트이다.

 

이 프로젝트를 선정하게 된 이유는 매우 심플하다. 프로젝트 아이디어 선정 당시 어떤 도메인으로 프로젝트를 진행할지 생각하는 시간이 있었는데 나는 한 치의 고민도 없이 "축구"를 선택하였다. 내가 제일 잘 알고 가장 좋아하는 영역이었기 때문이다. 그런데 도메인을 빠르게 정한 것 치고는 축구라는 도메인으로 프로젝트 기획하는 게 순탄치만은 않았다.

 

처음에는 내가 평소에 축구 하이라이트 영상이나 경기 일정 및 순위 같은 것을 많이 찾아보는 편인데 이게 한 사이트에 정리되어 있는 곳이 없어 유튜브 가서 하이라이트 영상 보고 네이버에서 경기 일정이랑 순위 찾아보고 또 경기에 대한 정보는 다른 커뮤니티 사이트들을 보면서 찾아보는 번거로움이 있었다. 그래서 나는 이 정보들을 한곳에서 볼 수 있도록 기획 방향을 잡고 설레는 마음으로 종이에 직접 손으로 구상할 화면들을 그려보았다. (이때는 몰랐다. 디자인 툴을 사용해서 작업하는 게 더 편하다는 것을....)

 

이게 맨 처음 기획한 UI화면이다. (이게 화면이라고 할 수 있나...???)

 

하지만 이렇게 기획한 아이디어는 무산되었다. 내가 구현하려는 기능들이 매우 단순하다는 피드백을 받았기 때문이다. 단순히 데이터를 가져와서 보여주는 반복적인 작업이 될 것 같다는 피드백을 받고 새로 아이디어를 생각하기 시작했다. 중간에 축구 도메인이 아닌 실시간 중고 경매 서비스나 키노라이츠 같은 서비스를 기획했었는데 축구라는 도메인을 포기하지 못하고 3일간 고민한 끝에 지금의 "KiCK OFF"서비스가 탄생한 것이다.  

1-2) 개발 기간 

 약 2달 - 2022.10.15 ~ 2022.12.12

 

1-3) 주요 구현 기능 소개

축구 경기 일정 조회  기능

  • 오늘 날짜 기준으로 진행되는 경기들을 상단에서 확인할 수 있고 직접 경기 결과나 일정을 확인하고 싶은 날짜를 선택해서 해당 날짜 사이의 경기들의 정보를 확인할 수 있다.

 

 

양 팀 간의 전력 비교 및 실시간 응원 기능

  • 경기 일정화면에서 오늘 날짜 기준으로 진행될 경기의 "전력 비교" 버튼을 클릭 시 해당 매치 업의 경기 전력을 비교하는 정보와 함께 해당 페이지에 접속한 사용자끼리 실시간 채팅을 통해 응원할 수 있는 기능이다.

 

실시간 알림 기능

  • 자신이 작성한 게시글에 다른 사용자가 댓글을 작성할 시 실시간으로 댓글 알림을 받을 수 있는 기능이다.

 

관리자 계정으로 게시판 및 사용자 관리 기능

어드민 기능으로 할 수 있는 작업들은 아래와 같다.

 

  • 대쉬보드 페이지
    • 전체 멤버 수, 게시글 수, 등업 승인 대기자 수 확인
    • 일일 가입 멤버 수, 작성 게시글 및 댓글 수 확인
    • 최근 일주일간 날짜별로 게시글 및 댓글 작성 개수 확인 및 선그래프로 수치 비교 가능
    • 4대 리그 게시판 별 게시글 비중 확인 가능

 

  • 멤버 관리
    • 전체 멤버 조회, 아이디 검색 기능 
    • 선택한 멤버 등급 변경 및 강제 탈퇴 기능

 

  • 등업 신청 관리
    • 사용자가 신청한 등업 신청 수락 및 거절 

 

  • 게시판 관리
    • 게시판 생성 및 삭제 기능

 

  •  통계
    • 게시글 조회 수 순으로 확인

 

 

2. 프로젝트 기획 및 설계 단계

그 당시에는 몰랐지만 프로젝트가 끝나고 난 이 시점에서 프로젝트 진행 시 가장 중요하다고 느끼는 것 중 하나가 프로젝트 기획 및 설계 단계이다. 

2-1) UI 그리기 및 기능 리스트 업  

기획 단계에서 가장 처음에 한 일은 UI를 구상해보고 구현할 기능들을 리스트업 하는 것이었다. 어떤 화면을 어떻게 구상할 것인지 어떤 기능들을 구현할 것인지 그리고 나열해 봤다. 화면은 개발자가 아닌 일반인들도 이해가 갈 수 있도록 화면에 대한 설명도 적으면서 기획했다.

 

 

2-2) 프로세스 구조도 그리기

이후에 웹 프로세스 구조도를 그려보았다. 구조도는 위에서 작성한 UI와 리스트업 한 기능들을 바탕으로 UI를 어떻게 연결시킬지, 즉 어떤 버튼을 클릭했을 때 어떤 화면으로 이동하는지에 대한 플로우를 그려보는 작업이다. 

 

기획이 중간에 바뀌어서 플로우도 한번 수정을 해야 했었다. 수정을 하면서 프로세스를 그리는 작업에 대한 나의 생각도 바뀌었었는데 솔직히 처음에 그릴 때는 그냥 화면을 연결시키는 것에 집중했다면 수정을 할 때는 커뮤니티를 사용하는 사용자의 관점에서 그려보려고 노력을 했다. 특정 버튼을 클릭했을 때 화면을 이동시키는 것이 사용자의 입장에서 불편함이나 이질감을 느끼지는 않을까? 생각도 해보고 사용자가 이 서비스를 이용할 때 최대한 벗어나지 않고 오랫동안 이용할 수 있게 하기 위한 방법도 고민해 보았다.

이로 인해서 기존에 기획할 때 생각하지 못했던 기능들이 추가가 되는 효과를 얻을 수 있었다.  

 

좌 초기 프로세스 구조도 / 우 최종 프로세스 구조도

 

2-3) 사용자 스토리

다음으로 사용자 스토리를 작성했다. 사용자 스토리도 개발 중간에 한 번의 수정이 이루어졌다.

사용자 스토리를 처음 작성할 때 사용자 스토리를 제대로 고민을 하고 "사용자 가치" 중심적으로 작성해야 이후 개발 단계에서 사용자 스토리가 이정표가 될 수 있다는 것을 알지 못한 채 대충 작성했었다.

 

우선 처음에 작성한 사용자 스토리는 아래와 같다.

 

위 사용자 스토리에서 문제점은 기능을 사용하는 사용자가 구체적으로 명시되어 있지 않다는 것이다. "사용자는"이라고 되어있지 구체적인 사용자가 명시되어 있지 않아 발생한 문제는 사용자 가치 중심적으로 작성하지 못하게 했다. 

그냥 요구사항을 나열한 것이지 위 기능들을 사용함으로써 사용자에게 무슨 의미가 있는 건지, 어떤 가치를 얻을 수 있는지가 드러나있지 않다. 즉 사용자의 목적이 아닌 개발을 하는 나의 목적을 적고 있었다.

 

"사용자 가치" 중심적으로 작성해야 한다는 아샬 님의 피드백으로 나의 기능들을 사용하는 사용자가 정확히 누구인지 그리고 기능을 사용함으로써 얻을 수 있는 진정한 가치가 무엇인지에 대해 다시 고민하면서 사용자 스토리를 다시 작성했다.

 

위와 같이 작성한 사용자 스토리는 개발 단계에서 아주 큰 힘이 되었다. 가치 중심적으로 생각하다 보니 구현해야 할 기능들의 우선순위가 자연스럽게 정해지고 기존에 생각했던 기능들 중에서 필요 없는 기능들도 제거함으로써 개발 시간을 세이브할 수 있었다.

 

2-4 ) 인수 테스트 시나리오 작성

다음은 위에서 작성한 사용자 스토리를 바탕으로 인수 테스트 시나리오 작성이다. 개발 단계에서 구현한 기능을 사용자의 관점에서 테스트하기 위해 CodeceptJs로 인수 테스트를 진행하기 위해 시나리오를 작성하는 단계이다.

 

개발 단계에서 단위 테스트를 통해 각 기능들을 검증하지만 단위 테스트만으로는 시스템이 웹 브라우저에서 제대로 작동하는지 알 수가 없다. 그래서 사용자 스토리를 바탕으로 시나리오를 만들어서 개발 단계에서 기능이 하나 완성되면 인수 테스트를 통해 잘 작동하는지 검증하기 위해 인수 테스트 시나리오를 작성하였다.

 

 

 

2-5) 객체 설계

객체 설계는 아래와 같이 draw.io를 이용해 Entity의 관계를 그리면서 설계를 했었다.

왼쪽 사진은 맨 처음 설계했던 ERD이다. @OneToMany, @ManyToOne 어노테이션을 이용해 연관관계를 매핑할 계획이었지만 JPA의 n + 1 문제를 야기할 수 도 있다는 것을 알게 되어 오른쪽 ERD 사진처럼 특정 객체가 다른 객체를 참조해야 할 경우 해당 객체의 아이디값을 필드로 갖고 있도록 Entity 설계를 다시 했다.

 

 

이후 프로젝트 중반에 객체 설계가 잘못되었다는 것을 알게 되고 "객체지향의 사실과 오해" 책을 참조하며 객체지향적인 설계를 하는 방법을 공부했다. 우선 나의 관점부터 바꿔야 된다는 것을 알게 되었다. 객사오에서는 객체지향 설계의 첫 번째 목표를 훌륭한 협력을 설계하는 것이라고 강조하고 있었다. 그래서 나는 먼저 객체를 설계한다기 보다 협력을 설계하는 관점으로 바라보고 설계를 시작했다.

 

처음에는 협력을 설계한다는 것이 무슨 말인지 이해하기가 쉽지 않았지만 책을 따라 하면서 직접 프로젝트에 적용해보니까 아래 사진처럼 게시물을 작성하기 위해 객체들이 서로 메시지를 통해 협력하는 모습을 그려볼 수 있었다.

 

 

 

2-6) 스크럼 및 스프린트 회고

스크럼은 스크럼 마스터와 함께 매주 정해진 시간인 월요일 오후에 스프린트 회고를 진행을 했다.

진행 순서는 한 주 동안의 목표가 무엇이었는지와 함께 달성 여부를 체크하고 만일 달성하지 못했으면 회고를 진행했다. 그리고 한 주 동안 구현한 기능을 기획서를 함께 보면서 개발자의 관점이 아닌 일반인들도 이해할 수 있도록 화면과 함께 기능을 소개했다. 마지막으로 다음 스프린트동안에는 무엇을 할지 최소한의 MVP 목표를 세우고 목표를 성취하기 위해 구현해야 할 기능들을 리스트업 해서 각 기능마다 스토리 포인트를 매겨 다음 스프린트 동안의 할 작업들을 정의했다.

 

그리고 스프린트 회고가 끝나고 나서는 주간회고를 작성하면서 이번 스프린트에서 달성하지 못했던 작업들에 대해 구체적인 회고를 진행했다. 달성하지 못한 이유와 원인을 파악하고 다음 스프린트에는 동일한 문제로 목표 달성에 차질이 없도록 어떻게 하는 것이 좋을지 고민도 해보았다.

 

좌 4주 차 주간회고 / 우 6주 차 주간회고


3. 개발 단계

개발 단계에서는 기능들을 구현할 때 특별히 어려웠던 부분들에 대해서 적으려고 한다.

3-1) WebSocket을 이용한 채팅 기능 구현

이번 프로젝트를 하면서 기능 구현할 때 가장 오래 걸렸고 어려웠던 기능이 실시간 채팅 기능이다.

우선 채팅 기능을 구현하기 위해서 옛날의 채팅 방식인 http통신을 이용하여 구현하는 방법을 먼저 공부했었다.

서버에 요청을 일정한 주기로 보내 실시간으로 통신하는 것처럼 보이게 하는 방식인 polling과 long polling 방식을 공부했고, 이후에 webSocket을 이용해 실시간 1:1 채팅을 먼저 구현해 보았다.

 

구글 크롬 확장 프로그램인 WebSocketTestClient를 이용해 1:1 채팅을 테스트해보기도 했다.

 

하지만 서비스에서 요구하는 채팅 기능은 채팅방이 여러 개여야 한다는 것과 1:1 채팅이 아닌 1:N 다수와의 채팅이어야 한다는 점이 문제였다. WebSocket만을 이용해서 멀티 채팅방을 개설하려면 일일이 세션 관리를 해줘야 하는 어려움이 있었기 때문에 더 효율적인 방법을 위해 STOMP를 사용했다. pub/sub 패턴을 기반으로 동작하는 STOMP를 사용하면 WebSocket만 사용했을 때 별도로 메시지 송, 수신에 대한 규약을 정의해 줘야 하는 문제를 해결함으로써 멀티 채팅방을 구현할 수 있었다.

 

3-2) SSE 실시간 알림 기능 구현 

실시간 알림 기능을 구현할 때 실시간성을 보장하기 위해 채팅 기능을 구현할 때 사용했던 WebSocket을 이용하면 되겠다는 생각을 했었다.

그런데 WebSocket에 대해 공부하던 중 sse 통신 방법도 있다는 것을 알게 되었다.

WebSocket은 양방향 통신으로 서버와 클라이언트 간 데이터를 주고받을 수 있지만 sse는 단방향 통신으로 sse를 사용하면 클라이언트는 데이터를 받을 수만 있는 형태라는 것을 알게 되었다. 실시간 알림 같은 경우는 클라이언트가 서버로 데이터를 줘야 하는 상황이 없고 받기만(mono-directional) 해도 되기 때문에 sse방식이 더 효율적이라 판단을 해 sse 통신 방법을 추가로 공부하여 실시간 알림 기능을 구현하였다.

 

4. 데모데이

프로젝트의 마지막 날 데모데이를 진행했다.

데모데이를 처음 하다 보니 어떻게 진행해야 할지 방향을 잡는데 어려움을 느꼈었다. 데모데이를 진행하는 순서는 8주 동안 진행한 프로젝트에 대해 소개, 시연, 소감을 말하는 순서로 진행했는데 10분이라는 제한된 시간 안에 어디에 더 비중을 두는 게 발표를 하는 게 좋을지 고민을 많이 했다. 시연하는 시간보다는 프로젝트를 진행하면서 어려웠던 부분 해결방안 그리고 객체 설계 방법, 채팅 기능 구현 방법에 대해 비중을 두고 진행했다.

그 이유는 어떤 내용들을 주로 말하는 게 좋을지 생각하다 발표를 듣는 사람들이 궁금해할 만한 내용들을 말하는 것이 좋을 것 같다는 생각을 했다. 발표를 듣고 계신 분들은 트레이너님들도 계셨지만 주로 프로젝트를 이제 막 시작하는 2, 3 기분들이 많이 보고 계셨기 때문에 내가 프로젝트를 진행하면서 어려움을 겪었던 부분들과 궁금했었던 내용을 말하는 게 가치가 있을 것 같다고 생각했다.


프로젝트를 진행하면서 가장 어려웠던 부분이 채팅 기능을 구현하는 것이었고 채팅기능을 구현하려는 분들이 계셨기 때문에 채팅 기능을 구현하기 위해 공부한 순서나 

 

발표가 끝나고 스스로 생각했을 때 내가 무슨 말을 했지..?라는 느낌을 강하게 받았다. 다시 말해 횡설수설한 것 같았다. 특히 채팅 기능에 대해 말할 때는 채팅에 대한 배경지식이 없는 청중도 이해가 될 수 있도록 말을 했어야 했는데 다시 생각해보니 전혀 그러지 못했던 것 같다. 발표를 구성할 때 듣는 사람의 입장에서 생각을 한번 더 했어야 했는데 그 부분이 부족했던 것 같다.

 

그리고 트레이너님께 발표에 대해 받은 피드백으로 시연하는 시간이 더 길었으면 좋았다는 이야기를 들었다. 아무래도 데모데이다 보니까 자신이 만든 프로젝트를 보여주는 느낌이 강해야 했는데 그 부분을 미처 생각하지 못했다...

 

5. 아쉬웠던 점

사실 이번 프로젝트는 아쉬움이 가득한 프로젝트이다. 코드 구조에 대한 아쉬움도 있지만 코드 외적인 부분에서 아쉬움이 많이 남는다. 

5-1) 기획 및 작업 설계

특히 기획과 작업 설계 단계에서 코드를 작성한다고 신경 쓰지 못한 부분이 많았다. 처음 기획단계에서 잘못 기획한 것 때문에 개발 중간에 하던 것을 멈추고 기획과 설계를 다시 수정해야 했던 적이 있었다. 잘못된 사용자 스토리를 수정함으로써 인수 테스트 수정 및 객체 설계를 다시 하면서 발목을 잡았었다.

그리고 작업 설계도 미리 잘 설계된 문서를 바탕으로 고민 없이 코드만 칠 수 있도록 구체적으로 설계했어야 했는데 그러지 못했다. 코드를 치면서 개발하는 도중에 생각하는 시간이 길었다. 이로 인해 잘못된 코드를 작성해서 리팩터링 하는데 시간을 많이 쓴 적이 있다.

 

잘 작성된 기획 문서와 작업 설계는 개발 단계에서 어떻게 개발을 해야 할지 방향을 잡아주는 이정표로써 고민하는 시간을 아낄 수 있는 가장 큰 무기가 될 수 있다는 것을 배웠다. 

5-2) 기록에 대한 아쉬움

그리고 많은 것을 기록하지 못해 아쉬웠다. 

기록에 대해서는 프로젝트 중간에 트레이너님께 피드백을 받은 부분이기도 하다. 프로젝트를 진행하면서 작업 내용, 배운 점, 느낀 점들을 기록하는 게 좋다는 피드백을 받고 최대한 Notion이나 구글 문서를 통해 기록을 진행했다. 

 

실제로 프로젝트 5주 차 이후 동료가 기록하는 방식인 구글 문서를 통해 더 구체적으로 기록하려고 노력한 흔적들이다.

하지만 프로젝트 끝난 시점에서 다시 봤을 때 이 기록들 또한 아쉽다는 생각이 든다. 동료 한 분 중 1 뽀모도로 단위로 회고하는 동료분이 게신데 나도 몇 번 따라서해 본 적이 있다. 그리고 지금 와서 그 기록들을 보면 그 당시 기억이 떠오르기도 한다. 하지만 기록하는 습관이 잡혀있지 않다 보니 이 기록방법이 오래가지는 못했다. 계속 이어나갔으면 어땠을까 하는 후회를 한다.

 

기록한 흔적이 처참해서(중간중간 빼먹은 게..) 블로그에 올릴까 고민을 했는데 이것 또한 기록이라 생각하고 흔적을 남긴다.

 

6. 느낀 점

6-1) 개발자는 코드만 치는 직업이 아니다.

첫 번째로 느낀 점은 개발단계에서 코드를 작성해서 기능을 구현하는 것만이 개발하는 것이 아니라는 것과 개발자라는 직업이 코드만 잘 치면 되는 직업이 아니라는 것을 몸소 느꼈다.

그리고 위의 아쉬운 점에서도 적었지만 기록이 습관화되어야 한다. 사람은 완벽하지 못하기 때문에 모든 것을 기억할 수 없기 때문에 개발하면서 사소한 것 하나까지 모두 기록을 해야 한다는 것을 깨달았다.

 

프로젝트 이전에는 개발자는 코드만 잘 작성하면 되는 거 아니야?라는 안일한 생각을 했던 적이 있다. 하지만 프로젝트를 직접 해보니 코드를 잘 작성하는 것은 필수불가결한 존재이고 더 좋은 개발자가 되기 위해서는 잘 기록하는 습관과 문서화하는 능력이 중요하다는 것을 느꼈다.

 

6-2) 사용자가 얻을 수 있는 가치를 생각하자.

그리고 사용자의 관점에서 생각하는 것이 중요하다는 것을 느꼈다. 서비스를 사용하는 사용자가 얻을 수 있는 가치가 무엇인지 끊임없이 고민을 해야 한다. 프로젝트를 진행하다 보면 사용자의 관점으로 생각하는 것이 아닌 서비스를 만드는 "나"의 관점에서 생각하게 되는 경우가 많은데 이는 사용자가 서비스를 사용하는 목적에 맞지 않는 기능이 만들어질 수 있다는 것을 알게 되었다.

서비스를 사용하는 사용자의 목적과 서비스를 개발하는 나의 목적과 혼동하면 안 된다는 것을 배웠다. 이는 사용자 스토리를 작성하는 단계를 대충 작성해버리면 안 된다는 것을 느꼈습니다. 


7. 마무리

마지막으로 약 2달간의 프로젝트를 하면서 힘들기도 했고 아쉬운 점도 많이 있긴 했지만 재밌었다는 감정이 더 크다.

개발자를 시작하게 된 계기도 내가 생각한 아이디어를 내가 직접 구현할 수 있다는 점에서 매우 매력을 느껴 개발자라는 직업이 하고 싶었었다. 그리고 이번 프로젝트가 내가 개발자가 되고 싶었던 이유를 증명하는 프로젝트였기에 더욱 뿌듯하다. 진짜로 내가 머릿속으로만 상상하던 것들이 실체로 나타나서 만들어졌다는 게 무에서 유를 창조한다는 느낌으로 다가왔었다.

 

혼자서 기획 / 설계 / 프론트엔드 / 백엔드를 관리하고 만들다 보니 많은 것을 배울 수 있었던 나의 첫 프로젝트였다. 

 

+ 다음 프로젝트에는 이렇게 할 거다!

기획 및 설계 등한시하지 않기 

기록 꼼꼼히 하기 

Value Object 적극 활용하기