Main Project 회고

uxolrv·2023년 1월 1일
2

프로젝트 소개


영양제 유통 사이트 Pillivery


  • Pillivery
  • Github
  • 정기 결제로 손쉽게 영양제를 받아볼 수 있는 영양제 유통 사이트
  • Pillivery는 알약을 뜻하는 Pill과 배송을 뜻하는 Delivery의 합성어




프로젝트 선정 이유


남녀노소 누구나 관심을 가질만한 분야를 다뤄, 다양한 유저들이 이용할 수 있는 서비스를 만들고자 함.




개발 및 기술 정보


개발 기간

  • 2022.11.08 ~ 2022.12.07 (약 4주)

개발 인원

  • Front-end 4명
  • Back-end 3명

기술 스택

Front-end

JavaScript, React, Styled components, Redux toolkit, React query, axios

Back-end

Java, Spring boot, Spring Sercurity, Spring JPA, Redis, Gradle, MySQL, JWT, Quartz

Tools

Git, Github Figma, Postman, Discord, Zoom, notion








회고

팀 규칙


지금보니 지켜지지 못한 부분도 있기야 하지만 (어?!! 금지라던지... 특히나 내가...🥲) 팀원들과 처음으로 의견을 주고 받을 수 있는 시간이어서 좋았다!


프리 프로젝트 때, 아침 9시에 캠 키고 가볍게 인사를 나눈 후 데일리 스크럼을 진행하는 방식으로 진행하였었는데, 당시에 꽤 좋았다고 생각이 들어 팀원 분들께 이 규칙이 있었으면 좋겠다고 말씀을 드려 추가하였다.

아침 9시에 캠을 켜야 하다보니 8시에 일어나서 씻으면서 잠을 쉽게 깰 수 있었고, 데일리 스크럼을 진행하면서 오늘 해야 할 일이 무엇인 지 머리 속으로 정리하기 수월했던 것 같다.


처음으로 팀이 구성되어 모인 당일에 가볍게 인사를 나눈 후 바로 팀 규칙 선정으로 들어갔었는데, 지금 생각해보면 아이스 브레이킹 시간을 따로 가진 후 진행하였으면 더 좋았을 것 같다.

나는 원래 낯을 가리지 않는 성격인데다가, 원래 알고 있던 분들이 계셔서 괜찮았지만, 다른 분들 입장에서는 오늘 다 처음 본 사람인데 약간 어색하게 느끼셨을 수도 있다는 점을 고려하지 못했던 것 같다.




프로젝트 선정 과정


팀원들이 다같이 모여 생각나는 서비스들을 마구잡이로 얘기하는 브레인스토밍 방식으로 프로젝트 주제를 선정하였다. 각자 생각나는 의견을 낸 후, 해당 서비스를 구현한다면 어느 기능이 구현되어야 할 지를 다 같이 생각하는 방식으로 진행하였다.


위와 같이 정~~말 많은 의견이 나와 투표를 통해 최종 후보를 추렸다.



구현할 수 있는 기능들우려스러운 점
영양제 구독 서비스- 원하는 주기로 영양제 받아보기
- 효능별 카테고리 분류
- 건강 정보 체크해서 필요한 영양제 추천
- 리뷰 작성
- 찜 기능
- 영양제 관련 지식을 공부하는 시간이 오래 걸릴 것 같음
여행 패키지 플랫폼- 여행사 패키지 / 체험 패키지 등 카테고리 분류
가격비교
- 여행객 매칭 (여행 마치고 리뷰)
- 위치 별 모아보기 (서울/경기/충청/...)
- 찜 기능
- 실제 여행사 데이터를 받아 올 수 있을까?
이용권 중고거래 플랫폼- 기간을 채우지 못한 헬스장, 바디프로필 등의 이용권을 양도할 수 있도록
- 촬영, 운동 등 카테고리 분류
- 회당 금액을 계산해주는 기능
- 위치 별 모아보기 (서울/경기/충청/...)
- 양도비 포함 여부 표시
- 찜 기능
- 실 이용자가 적어서 트래픽이 작을 듯 함
- 예시가 많지 않아 참고할 자료가 부족함
- 데이터를 어디서 받아와야 할 지?
원데이 클래스 플랫폼- 원데이 클래스들을 모아서 가격비교하고, 예약
- 지역별, 분야별 필터
- 리뷰
- 선물 기능
- 이달의 클래스 추천
- 사용자 맞춤 클래스 추천 (ex. mbti별)
- 딱히 생각나지 않음

