TodoList 프로젝트 회고

2023. 7. 22. 14:42회고

개요

2주간의 TodoList 프로젝트를 마치고 회고를 하고자 글을 쓰게 되었습니다. 회고의 내용으로는 2주 동안 프로젝트를 하면서 좋았던점, 아쉬웠던 점, 개선할점, 다음에도 유지할 점과 같은 느낀점을 작성하였습니다. 프로젝트에 대한 구성은 다음과 같았습니다.

 

프로젝트 기간 : 2023-07-10 ~ 2023-07-21 (2주)

팀원 : 백엔드 4명, 프론트 엔드 2명 (6명)

주제 : 해야할 일, 하고 있는 일, 완료한 일과 같은 컬럼들과 각각의 제목과 내용을 담은 카드를 저장하여 사용자에게 TodoList 서비스를 제공합니다.

 

 

1. 좋았던 점

1.1 스프린트(Sprint)를 통한 일주일 계획 작성하기

스프린트(Sprint)는 팀이 일정량의 작업을 완료하는 시간이 정해진 짧은 기간을 말합니다. 저와 팀원들은 2주동안 두번의 스프린트를 계획하였습니다. 매주 월요일마다 스프린트를 계획하였고 첫번째 월요일에서는 스프린트 상관없이 2주동안 팀이 TodoList 서비스를 제공하기 위해 필요한 기능, 인프라(배포 환경) 등을 작성하였습니다. 그리고 나서 첫번째 1주동안 구현해야할 기능들을 계획하고 나머지 기능들을 2주차에 구현을 하기로 계획하였습니다.

2주차 스프린트에서는 1주차 스프린트 동안 기능을 구현하면서 추가적으로 필요한 기능이나 문제점, 다하지 못한 기능들을 생각하면서 계획했던 주차였습니다. 예를 들어 컬럼의 API 구현, 동시성 문제, Nginx를 설치를 통한 리버스 프록시 제공, 코드 개선 등이 있었습니다.

 

스프린트를 계획하면서 좋았던 점은 일주일 동안 구현해야 할 기능들을 목록화하였기 때문에 그 기능들을 구현하는데 집중할 수 있었다는 점이었습니다. 저희 팀 같은 경우 스프린트를 작성하고 스프린트를 기반으로 이슈를 작성하였는데 Github의 이슈에는 해당 이슈를 해결할 담당자(Assignees)를 설정할 수 있습니다. 그리고 담당자를 기준으로 이슈를 필터링하여 내가 구현해야할 기능들을 한눈에 파악하고 해결에 집중할 수 있습니다.

 

1.2 마감 기한전 배포 환경에서 기능 테스트

프로젝트의 작업 기간 중 마지막 날인 21일(금)은 마감 기한이자 저희가 지금까지 했던 서비스를 시연하는 날이기도 했습니다. 이전까지는 기한 하루전에 배포 환경에서 기능이 잘되는지 테스트하였습니다. 하지만 마스터의 조언으로 기한 하루전에 급하게 배포 환경에서 기능 테스트를 하지말고 최소 2~3일전(화, 수), 저번주 금요일 정도에 한번씩 테스트 해보라고 조언하였습니다. 마스터의 조언대로 이틀전인 수요일날 배포 환경에서 테스트하였는데 생각보다 명세서에 적혀져있는 프로퍼티명과 다르게 요청하고 응답받는 것을 확인하였습니다. 그래서 대부분의 기능들(예를 들어 10개의 기능들이라면 6~7개 정도)이 완벽하게 동작하지 않았습니다. (원인은 단순한 오타 정도로써 변수의 이름을 제대로 클라이언트와 서버 간에 맞추면 금방 해결할 수 있는 것들이었습니다.)

 

또한 배포 환경에서 시간을 제어하는 부분에서도 문제가 있었습니다. TodoList 서비스하는 기능들 중 사용자의 카드 조작(등록, 삭제, 수정, 이동) 활동 기록을 조회하는 기능이 있습니다. 이때 조회하는 기능에서 사용자는 특정 활동이 발생하고 어느 정도 시간이 경과되었는지 확인하는 것이 있었습니다.

사용자가 das 카드를 삭제한지 25분이 경과되었습니다.

