'Dang-il' 프로젝트 회고 by 내가 팀장

단단·2024년 5월 4일
1

프로젝트

목록 보기
4/10

프로젝트

당신 근처 일자리를 당일에 구하는 사이트 '당일'

Friendly 12team 깃허브 조직
배포 링크
노션 링크

내가 구현한 것

  • 초기 세팅: .eslintrc.json, .prettierrc를 루트 폴더에 세팅했다. / 테일윈드를 사용하므로 tailwind.config.ts에 반응형 사이즈와 color 변수를 지정했다.
  • 랜딩 페이지(NoticeList) 상세 필터: 필터 입력 값에 맞는 데이터만 리렌더링해야한다. 상세 필터를 사용하는 상위 컴포넌트에서 상세 필터 값과 필터값을 바꾸는 이벤트를 만든다. 이 이벤트를 하위 컴포넌트인 상세 필터 컴포넌트에 걸어줘서 하위 컴포넌트의 상태를 상위 컴포넌트가 인식할 수 있게 구현했다.
const [filterValues, setFilterValues] = useState<FilterValues>({
    clickedAddress: '',
    hashtag: [],
    startDate: undefined,
    money: undefined,
  });

  const handleClickFilter = (filterValues: FilterValues) => {
    setFilterValues(filterValues);
  };
  • 랜딩 페이지(NoticeList) 데이터 sort: 데이터를 마감임박순, 시급많은순, 시간적은순, 가나다순 sort value를 선택하면 이에 맞는 param이 쿼리로 사용된다. 그리고 리렌더링된다.
const SORT_OPTIONS = [
  { value: 'time', label: '마감임박순' },
  { value: 'pay', label: '시급많은순' },
  { value: 'hour', label: '시간적은순' },
  { value: 'shop', label: '가나다순' },
];
  const { data, loading, error, execute } = useFetch(() => {
    return noticeAPI.getNoticeList({
      offset: cardOffset,
      limit: ITEM_PER_PAGE,
      address: filterValues.clickedAddress,
      keyword: keyword,
      startsAtGte: filterValues.startDate?.toISOString(),
      hourlyPayGte: filterValues.money,
      sort: sortedData,
    });
  });

  useEffect(() => {
    execute();
  }, [
    currentPage,
    sortedData,
    filterValues.clickedAddress,
    keyword,
    filterValues.startDate,
    filterValues.money,
  ]);
  • 랜딩 페이지(NoticeList) user 주소 맞춤 공고
    토큰에 있는 로그인 user의 주소와 공고 데이터의 주소를 비교해 일치하는 데이터만 렌더링되게 했다.

  • 페이지네이션 / Pagination
    페이지네이션 구현 포스팅

  • 테이블 / Table
    테이블 컴포넌트를 사용하는 페이지가 myProfileInfo, noticeInfo 2개였다. 그래서 재사용성을 고려하기 보다 두 페이지에 각각 맞는 데이터를 연결한 테이블 컴포넌트를 구현했다.

트러블 슈팅

  • 페이지네이션 사이드 화살표 클릭 시 바로 다음 페이지로 넘어가지 않음
    -> 원인: 오른쪽 사이드 화살표 클릭 이벤트 로직을 잘못 짰다.
 const handleNextClick = () => {
    const newCurrentPage = Math.min(totalPage, currentPage + limit);
    setCurrentPage(newCurrentPage);
    setCurrentPageArray(sliceArrayByLimit(totalPage, limit, newCurrentPage));
  };

-> 해결: 현재 페이지가 속한 페이지네이션 그룹 순서를 나타내는 pageGroup 변수를 만든다. 이 변수를 활용해 오른쪽 사이드 화살표를 누르면 바로 다음 페이지로 넘어가게 만든다.

const handleNextClick = () => {
    const pageGroup = Math.ceil(currentPage / limit);
    const newCurrentPage = limit * pageGroup + 1;

    setCurrentPage(newCurrentPage);
    setCurrentPageArray(sliceArrayByLimit(totalPage, limit, newCurrentPage));
  };
  • 테이블 컴포넌트의 각 행마다 있는 버튼들이 같은 상태를 공유한다.
    -> 원인: Table 버튼 상태를 버튼 컴포넌트를 사용하는 TableBody 컴포넌트에서 관리하니 버튼의 상태를 각각 버튼이 아닌 통합적으로 관리했다.
    -> 해결: 버튼 상태를 버튼 컴포넌트에서 관리해서 따로 이벤트를 적용할 수 있었다.

  • 테이블 버튼 컴포넌트에 onClick으로 API에 put으로 status를 보내려는데 계속 400번대 에러가 발생했다.
    -> 원인: API 명세에 나와있는 put 요청 형식을 제대로 지키지 않았다.
    -> 해결: param으로 status: 객체가 아닌, string 형식 status를 넣으니 잘 작동했다.

  • NEXT.js의 페이지 라우터를 썼는데, id만 다르고 형식은 같은 공고 상세 페이지를 구현하는 데 어려움을 겪었다.
    -> 원인: Link에 id 값을 2개 이상 넣어줘야 할 땐 공고 상세 페이지 폴더 안에 id.tsx를 만들고 거기에 공고 상세.tsx를 넣으면 페이지 라우터가 제대로 동작하지 않는다.

<Link href={`/noticeInfo?shopId=${item.item.shop.item.id}&noticeId=${item.item.id}`} >

-> 해결: 공고 상세 페이지에 하위 폴더를 두지 않고, pages에 공고 상세.tsx를 만들어 shopId, noticeId를 router.query로 받아 이슈를 해결했다.

  const router = useRouter();
  const { noticeId, shopId } = router.query;

KPT 회고