4개의 의견 중 다같이 우려 사항을 생각해보고 최종 투표를 통해 영양제 구독 서비스로 결정하였다!

영양제 관련 지식 부분은 기존의 영양제 사이트에 이미 카테고리 분류가 잘 되어있고, 영양제 자체에도 성분표가 잘 나와있기 때문에 크게 걱정하지 않아도 될 것 같다고 결론을 내렸다.




사용자 요구사항 정의서


처음 사용자 요구사항 정의서를 작성할 때에는 해보고 싶은 기능들을 다 추가하고, 다 구현하고 싶은 마음에 대부분 중요도를 으로 두었었다.
그러나 멘토님께서 주어진 기간에 비해 구현해야 할 기능이 너무 많고, 중요도가 너무 에 밀집되어 있어 중요도의 의미가 없다는 피드백을 주셨다.

아무래도 본격적인 프로젝트는 처음이다 보니 잘하고 싶은 욕심이 났던 것 같다. 🥲

그래서 유통 사이트에 없으면 안되는 필수적인 기능들은 , 있으면 좋은 기능을 , 없어도 지장은 없으나 시간이 된다면 해볼 만한 기능들은 로 다시 설정하였다.


물론... 여전히 엄청나게 많지만 중요도를 낮추니 확실히 부담이 덜어져서 좋았던 것 같다!




유저 플로우


오른쪽 마우스 - 새 탭에서 이미지 열기로 더 선명하게 볼 수 있습니다.

주제를 선정한 후에는 프론트엔드와 백엔드가 각자의 작업을 하기 시작하였다. 프론트엔드에서 가장 먼저 시작한 작업은 유저 플로우다!

초반에는 유저가 사이트에 접속하여 카테고리에서 원하는 영양제를 구매하는 플로우만을 생각했기 때문에 유저플로우가 굉장히 심플했다.

그러나 점점 "카테고리로 접근하지 않고 검색으로 접근한다면?", "구매하러 온 게 아니라 리뷰를 작성하러 방문한 거라면?" 등등 꼬리에 꼬리를 물고 다양한 플로우들이 생각이 나버려 굉장히 거대한 유저 플로우가 되었다...

그래서 만들면서도 이렇게까지 세세하게 짜는 게 맞나? 너무 모든 경우를 고려한 건가? 의문이 가득한 상태로 만든 후, 멘토님께 여쭤보니 세세하게 짤 수록 좋다고 아주 잘 구성했다고 칭찬해 주셔서 너무 뿌듯했다!!




UI/UX 디자인 - 와이어프레임


피그마를 사용하여 페이지의 구조를 잡는 와이어프레임을 만들었다.

프론트엔드에서 디자인 작업을 하는 동안에, 백엔드 분들도 다른 작업을 하실 수 있도록 각 페이지에 어떤 데이터가 필요한 지 명시하였다.

디자인도 동시에 하면서 구조를 잡아갔다면 굉장히 오래 걸렸을 텐데 흑백 박스로 대략적인 요소들의 위치를 잡아가며 구성하니 생각보다 빨리 끝낼 수 있었던 것 같다!




UI/UX 디자인 - 프로토타입


앞서 완성한 와이어프레임을 바탕으로 웹 사이트를 디자인하여 프로토타입을 만들었다.

이때 각자 원하는 스타일을 모아놓고 얘기하는 과정이 있었는데, 역시 디자인은 취향이 많이 갈리는구나 싶었다.🤔 나는 너무 심플하면 단조로워 보일 것 같아서 색을 어느 정도 쓰고 싶었는데, 다른 팀원분들은 블랙&화이트 위주의 심플한 디자인을 선호하셨다.

그래서 메인 컬러와 포인트 컬러 등을 결정하여 컬러칩 내에 있는 컬러만을 사용하고, 디자인 자체는 심플하게 가는 방향으로 결정하였다!

컬러칩을 결정한 후에는 팀원들끼리 컴포넌트별로 분담하여 디자인을 구체화하는 작업을 하였다. 프로토타입에서 디자인을 확실히 잡고 가야 추후에 코드 작업에서 시간을 단축시킬 수 있을 것 같아 최대한 꼼꼼하게 작업을 하였다.

