[nestJS] DB 데이터의 순서 바꾸기 -2

Uhan33·2024년 3월 21일
1

TIL

목록 보기
52/72

이전에 올렸던 코드에서 리팩토링된 부분이 좀 많아 다시 작성하려한다.

이전글을 참고해서 코드를 보면 순서를 많이 바꾸거나 새로운 카드를 추가했을 때, 순서 값을 초기화해야하는 상황이 있는데 이 부분을 추가하였고,
순서 조정을 할 때, 앞 순서에서 뒷 순서로 가는 것은 상관이 없으나 뒷 순서에서 앞 순서로 갈 때는 중간 값을 계산하기 위해 선택되어야 하는 카드를 다르게 만들어주어야 한다.

그렇게 해서 수정된 코드는 아래와 같다.
우선 카드를 추가하는 코드의 일부이다.

	// 카드의 순서 값. 카드가 없을 경우만 최대값에서 2를 나눈다.
    if (cardList.length === 0)
      nextCardPosition = Number.MAX_VALUE / 2;
    else
      nextCardPosition = cardList[0].position / 2;

    // position 초기화작업
    if(nextCardPosition = cardList[0].position) {
      const resetCard = await this.sortByPosition('card', list.id, 'DESC');
      await this.resetPosition(resetCard);
    }

    return await this.cardRepository.save({
      listId: createCardDto.listId,
      userId,
      title: createCardDto.title,
      content: createCardDto.content,
      backgroundColor: createCardDto.backgroundColor,
      image: createCardDto.image,
      position: nextCardPosition,
      startDate,
      dueDate,
    });

그리고 순서를 바꾸는 코드의 일부는 아래와 같다.

    const selectCard = await this.sortByPosition('card', card.listId, 'ASC');
    const selectPosition = selectCard[changePositionNumber - 1].position;

    if (changePositionNumber >= selectCard.length || changePositionNumber <= 0)
    throw new BadRequestException('요청한 position은 card의 범위를 넘어갔습니다.')

    // 첫 번째 자리로 옮기는 경우
    if (changePositionNumber === 1) {
      // position을 초기화 해야 하는 경우(더이상 나누어지지않고 같은 값이 되어버릴 때)
      if(selectPosition === selectPosition / 2) {
        const resetCard = await this.sortByPosition('card', card.listId, 'DESC');
        await this.resetPosition(resetCard);
      }
      
      await this.cardRepository.update({ id: cardId }, { position: selectPosition / 2 });
      return { message: `${selectPosition / 2}로 이동` }
    }

    // 마지막 자리로 옮기는 경우 기존 마지막녀석의 position을 그 앞으로 옮기게 값을 바꾸고
    // 이후에 우리가 선택한 녀석을 마지막자리로 보내준다(Number.MAX_VALUE/2가 마지막 수 고정)
    else if (changePositionNumber === selectCard.length) {
      // position을 초기화해야 하는 경우(last position과 last-1 position의 합을 2로 나눈 값이 last-1 position일 경우)
      if(selectCard[selectCard.length - 2].position === (selectPosition + selectCard[selectCard.length - 2].position) / 2) {
        const resetCard = await this.sortByPosition('card', card.listId, 'DESC');
        await this.resetPosition(resetCard);
      }
      await this.cardRepository.update({ id: selectCard[selectCard.length-1].id }, { position: (selectPosition + selectCard[selectCard.length - 2].position) / 2 });
      await this.cardRepository.update({id: cardId}, {position: Number.MAX_VALUE/2})
      return { message: `${(selectPosition + selectCard[selectCard.length - 1].position) / 2}로 이동` }
    }

	// 앞 -> 뒤 : 선택한 위치의 다음 카드를 선택, 뒤 -> 앞 : 선택한 위치의 이전 카드를 선택
    let nextPosition = selectCard[changePositionNumber].position;
    if(card.position > selectPosition) {
      nextPosition = selectCard[changePositionNumber-2].position;
    }
    
    const changeValue = (selectPosition + nextPosition) / 2;

    // position을 초기화해야 하는 경우((A + B) / 2가 A 혹은 B가 될 경우)
    if(nextPosition === changeValue || selectPosition === changeValue) {
      const resetCard = await this.sortByPosition('card', card.listId, 'DESC');
      await this.resetPosition(resetCard);
    }

    await this.cardRepository.update({id: cardId}, {position: changeValue});

방식은 이전에 정리해둔 글과 똑같은데,
카드가 앞 -> 뒤로 이동하는 경우와 뒤 -> 앞으로 이동하는 경우를 나누어 주었다.
이렇게 하지 않으면 뒤 -> 앞으로 이동하는 경우에 n번째에 넣으려 하면 n+1 번째로 들어가는 문제가 생긴다.

+순서를 초기화 하는 메서드는 간단하다.
내림차순 정렬로 카드들을 불러온 뒤 카드를 생성할 때 넣는 값을 순차적으로 부여해준다.

  // 순서 값 초기화 메서드
  async resetPosition(selectCard: Card[]) {
    let position = Number.MAX_VALUE
    for (let card of selectCard) {
      position /= 2;
      await this.cardRepository.update({ id: card.id }, { position: position });
    }
  }

이렇게 많은 카드가 생기거나 카드 순서를 많이 바꾸더라도 하나의 카드만 수정하여 순서를 바꿀 수 있도록 하였고, 초기화도 넣어두었지만 초기화까지 굉장히 오래 걸릴 것이다.
효율적이지 않을 수도 있고 사실 잘 모르겠다..
피드백은 언제나 환영!

0개의 댓글