나의 목표: 소외되는 사람없이 팀원들이 함께 성장한다. / 기능 분할 설계를 잘한다. / 프로젝트를 잘 마무리해서 회식하기

KEEP

  • 아침 회의 시간을 줄이기 위해 데일리스크럼 틀을 만들어 각자 진행 상황과 계획을 공유하는 방식을 적용했다. 작업 효율이 늘어나고, 팀원들이 모두 만족했다.
  • 깃허브 organization을 만들어서 이슈 관리, PR 템플릿 적용을 해 협업을 진행했다. 이슈 관리를 하니 남은 이슈를 잘 파악할 수 있고, 후에 트러블슈팅을 작성할 때 관련 커밋도 확인하기 편했다.
  • 서로 코드 리뷰를 꼼꼼히 하니 내 코드를 더 잘 쓰려고 노력하게 됐다. 자주 하는 실수 정도는 PR 전 셀프 코드 리뷰하기 시작했다.
  • API 명세를 보고 로직을 한 번 정리한 후 사용하니 API 데이터를 받아오는 데 편했다.
  • 이전보다 스스로 해결한 이슈 비율이 늘었다. 심지어 팀원들의 이슈를 해결한 적도 있다. 나 쫌 늘었네?ㅎㅎ
  • 코어타임을 하면서 팀원 간 소통이 즉각적으로 됐고, 문제가 생겼을 때 라이브 셰어를 하면서 페어프로그래밍을 한 게 도움이 많이 됐다.
  • 이전에 받은 피어리뷰를 반영해 소통 시 부드러운 화법을 사용하려고 노력했다. 이번 팀원들의 평가를 들었을 때 노력이 결실을 맺었다.
  • 종종 팀원들의 상태를 확인했다. 그러면서 어려운 지점을 함께 해결하려고 노력했다. 문제에 직면한 동료를 혼자두지 않으려고 한 게 잘한 점 같다. 우린 팀 회식하면서 프로젝트를 잘 마무리할 수 있었다. 다른 팀원들이 우리 팀이 디스코드 음챗에서 계속 대화하는 걸 보고 프로젝트를 협력해서 잘 진행하는 것 같다고 칭찬하기도 했다. 실제로 즐겁게 프로젝트 했다는 팀원의 평가도 있었다.
  • 페이지 완성 후 1차 배포를 하고 타입 에러를 잡아서 최종 배포를 하는 데 타입 에러가 매우 적었다. 배포를 미리 해보길 잘했다.
  • 주어진 기간에 비해 많은 양의 프로젝트였지만, 마지막까지 이슈를 해결하며 프로젝트를 완성했다.

PROBLEM

  • ESLint가 적용되지 않고 있다는 사실을 배포 링크 제출 전에 알았다. ESLint가 잘 적용되고 있는지 초기에 확인해야한다.
  • 코드 컨벤션을 정했지만 데이터 fetch 방식이 다양하게 구현돼 일관성이 떨어진다.
  • '내가 더 하면 되지'라는 마인드로 팀원들에게 무리해야 한다는 부담을 주지 않으려고 노력했다. 그런데 나는 팀원들이 못한 부분을 작업하기에 속도가 느렸다. 결국 목표 일정보다 진행 과정이 계속 밀렸고, 발표와 제출을 급박하게 진행하게 됐다.
  • 팀장으로서 팀원들의 상황을 고려하는 게 중요하다. 그러나 진행 일정 마지노선을 정하고 이를 맞출 수 있게 진행 상황을 계속 체크하며 독려하는 게 오히려 마지막 마감 부담을 줄일 수 있다는 생각이 들었다.
  • 아울러 개발 고수가 돼 내 부분을 신속히 끝내고 동료의 작업까지 여유롭게 진행할 수 있게 되면 좋겠다. 기능 구현뿐 아니라 클린 코드를 쓰려면 개발 속도를 늘려야 한다.

TRY

  • API 명세를 보고 로직을 정리하는 파일에 return 데이터 타입도 정의해야겠다.
  • classnames 라이브러리를 계속 추천받고 있는데 이번 프로젝트에서도 못썼다. 다음엔 꼭 써봐야겠다.
  • 기능 분할 설계를 하면서 폴더 구조와 설계의 중요성을 배웠다. 그러나 설계를 이해하는 데 좀 오래걸렸다. 다음 협업을 할 땐 어떻게 설계할지 기획 단계부터 팀원들과 소통해야겠다.
  • 이번에 배포를 진행하면서 타입 에러를 잡는데 몇 가지 타입이 계속 헷갈렸다. 이 헷갈린 타입들을 정리해서 포스팅 해야겠다.

프로젝트 팀장 소감

팀장은 여러 부분을 챙겨야 한다. 솔선수범해야하고, 부드럽게 얘기하면서도 바로 잡아야 할 부분은 명확하게 얘기해야한다. 팀원들의 상황과 진행상황 관리의 균형을 맞추는 것도 중요하다. 팀 내 문제를 빨리 파악하고 해결해야 작업을 효율적으로 진행할 수 있다.
이런 상황에서 내가 이번에 가장 중점을 둔 것은 프로젝트의 완성보단 작업 측면에서 소외되는 팀원없이 함께 성장하는 것이었다. 함께 성장하는 것에 중점을 두니 서로를 더 돕게 되고, 마무리도 잘 할 수 있었다.
이런 결과를 얻을 수 있었던 이유는 서로의 상황을 존중하고, 어려움을 공유하면 돕는 따뜻한 팀원들이 있었기 때문이다. 우리 팀원들 정말 고생많았다💗💗💗💗💗

profile
반드시 해내는 프론트엔드 개발자

2개의 댓글

comment-user-thumbnail
2024년 5월 4일

고생많으셨습니다~ 멋지네요!

1개의 답글