작업을 하다보니 신기했던 것이 피그마가 어도비 일러스트레이터와 매우 유사하다는 것이었다. 심지어 피그마가 훠어얼씬~~ 쉽고 가벼워서, 일러스트레이터였다면 진작에 꺼져서 다 날아가고... 또 다시하고... 너무 무거워지면 결국 여러 파일로 분할해서 작업해야 했을텐데, 피그마는 조금 버벅거리는 정도이기만 하고 잘 돌아가는 게 너무너무 신기하고 신세계였다... ✨ 피그마 짱

일러스트레이터를 다뤄본 적이 있어서, 다른 분들보다 빠르게 내 분량을 끝낼 수 있었기 때문에 다른 분들을 도와드릴 수 있었고, 유용하게 쓰일 만한 단축키들도 알려드릴 수 있어서 좋았다! 디자인 배웠던 게 여기서 다 도움이 되는구나~ 싶었다 🥳

워낙 꼼꼼하게 작업을 해서 그런지, 2~3일이면 끝날 줄 알았던 디자인 작업이 생각보다 길어져서 코드 작업에 지장이 있을 정도가 되어버리자, 팀원들과 의논하여 데드라인을 정했다. 그리고 그 날까지 모두가 다같이 게더타운에 모여서 아침까지 실시간으로 의논하며 불🔥같이 작업을 한 덕분에 결국은 마감일까지 작업을 완료할 수 있었다!


완성한 ✨프로토타입✨!!


처음에는 나만 선호하는 스타일이 조금 달라 걱정했었지만, 오히려 선호하는 스타일이 달랐기에 더욱 시너지 효과를 낼 수 있었다!
나 혼자 디자인할 때에는 단조로워 보이지 않게, 심심해보이지 않게 하는 것에 집중하게 되어 디자인이 조금 과해질 때도 있는데, 그러한 부분들을 다른 팀원분들이 잘 덜어내주신 덕분에 조화로운 디자인이 나온 것 같다!

나는 원래 디자인 작업을 대학교에서 내내 해왔기 때문에 작업 기간이 길었던 게 그렇게 힘들지는 않았는데, 다른 분들에게는 꽤 지치는 과정이었을 것 같다...

그럼에도 불구하고, 다들 책임감을 갖고 서로를 도와가며 작업한 덕분에 무사히 마칠 수 있었던 것 같다. 깐깐하다고 느낄 정도로 하나하나에 의견을 많이 냈는데도 기꺼이 수용해 준 팀원들에게 감사하다!! 👏




어려움을 겪었던 부분, 에러들

💡 페이지 이동 시, 토글 상태 유지하기


일반을 클릭하면 일반 주문내역 페이지로, 정기를 클릭하면 정기 주문내역 페이지로 이동하는 토글버튼이다.
일반 → 정기를 클릭했을 때 order/subscription으로 이동은 되지만 토글 상태가 일반에 남아있으며, 한번 더 클릭을 해야만 정기쪽으로 넘어왔다. 반대의 경우도 마찬가지...🥲



토글 컴포넌트를 일반 주문내역 페이지와, 정기 주문내역 페이지에 각각 따로 두어서 페이지가 바뀌며 리렌더링이 되면서 상태가 유지가 되지 않는 것으로 보였다.



function MyPage() {
	const { pathname } = useLocation();
	// 일반/정기 토글이 주문내역에서만 보이도록
	const show = pathname.includes('/order');
	return (
		<Container>
			<MyPageHeader />
			<MypageTab />
			{show && <ToggleTab />}
			<Outlet />
		</Container>
	);
}

마이페이지의 레이아웃을 담당하고 있는 MyPage.js에 토글 컴포넌트를 위치시켜, 주문내역에서만 토글이 보이도록 구현하였다!




💡 페이지마다 배경색 크기 다르게 설정하기


피그마로 작업했던 프로토타입을 살펴보면 배경색이 1️⃣ 전체 흰색인 페이지, 2️⃣ 흰색과 회색이 함께 있는 페이지, 3️⃣ 전체 회색인 페이지로 나누어져 있다.

한 가지 색으로 이루어진 페이지는 문제가 없었으나, 흰색과 회색이 함께 있는 페이지를 구현하는 것이 고민이었다.

background-color는 한 컴포넌트에 하나 밖에 적용이 안되기 때문에, 회색 배경을 담당할 컴포넌트를 하나 더 만들어서 positionfixed로 두어야 하나? 생각을 했지만 불필요한 컴포넌트를 만드는 것이라고 느껴졌다.



