이전에 올렸던 코드에서 리팩토링된 부분이 좀 많아 다시 작성하려한다.
이전글을 참고해서 코드를 보면 순서를 많이 바꾸거나 새로운 카드를 추가했을 때, 순서 값을 초기화해야하는 상황이 있는데 이 부분을 추가하였고,
순서 조정을 할 때, 앞 순서에서 뒷 순서로 가는 것은 상관이 없으나 뒷 순서에서 앞 순서로 갈 때는 중간 값을 계산하기 위해 선택되어야 하는 카드를 다르게 만들어주어야 한다.
그렇게 해서 수정된 코드는 아래와 같다.
우선 카드를 추가하는 코드의 일부이다.
// 카드의 순서 값. 카드가 없을 경우만 최대값에서 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 });
}
}
이렇게 많은 카드가 생기거나 카드 순서를 많이 바꾸더라도 하나의 카드만 수정하여 순서를 바꿀 수 있도록 하였고, 초기화도 넣어두었지만 초기화까지 굉장히 오래 걸릴 것이다.
효율적이지 않을 수도 있고 사실 잘 모르겠다..
피드백은 언제나 환영!