하지만 이 경과 시간은 배포 환경에서 운영되고 있는 MySQL 데이터베이스의 시간을 따릅니다. 그래서 MySQL 데이터베이스의 타임존이 UTC인 경우 9시간 25분전으로 출력될 것입니다. 배포 환경에서 이를 확인하고 배포 환경의 데이터베이스 타임존을 UTC -> Asia/Seoul로 변경했던 적이 있습니다.

 

위와 같이 로컬 개발 환경과 배포 환경에서 제공하는 TodoList 서비스간에 설정이 다르기 때문에 로컬 개발 환경에서 실행하는 서비스 기능이 배포 환경에서는 동일하게 제공할 거라는 보장이 없다는 것을 알 수 있는 사건이었습니다. 이러한 문제가 발생하는 것을 예방하기 위해서는 주기적으로 배포 환경에서 문제가 없는지 테스트하는 것이 중요하다고 생각하였습니다.

 

1.3 팀원들과의 코드 구현, 어쩔 수 없는 코드 충돌

백엔드 팀원은 저 포함해서 4명입니다. TodoList 서비스에서 구현해야할 기능은 상대적으로 적었기 때문에 코드 충돌이 있을 수 밖에 없었습니다. 저번 프로젝트에서 개발 과정중 코드 충돌을 해결하는데 많은 시간을 소비하였기 때문에 이번 프로젝트에서는 코드 충돌을 줄이기 위해서 프로젝트를 어느정도 초기화하는 작업을 수행하였습니다. 예를 들어 특정 도메인의 엔티티 객체, 서비스, 컨트롤러, Repository와 같은 객체를 미리 만들어두고 도메인의 엔티티 객체는 필드 멤버를 정해두고 개발하였습니다. 프로젝트를 초기화하여 어느 정도 초기화를 하니 코드 충돌 횟수가 저번 프로젝트보다 훨씬 줄은 것을 체감할 수 있었습니다.

 

하지만 어쩔 수 없는 코드 충돌은 발생할 수 밖에 없었습니다. 같은 CardService 객체에서 메소드 추가로 인한 코드 충돌, 테스트 클래스에서 추가한 테스트로 인한 코드 충돌 등이 대표적이었습니다. 그래도 코드 충돌을 보다 쉽게 해결할 수 있었던 점은 개발 브랜치인 be 브랜치를 기준으로 비교하여 코드 충돌을 해결하였다는 점입니다. 팀원들이 개발한 소스 코드를 완성하면 be 브랜치에 PR(Pull Request)를 날려서 합치고 다른 팀원들이 be 브랜치에 PR을 날릴때 코드 충돌이 발생합니다. 이럴때 Github는 친절하게도 코드 충돌이 적게 난다면 웹 에디터를 통하여 코드 충돌을 해결할 수 있게 도와준다는 점입니다.

이 코드 충돌은 예시입니다.

위 그림과 같이 master 브랜치와 add-emoji 브랜치간에 코드를 비교하여 "======"를 기준으로 코드를 수정할 수 있습니다. 대개의 코드 충돌은 어느 한쪽 브랜치의 코드를 선택하고 다른 브랜치의 소스 코드를 제거하거나, 아니면 두 브랜치의 소스코드를 합치는 방향으로 코드 충돌을 해결한것 같습니다.

 

하지만 코드 충돌이 많은 경우에는 인텔리제이와 같은 IDE 편집기에서 코드 충돌을 해결할 수 있습니다. 이때는 PR하고자 하는 브랜치에서 PR 대상의 브랜치를 pull하여 코드 충돌을 발생하게 하고 코드 충돌을 해결할 수 있습니다.

 

위와 같이 왼쪽 브랜치의 코드 전부와 오른쪽 브랜치의 코드 전부 중에 한쪽을 전부 수락 할 수도 있고 ">>" 버튼을 클릭하여 일부 수락하여 가운데의 최종 완성된 코드로 만들 수 있습니다. 만약 이런 방식으로 보기 싫고 웹 에디터에서처럼 "===="를 기준으로 보고 싶다면 이전에 코드 충돌이 발생했다는 창에서 닫기 버튼을 클릭하면 직접 편집할 수 있습니다.

화면에서 Close를 클릭하면 직접 코드 충돌을 해결할 수 있습니다.

프로젝트를 하면서 코드 충돌난 점이 좋았던 점으로 분류한 이유는 이번 프로젝트를 하는 동안 코드 충돌을 해결하는 경험이 그렇게 불쾌하고 어렵지 않고, 귀찮지만 해볼만 한데? 라는 감정이 들었기 때문에 좋았던 점으로 분류했던 것 같습니다. 그리고 코드 충돌을 이렇게 해보면서 코드 충돌난 것이 그렇게 무서워지지 않고 도움이 되었단 점도 한 몫 한것 같았습니다.

 