그러다 문득 2개 이상의 배경색을 설정할 수 있는linear-gradient를 이용해서 색이 점진적으로 변하지 않게 설정하면 되지 않을까? 싶어져서 직접 사용해보니 색상의 정지점을 퍼센트가 아니라 픽셀로도 설정할 수 있었다!



const Container = styled.div`
	${({ pathname }) => {
		switch (pathname) {
			case 'cart':
			case 'pay':
				return `
				background-color: var(--gray-100)
				`;
			case 'mypage':
				return `
				background-image: linear-gradient(to bottom, white 278px, var(--gray-100) 0)
				`;
			case '':
				return `
				background-image: linear-gradient(to bottom, white 800px, var(--gray-100) 0)
				`;
			default:
				return `
				background-color: white`;
		}
	}}
`;

switch 문을 사용하여, 페이지 경로에 따라 픽셀 값을 조절하여, 배경색을 다르게 설정하였다!




💡 옵셔널 체이닝 파싱 에러 해결하기


서버로부터 데이터를 받아오기 전에 데이터의 프로퍼티에 접근하게 되면 에러가 발생하여, 이러한 경우에 옵셔널 체이닝(?.)을 사용하곤 했는데 eslintParsing error를 발생시키는 것을 확인하였다.

그러나 실행도 잘되고... 작업하는 데에 큰 문제는 없어서 처음에는 두고 있다가, 파일 목록에서 파일명이 빨갛게 뜨는게 거슬리기도 하고 실제로 다른 에러가 발생한 파일과 헷갈리기도 해서 에러를 고치기 위해 공식문서를 찾아보았다.



eslint 공식문서에 따르면, parserOption은 기본적으로 ECMAScript 5 문법을 지원한다고 한다.
옵셔널 체이닝(?.)이 ES2020에 도입된 최신 문법이라 parser가 이해하지 못하여 Parsing error 발생하는 것으로 보였다.



// .eslintrc.json

"parserOptions": {
	"ecmaVersion": 2020
}

eslintrc 파일에 parserOptions 설정을 추가하니 더이상 에러가 발생하지 않았다!


출처: eslint 공식문서




💡 가격필터 컴포넌트 정렬하고 애니메이션 적용시키기


작업 도중 팀원 한 분이 검색 페이지에 가격 필터정렬 방법 버튼을 배치하였는데 정렬이 안된다고 말씀하셔서 확인해보니, 오른쪽이 고정된 상태에서 왼쪽으로 펼쳐져야 하는 필터가 가운데를 기준으로 양옆으로 펼쳐지고 있었다.



const Filter = styled.div`
	width: 158px;
	height: 113px;
	flex-direction: column;
	display: flex;
	align-items: center; // 📌
	justify-content: center;
`;

코드를 확인해보니 가격 필터정렬 방법을 감싸고 있는 컴포넌트의 align-item 값이 center로 설정되어있어서 가운데 정렬이 되고 있음을 확인하였다. 값을 flex-end로 변경하니 오른쪽 고정은 잘되었으나 새로운 문제가 발생하였다.



원래 디자인할 때에는 가격 필터정렬 방법을 가리면서 펼쳐지는 것을 의도했었는데, 정렬 방법을 밀어내면서 펼쳐지고 있었다. 또한 가격 필터를 펼쳤을 때 할인상품 모아보기 버튼의 위치가 잠시 이상했다가 원 위치로 돌아오는 문제도 있었다.

가격 필터는 내가 작업했던 부분은 아니었으나 이 두 부분을 고쳐보고 싶었기 때문에 팀원분들께 양해를 구해 제가 한번 고쳐보겠다고 말씀을 드리고 수정해보았다.



// 가격 필터 및 정렬 방법의 상위 컴포넌트
const ButtonsBox = styled.div`
	...
	position: relative;
`;


// 가격 필터 내부의 가장 상위 컴포넌트
&.price-container {
	position: absolute;
	right: 0px;
	top: -60px;
	z-index: 2;
}

가격 필터정렬 방법의 상위 컴포넌트에 position: relative 속성을 추가하고, 가격 필터position: absolute를 추가하여 원하는 위치로 고정한 후, z-index 값을 추가하여 펼쳐졌을 때 정렬 방법을 가릴 수 있도록 하였다.



