프론트엔드 개발자의 기록 공간

[우아한테크캠프] TODO 프로젝트 본문

우아한테크캠프5기

[우아한테크캠프] TODO 프로젝트

[리우] 2022. 7. 17. 23:47

2주 차도 빨리 지나갔다.. 이번 주는 많이 잔 게 6시간인 것 같다. 2주 차는 2인이 한 팀이 되어 "TODO" 프로젝트를 개발하는 것이었다. 월요일에 출근하자마자 팀원과 아이스브레이킹 타임을 가졌다. 짧은 시간이지만 이 분도 대단하다고 느껴졌다. 매일매일이 겸손해지는 것 같다. 간단한 잡담 타임이 끝나고 프로젝트 소개를 해주셨다. 이번 미션은 VanillaJS와 node를 이용하여 CSR로 개발하는 것이 미션이었다.


프런트에서 CSR을 하기 위해 babel, webpack 환경 세팅을 직접 하는 것도 미션에 포함되어 있었다. 간략한 수업을 마치고 팀원과 이번 프로젝트를 기획서를 보면서 일정과 협업 방식을 정했다. 하루마다 진행해야 할 일정을 정리하고 git commit, git issue, git branch 등을 정했다.

프로젝트 후기

FE 요구사항

  • Webpack과 Babel을 활용해 기본적인 환경 구성
  • sourceMap 설정을 해서 디버깅이 가능하도록 구성
  • fetch API 사용
  • then 메서드 활용 (async / await는 나중에)

BE 요구사항

  • AWS를 이용한 배포
  • MySQL 설치해서 사용
  • Node.js + Express를 활용해서 API 구현

요구사항에 따라 팀원과 일정과 시간 관리를 진행했다. 필요한 부분은 notion을 통해 기록하면서 회의를 진행했다.

크게 월요일은 협업 방식과 환경 세팅, 화요일은 UI 작업, 수요일은 기능 개발, 목요일은 프론트와 서버와 sql 연동 및 배포. 금요일은 시연 영상 촬영으로 시간을 보냈다.

 

환경 세팅

node.js express, webpack-dev-middleware, mysql2, babel, webpack, aws 배포 환경으로 구성했다.

환경 설정에 관한 것은 따로 포스팅할 예정이다.

폴더구조

간략하게 설명하면 하나의 프로젝트에 프런트, 백엔드 폴더를 나누어 관리했다.
웹 팩 설정으로 프런트 파일을 하나의 파일로 번들링 하여 public/dist로 내보내줍니다.
서버는 서버에 있는 html에서 번들링 된 결과물은 dist 파일에 있는 js 파일을 import 하여 연결해 줍니다.
그럼 사용자는 서버 접속 시 서버에서는 빈 html과 번들링 된 js 파일을 내려받아 csr로 화면을 렌더링 하게 된다.

개발 (레포주소)

드래그 앤 드롭에서 삽질과 너무 많이 시간을 할애해서 내가 맡은 사이드바 history 개발 쪽은 다 구현하지 못했다.
crud, move 할 때 모든 기록을 저장해야 하는데 카드 생성 시에만 기록이 저장이 된다.

todo

개발 이슈

드래그 앤 드롭 UI 처리 이슈


드래그 앤 드롭 기능만 이틀이나 걸렸다. 드래그 앤 드롭을 UI에 적용시키고 코드를 이해하는 데 하루가 걸렸고, 드래그 앤 드롭에 따른 데이터 처리와 화면 렌더링에 또 하루가 걸렸다.
카드를 옮기는 로직이 제일 까다로웠는데 다음과 같이 처리했다. (코드 일부분 소개)


todoCard는 마우스 좌표에서 가장 가까운 카드
todoCardContainer는 마우스 좌표에서 가장 가까운 컨테이너(칼럼 위치: 마우스가 어느 행에 있는지 알기 위해)
targetLi는 클릭한 카드

	const elemBelow = document.elementFromPoint(pageX, pageY)
    // 마우스 좌표에서 가장 가까운 카드 받아오기 (상위 카드)
    $todoCard = elemBelow.closest('.todo-card-wrapper')
    // 마우스 좌표에서 가장 가까운 카드 컨테이너 받아오기
    const $todoCardContainer = elemBelow.closest('.todo-card-container')
    dragPoint.hidden = false

    // 마우스 따라 이동
    dragPoint.style.left = pageX - dragPoint.offsetWidth / 2 + 'px'
    dragPoint.style.top = pageY - dragPoint.offsetHeight / 2 + 'px'

    // 가장 가까운 카드는 없고 카드 컨테이너가 있는 경우
    // -> 카드가 제일 상단에 위치해야 하거나 제일 하단에 위치해야함
    // 그냥 하위에 요소를 넣으면 된다
    if (!$todoCard && $todoCardContainer) {
      $todoCardContainer.appendChild(targetLi)
      return
    }
    // 가장 가까운 카드가 있는 경우 해당 카드 하단에 배치
    $todoCard?.parentNode?.insertBefore(targetLi, $todoCard)

mouseMove가 발생될 때마다, 마우스 좌표에서 가장 가까운 카드 위치와 컨테이너(칼럼) 위치를 받아온다.
만약 카드가 없고 컨테이너는 있다면 두 가지 중 하나의 의미로 해석된다.
1. 해당 컨테이너(칼럼)에 카드가 하나도 없는 경우
2. 해당 컨테이너(칼럼)에 제일 하단에 배치되어야 하는 경우
두 가지 경우 그냥 컨테이너(칼럼) 아래에 자식 요소로 넣어주면 둘 다 해결된다.
그리고 그 외에는 가장 가까운 카드를 찾아 하단에 배치를 하면 나머지의 경우가 처리된다.

 