2. 아쉬웠던 점

2.1 드래그 앤 드롭과 카드 이동

프론트 엔드 팀원들에게 이번 프로젝트에서 가장 어려운 기능이 드래그 앤 드롭 기능이 아니웠나 싶었습니다. 그리고 백엔드 팀원들에게 가장 어려웠던 주제는 카드 이동 기능인 것 같았습니다. 카드 이동 기능에서 서버가 제공해야 하는 가장 중요한 점 중 하나는 순서인것 같습니다. 카드를 같은 컬럼 내에서의 이동, 다른 칼럼으로의 이동같이 여러가지 케이스로 고려해야 하는 부분이 있었고, 카드를 최상단, 최하단으로 이동하는 경우도 고려해야 했습니다. 그중에서 가장 생각해야 했던 것은 하나의 카드가 이동시 어떤 방법으로 순서를 유지해야 할지 고민하는 것이었습니다. 단순히 카드를 이동하고 해당 컬럼 내에서 정렬하는 방법이 있을 수 있고 연결 리스트와 같은 자료구조를 선택하여 데이터베이스 내에서 여러번의 쿼리를 날려서 연결 리스트와 같이 유지시킬 수 있습니다. 저희 팀이 선택한 방법은 각각의 카드가 position이라는 값을 가지고 카드 이동시 상단 카드와 하단 카드의 위치 합계의 절반을 해당 카드의 이동된 position값으로 계산하는 것이었습니다. 이러한 방법의 경우 카드를 계속 이동하다보면 상단 카드와 하단 카드간에 간격이 1보다 작게 될 것입니다. 이러한 경우 1024의 배수로 재정렬하는 방법을 취하였습니다.

 

프론트 엔드 팀원들은 며칠을 소비하여 드래그 앤 드롭 기능을 기한 하루전에 완성은 하였지만 카드 이동시 리퀘스트 요청이 이상하게 요청되어 카드 이동이 불안정하게 수행되어 결국 시연에는 선보이지는 않았습니다. 드래그 앤 드롭 기능은 완성하였지만 이러한 불안정한 리퀘스트 요청을 고칠 시간이 부족한 점이 아쉬웠던 점 중 하나로 선택하였습니다.

 

2.2 컬럼 추가/수정/삭제

컬럼 추가/수정/삭제와 같은 API 구현은 저의 이슈였습니다. 구현은 스프린트 2주차때 구현을 하였고 월~화요일 2틀간 소비하여 구현을 완료하였습니다. 하지만 프론트 엔드 팀원분들이 드래그 앤 드롭 기능 구현에 생각보다 시간을 많이 쓰게 되어 프로젝트의 선택 기능이었던 컬럼 API는 백엔드 서버에만 구현되었고 UI 부분에서는 구현되지 않아서 시연에서는 선보이지 않았습니다. 그래서 시간이 부족하여 기능을 선보이지 못한점이 아쉬운 점으로 선택하였습니다.

 

2.3 포스트맨 API의 부족한 예제 작성

API 명세서 작성 도구로 포스트맨을 사용하게 되었습니다. 포스트맨은 목서버를 생성하고 목서버를 이용하여 예제를 작성하여 특정 URL에 대한 정해진 결과를 반환할 수 있는 좋은 기능을 제공하고 있습니다. 그중에서 아쉬웠던 점은 카드 이동 API에서 다양한 케이스의 카드 이동 예제를 작성하지 않아서 프론트 엔드 분들이 드래그 엔 드롭 기능 테스트에서 놓쳤다는 점이 아쉬웠습니다. 다음에는 좀더 다양한 케이스로 예제를 작성하도록 생각하였습니다.

 

3. 개선할점

3.1 로그인 기능을 통한 동시성 문제 해결

프로젝트의 기한 2주이기 때문에 시간 문제로 월요일 회의때 로그인 기능은 넣지 않기로 하였습니다. 그로 인해서 2주차때 발생한 문제는 여러 사용자들이 하나의 웹 애플리케이션을 사용하기 때문에 여러 사용자들이 한명의 사용자처럼 카드를 조작합니다. 이때 잘못하면 동시성 문제가 발생할 수 있습니다. 그래서 만약에 TodoList 서비스를 더 개선한다면 로그인 기능을 추가하여 각각의 사용자가 개인 TodoList 서비스를 제공할 수 있는 개선사항이 있다고 생각하였습니다.