할인상품 모아보기 버튼의 위치가 이상했던 것은 할인상품 모아보기 버튼이 priceSortButton 내부에 위치해있었고, position: absolute를 통해 위치가 고정되어있었기 때문에 애니메이션 효과로 인해 가격 필터가 펼쳐지는 동안 위치가 이상하게 잡혔던 것으로 보였다.

할인상품 모아보기 버튼 컴포넌트의 위치를 priceSortButton에서 분리하고 상위 컴포넌트인 priceButton에 위치시켰다!



정상적으로 작동하는 모습 🥳




💡 응답 헤더에서 userId 받아오기


상품의 상세페이지에 접근하였을 때, 현재 로그인한 유저가 작성한 글에만 수정|삭제 버튼을 표시하기 위해 이를 판별할 수 있는 userId 데이터가 필요했다.


그래서 백엔드 분들께 요청하여 로그인 시에 userId를 받기로 했는데 포스트맨으로는 응답 헤더에서 잘 보이는 userId가 브라우저 응답에서는 전혀 안보이고 있었다...

내가 코드를 잘못 짰나 싶어서 확인해보니 userId와 동일하게 헤더에서 받아오는 AuthorizationRefresh은 잘 받아와지고 있었다.



브라우저 콘솔에서 응답 헤더를 하나하나 뜯어 살펴보니 Access-Control-Expose-HeadersAuthorizationRefresh가 적혀 있는 것을 확인했다.



Access-Control-Expose-Headers에 대해 찾아보니, Access-Control-Expose-Headers를 통해 응답으로 브라우저에서 실행 중인 스크립트가 사용할 수 있는 응답 헤더를 지정할 수 있다고 한다.

Access-Control-Expose-HeadersuserId가 포함되어 있지 않아, 브라우저 상에서 userId에 접근할 수 없었던 것이었다! 처음에는 userId

위와 같은 내용을 정리하여 백엔드 팀원분들께 말씀드려 응답 헤더에서 userId에 성공적으로 접근할 수 있게 되었다!


출처: Mdn




💡 상세페이지에서 받은 응답, 결제페이지로 보내기


상세페이지에서 바로 구매하기를 클릭하면 장바구니를 거치지 않고 곧바로 결제 페이지로 이동할 수 있다.

그래서 처음에는 유저가 수량을 선택하면 서버에 구매 요청(POST)를 한 후 결제 페이지로 이동시키는 방식으로 코드를 구성하였었다.

그런데 결제 페이지를 담당하고 있던 팀원분이 말씀하시기를, 바로 구매를 요청한 후, 응답으로 돌아오는 정보가 결제 정보라서 결제 페이지에서 필요하다고 말씀을 하셨다.



응답을 확인해보니 정말 결제 정보가 담겨 있는 것을 확인할 수 있었다.

페이지가 이동되는데 이걸 다른 페이지에 보낼 방법이 있나? 그냥 서버 측에 결제 페이지에서 다시 저 정보를 보내 줄 수 있는 지 여쭤봐야 하지 않을까? 생각하다가 문득, useNavigate로 이동할 페이지에 데이터를 전송할 수 있다고 얼핏 읽었던 것이 기억이 났다!



공식 문서를 확인해보니 두번째 인자로 state를 넘겨줄 수 있음을 확인하였다.

모든 요청은 팀원분들이 만들어주신 hook을 이용하고 있었는데, 상세 페이지와 장바구니 페이지에서 보내는 구매 요청만 navigate에 두번째 인자가 필요한 상황이라, 새로운 hook을 만들어야 했다.



function usePurchase(url, params) {
	const queryClient = useQueryClient();
	const navigate = useNavigate();

	const { mutate, isLoading, isSuccess, isError } = useMutation(
		(data) => axiosInstance.post(url, data),
		{
			onSuccess: (res) => {
				navigate(`/pay/${params}`, { state: res.data.data }); // 결제 페이지로 응답 전송
				queryClient.invalidateQueries();
			},
			onError: async () => {
				toast.error(
					<div>
						현재 구매할 수 없는 상품입니다.
						<br />
						서비스 이용에 불편을 드려 죄송합니다.
					</div>,
				);
			},
		},
	);

	return { mutate, isLoading, isSuccess, isError };
}

상세 페이지와 장바구니 페이지에서 구매 요청 시 사용할 usePurchase hook을 만들었다. 팀원분들이 만들어 놓으신 hook 코드를 찬찬히 살펴보며 만드니 금방 만들 수 있었다!