드래그 앤 드롭에 따른 데이터 변경

위의 과정으로 UI로의 처리가 끝났다. 하지만 각 컨테이너(칼럼) 상단에 카드가 몇 개인지 나타내야 하고
새로 고침 시 해당 카드들을 옮긴 위치에 제대로 다시 뿌려주기 위해서는 옮겨진 카드들의 정보를 계산해서 데이터를 교체해 주고 서버에게 알려줘야 한다.

 

카드를 클릭했을 때, 해당 카드의 DOM 정보는 가지고 올 수 있는데 어디로 옮겨졌는지는 따로 DOM을 저장하거나 가리키고 있지 않기 때문이었다. 그래서 팀원과 얘기를 통해 클릭이 끝났을 경우, 즉 카드가 옮겨진 후 어떻게 해보면 되지 않을까라는 의견을 토대로 해당 작업을 수행했다. 동작은 다음과 같다


1. 클릭이 끝난 경우 클릭한 노드 정보를 토대로 해당 카드가 어디 칼럼에 존재하는지(해야 할 일, 하고 있는 일, 완료한 일)에 몇 번째 데이터에 있는지 계산한다.

 

2. 클릭된 카드의 상위 카드를 DOM에서 찾아서 상위 카드에 대한 1번 계산을 수행한다. (첫 번째 카드이고 상위가 컨테이너(칼럼)인 경우는 0번째로 인식한다.

3. 1,2번에서 찾은 카드들의 정보로 전체 데이터에서 계산을 수행한다. (데이터를 삭제, 추가를 통해 옮겨진 것처럼 표현) 그다음 데이터 변경을 통해 카드 정보 DOM을 새로 그려주면 데이터도 UI에 맞게 변경이 된다. (서버에도 api 요청을 통해 카드의 상태 정보를 업데이트해준다.)

  const handleMouseUp = () => {
    prevCard = targetLi?.previousSibling
    // 선택한 카드와 선택한 카드 상위 카드 or 컴포넌트가 있는 경우
    if (targetLi && prevCard.getAttribute('data-name')) {
      // 선택한 카드 정보 계산
      getClickedCard()
      // 상위 카드 정보 계산
      getPrevCard()
      // 교체된 위치에 따라 전체 데이터 교체로직 함수
      setStateCard()
    }

 

코드 리뷰

전반적인 코드 리뷰 타임으로 다음과 같은 말씀을 해주셨다.

  • mysql2 사용조건에 있었는데 mysql1과 다른 점이 무엇인지 알아볼 것
    • promise 지원으로 비동기 처리가 가능
    • connection pool 지원으로 여러 번의 db 연결 시 과부하를 방지
  • 저장소 보호 기능으로 dev 브랜치에서 작업하는 것을 방지
  • console.log 금지 디버깅 활용할 것
  • 이벤트 발생 순서와 제어 알기

 

2주차 전체 회고

좋았던 점

담도 경쟁력이다.

이번 주도 많은 잡담 속에서 많은 것을 접하고 배울 수 있었다. 카드 작업에 따라 사이드바에 기록을 남겨야 하는 기능이 있었는데, 나는 카드 생성 시 카드 생성 api요청 따로, history 요청 따로 생각해서 두 번의 요청으로 해결하도록 생각했다. 하지만 생성 시 단 한 번의 요청으로 서버에서 두 개의 작업을 나누어 처리하면 된다는 얘기를 듣고 아! 하고 생각했다. 사실 생각해 보면 당연히 후자로 하는 것이 맞는데, 생각이 짧아 설계를 잘못했던 것 같다.
이외에도 클래스로 컴포넌트를 작성한 팀과 VaillaJS에서도 커스텀 이벤트를 만들어서 사용한 팀, 웹 컴포넌트 개념을 사용하여 개발한 팀 등 새로운 것을 어깨너머 많이 들을 수 있었다.

 

 

아쉬웠던 & 어려웠던 점

협업

처음에는 페어 프로그래밍을 통해 설계와 구조를 함께 작성했다. 이후 기능을 나누고 각자 개발하면서 pr 수행 시, 각자 기능 개발한 것을 설명하고 그것에 대해 토론하면서 코드 리뷰 타임을 가졌다. 하지만 시간이 점점 촉박해지면서 기능 설명이랑 코드 리뷰가 제대로 이루어지지 않았다. 그러다 보니 상대방의 기능을 이용해야 할 때 다소 힘들었다. 처음부터 끝까지 페어 프로그래밍 한 팀 보고 대단하다고 느꼈다. 다음 프로젝트 때는 규칙을 정해서 지키기 위해 노력해야겠다.

 

드래그 앤 드롭 기능에 시간을 많이 할애하여 다른 기능들을 많이 개발하지 못했다. 처음에는 엄청 쉽게 끝낼 줄 알았는데 역량이 부족해서 많이 걸렸다고 생각한다. 하지만 드래그 앤 드롭을 계속 파다 보니 해결할 수 있었다. 굉장히 뿌듯했고 하나라도 끝내서 좋았다. 서버 부분은 아예 작업을 못해봐서 많이 아쉬움이 남지만, 이후에 리팩토링하면서 학습할 예정이다.

728x90
Comments