3.2 컬럼간의 순서 변경

새로운 컬럼 생성시 오른쪽 또는 왼쪽에 컬럼이 생성되지만 현재 기능에서는 컬럼간의 순서는 고려되지 않았습니다. 만약 여기서 추가적인 컬럼에 대한 개선사항을 적는다면 컬럼간의 순서 변경을 할 것 같습니다. 

 

4. 어려웠던 점

4.1 카드 이동시 어떻게 순서를 유지시킬까

카드 이동시 여러가지 방법 제안이 있었습니다. 첫번째 방법은 카드를 이동하면 해당 컬럼의 카드들을 재 정렬하고 응답하는 방법이 있었습니다. 이러한 경우 각각의 카드를 수정하는 쿼리를 날릴 수밖에 없습니다. 예를 들어 해당 컬럼에 카드가 100개 있다면 100개의 쿼리를 날려서 카드의 순서를 변경해야할 것입니다. 두번째 방법은 데이터베이스 Card 테이블에 컬럼을 이용하여 연결 리스트와 같은 구조를 구현하는 것입니다. 이러한 경우 카드가 아무리 많아도 4~5번의 쿼리만 날려서 카드간에 순서를 유지시킬 수 있습니다. 하지만 이 방법 역시 쿼리를 많이 날리는 문제를 가지고 있습니다. 세번째 방법은 카드가 position 값을 가져서 카드 이동시 상단 카드와 하단 카드의 합계의 절반을 position값으로 계산하여 저장하는 방법입니다. 이 방법 같은 경우 쿼리를 1번만 날려서 위치를 변경하기 때문에 저희 팀이 선택한 방법이었습니다. 

 

5. 다음에도 유지하면 좋을점

5.1 잘 알지 못하는 기술을 학습용의 목적으로 프로젝트에 도입하지 않기

제가 이번 프로젝트에서 실수할뻔한 점은 잘 알지 못하는 기술인 OAuth2.0을 도입하여 Github 로그인 기능을 추가하려고 한 점이었습니다. 추가하려고 한 이유는 첫번째로는 로그인 기능을 추가함으로써 각각의 사용자가 개인적인 TodoList 서비스를 제공하고 동시성 문제를 해결하고자 하는 것이었습니다. 두번째는 프론트 엔드가 UI 구현하는 것에서 로그인과 회원가입 UI를 구현하는데 시간을 뺏지 않게 하기 위해서 였습니다. 하지만 그때 당시 저는 OAuth2.0을 블로그를 통해서 예제를 작성하여 성공만 한 상태였고 자세한 수행과정은 완벽하게 파악하지는 못한 상태였고 OAuth2.0을 도입하면서 학습하면 어떻게 될꺼라고 생각하던 상태였습니다. 그러던 와중 다른 마스터의 조언으로 프로젝트에 필요하지 않고 요구사항에 명세되지 않은 과한 기술은 적용할 필요가 없다는 조언을 듣고 월요일 회의를 통하여 도입하지 않게 되었습니다. 지금 생각해보면 제가 잘 알지 못하는 기술을 학습용이라는 목적으로 도입하지 않는 것을 꽤 잘한 선택이었던 것 같았습니다.

 

5.2 요구사항에 명세된 기술, 내용만을 가지고 최대한 만족하도록 수행하기

이것은 5.1과도 연관된 내용입니다. 마스터의 조언으로는 프로젝트들에 명세된 요구사항들이 앞으로의 커리쿨럼을 고려하여 명세하였기 때문에 요구사항에 명세되지 않은 기술이나 내용을 지양하는 것이 좋다는 조언을 하였습니다. 이러한 조언을 듣고 현재 명세된 요구사항을 최대한 만족하도록 수행하기로 생각하였습니다. 그래서 다음 프로젝트를 하게 된다면 주어진 요구사항을 잘 읽고 어떻게 하면 잘 만족시킬 수 있을지를 생각해보는 계기가 되었습니다.

 

References

Github : https://github.com/codesquad-team-06/todo-max

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

FineAnts 프로젝트 회고  (0) 2023.11.06
사과마켓 프로젝트 회고  (0) 2023.10.09