응답이 성공적으로 돌아왔을 때에는 navigate의 두번째 인자로 응답 데이터를 전송하도록 만들고, 에러가 발생했을 때는 안내창을 띄우는 식으로 코드를 구성하였다.


출처: React Router 공식 문서




💡 모달 일정 시간 후 자동으로 닫히게 하기


모달을 직접 구현하고 싶었지만 일주일을 프로젝트 기획 및 디자인 작업하는 데 써버려 코드 작업 기간이 촉박한 상황이었기에 react-modal 이라는 라이브러리를 사용하여 구현하였다.

react-modal 라이브러리는 모달 외부 클릭 및 ESC 키 클릭 시 모달이 닫히는 기능을 자체적으로 제공하고 있다.



그러나 유저가 반드시 클릭해야 하는 모달(ex. 장바구니에서 상품을 삭제할 경우, 한번 더 확인하는 모달) 외에 사진처럼 장바구니에 담기를 클릭 했을 때 장바구니로 이동 의사를 묻는 모달의 경우, 유저가 장바구니로 페이지에 머물고 싶을 때 무조건 모달의 외부를 한번 클릭해야만 했다.

사소한 일이지만 불필요한 유저의 제어가 늘어나는 것이 UX에 좋지 않을 것이라 판단이 되어 일정 시간이 지나면 자동으로 닫히도록 구현하고자 했다.



공식 문서를 살펴보니 ReactModal에게 onAfterOpen이라는 props로 전달된 함수는 모달이 열린 후 실행되는 것을 확인하였다.



const afterOpenModal = () => {
	if (autoClose) {
		setTimeout(() => {
			closeModal();
		}, 1800);
	}
};

return (
	<Modal
		onAfterOpen={afterOpenModal}
		...
	>
)

유저의 제어가 필수적이지 않은 모달은 전체 모달의 뼈대가 되는 defalutModal에게 autoClose라는 props를 보내주도록 하고, autoClose가 있을 경우에만 setTimeout을 실행시켰다.



유저의 제어 없이도 일정 시간 후 닫히는 모달이 구현되었다!




KPT 회고


KEEP

매일 아침 데일리 스크럼을 진행했던 점
아침 잠을 깨우는 데에도 효과적이었고, 어제의 작업량을 한번 더 상기시킨 덕분에 오늘 작업할 분량을 계획하는 데에 효과적이었던 것 같다.


항상 먼저 나서서 의견을 냈던 점
낯을 가리시거나 먼저 의견 제시하는 것을 어려워하시는 성향일 수도 있음을 고려하여 항상 먼저 의견을 내려고 노력하였다.
또한, 회의할 때 가벼운 장난도 치며 분위기를 띄우려고 노력했었는데 나도 엄~~청나게 활발한 성격은 아니라서 가족처럼 화목한 분위기를 만들지는 못했지만 어느정도 웃으면서 편하게 작업할 수 있었던 것 같다!


전달 및 요구 사항이 있을 때는 근거를 덧붙였던 점
에러가 발생할 때에는 해당 에러를 캡쳐하고 상황을 설명하며 에러를 설명드려 전후관계 파악이 쉽도록 하였다.

백엔드 분들께 추가적인 데이터를 요구할 때에나 같은 프론트엔드분들께도 수정했으면 하는 사항을 말씀드릴 때에도 항상 타당한 이유를 덧붙여 설명드리고자 했기 때문에 팀원들 간의 의견 충돌이 적었던 것 같다.


혼자서 해결하기 어려운 일이 있을 땐 바로 질문했던 점
디자인하는 과정에서 어떤 게 더 나은 지 헷갈릴 때가 많았는데, 그때마다 팀원들에게 보여주고 의견을 물어보는 방식으로 진행했다.
독단적으로 결정했다면 결정이 오래 걸렸을 뿐만 아니라, 추후에 수정해야 할 수도 있는 부분이었는데 물어본 덕분에 빠르게 결정할 수 있었던 것 같다.

또한, 다른 분들이 작업했던 부분을 수정할 일이 있을 때 내가 적은 코드가 아니다보니 코드의 연관관계를 파악하는 게 오래 걸릴 때가 있었는데 그럴 땐 바로 여쭤보았다. 이 덕분에 작업 시간도 단축시켰을 뿐만 아니라 코드를 수정하며 에러가 발생할 일이 적었던 것 같다.




PROBLEM

일정 관리를 잘 하지 못한 점

나름 일정 관리를 한다고 했는데, 미리 계획한 게 아니라 작업이 시작되면 마감기한만 정하는 방식으로 그때그때 계획을 세웠던 게 문제였던 것 같다.

대표적으로는, 코드 상으로 컴포넌트+페이지 UI를 구현하는 작업인데 이 작업만 일주일 넘게 걸린 것 같다.

피그마에서 디자인을 확실히 잡아 놨다고 생각했는데도, 피그마 화면에서 보는 것과 브라우저에 구현해서 보는 건 차이가 꽤 있어서 사이즈를 조절하는 작업이 많이 들어갔었다.

또한 최대한 비슷한 컴포넌트끼리 묶어 분담하여 작업을 했는데도, 작업하는 페이지가 다르다보니, 페이지마다 스타일이 묘하게 달라 어색할 때가 많아서 수정하고 또 수정하느라 시간을 너무 많이 잡았던 것 같다. 🥲


겹치는 컴포넌트가 발생한 점
이미 만들어진 컴포넌트가 활용되지 않고 새로 만들어 사용되는 경우가 많았다.


후반부에 프론트-백 간의 소통이 부족했던 점
초반에는 활발히 소통했으나 앞서 말한대로 시간이 부족해지니 각자 작업하기 바빠 소통이 부족했던 것 같다.

프로젝트 마감 2일 전에 서버의 API가 완성되어 그제서야 부랴부랴 API 요청 작업을 했었는데, 미리 json server를 사용하여 요청 틀은 잡아놓은 상태였는데도 통신 과정에서 생각지 못한 이슈가 많이 생겨서 바쁜 와중에 더 시간이 지체되었었던 것 같다.

사전에 미리 완성된 만큼이라도 받아서 API 요청 작업을 해두었다면 통신 과정에서 발생하는 에러나 빠져있는 데이터를 미리 파악하고 수정할 수 있었을텐데 싶은 아쉬움이 있다.


다른 분들의 의견을 잘 챙기지 못한 점
KEEP에서 항상 의견을 먼저 제시했다고 했는데 이 때문인지 다른 분들의 의견은 많이 들을 수 없어서 아쉬웠다.




TRY

프로젝트 시작 전에 미리 일정 계획하기
프로젝트를 본격적으로 시작하기 전에 미리 대략적으로라도 일정을 계획해놨더라면 임시적인 마감 기한에 최대한 맞출 수 있지 않았을까? 싶다.

만약 계획했던 기간 안에 마치지 못했고, 작업 중인 부분이 추후에 수정해도 괜찮은 부분이라면 적당히 마무리한 후 다음 작업으로 넘어가고 모든 작업을 끝내고 수정하는 방식으로 일정 관리를 철저히 해야겠다.


소통에 더욱 신경쓰기
서버와는 각자 작업을 끝낸 후가 아니라, 중간 중간에도 꾸준히 통신해보며 맞춰가는 작업을 하고, 프론트엔드끼리는 각자 작업할 파트를 나눴다고 끝이 아니라, 컴포넌트 작업 전/후에 공지를 하는 방식으로 진행해야겠다.

먼저 의견을 제시한 후에는 각자가 생각할 시간을 충분히 드리고, 다른 사람들의 의견도 먼저 여쭈어 보는 자세를 갖춰야겠다.

바쁘다고 빠르게 작업하는 데에만 신경쓰지 말고 소통에도 많은 신경을 기울여야 할 것 같다.








타락파워전사라는 팀명으로 모인 지 벌써 한달이 지나 프로젝트가 마무리되었다.

지금 돌이켜 생각해보니 팀과 협업하면서 커뮤니케이션 능력은 물론, 기술적인 부분에서도 많이 배울 수 있었던 시간이었던 것 같다!

우선 앞으로의 계획은 시간 탓에 적용해보지 못했던 타입스크립트를 공부한 후, 프로젝트에 적용하고 코드 퀄리티를 높이기 위한 리팩터링을 진행할 예정이다.

초면에 얼렁뚱땅 낸 팀명인데도 선뜻 응해주었던 타락파워전사 팀원들 !!
다들 만렙전사답게 앞으로도 화이팅하셔서 레전드로 남으시길 ✨🥳




profile
안녕하세연🙋 프론트엔드 개발자입니다

0개의 댓글