Trello 사이트같은 칸반보드를 구현해내는 팀프로젝트를 진행중이다. 이번 프로젝트의 가장 중요한 부분은 리스트와 카드의 이동(드래그 앤 드롭)이다. '잦은 이동이 있는 해당 로직을 어떻게 구현해 낼 것인가?' 팀원들과 이야기 나누고 찾아본 결과 우리팀은 LexoRank를 이용하기로했다.
LexoRank 선정 이유
LexoRank를 선택한 이유는 아래 글을 참고했다.
https://techblog.lycorp.co.jp/ko/about-atlassian-jira-ranking-algorithm-lexorank
이처럼 기존 방식의 한계를 모두 극복할 수 있기 때문!
LexoRank 트러블 슈팅
결정 후, LexoRank를 사용해 카드의 순서를 조정하는 기능을 구현하던 중 오류가 발생할 가능성이 있었다. 특히, rank 값과 배열 경계를 다루는 부분에서 잘못된 계산이 발생할 수 있음을 확인했다.
기존 코드
let lexoRank: string;
if (rank >= cards.length) {
lexoRank = LexoRank.parse(cards[cards.length - 2].lexoRank)
.genNext()
.toString();
} else if (rank < 1) {
lexoRank = LexoRank.parse(cards[0].lexoRank).genPrev().toString();
} else {
lexoRank = LexoRank.parse(cards[rank - 1].lexoRank)
.between(LexoRank.parse(cards[rank].lexoRank))
.toString();
}
문제 분석
- Rank 참조 문제: 원래 코드에서는 rank 값을 직접 참조했으며, 배열 크기와의 경계값 처리에서 오류 가능성이 있었다.
- 비효율적인 카드 참조: cards.length - 2를 참조하는 방식은 카드 배열이 적거나 빈 경우 잘못된 접근을 유발할 수 있었다.
해결책
코드를 findIndex를 사용해 movedCardId의 정확한 위치를 찾아 처리하도록 변경했다. 이로 인해 배열 범위를 벗어나는 문제를 방지할 수 있었다. 또한, 경계 조건을 개선하여 마지막 카드와 첫 번째 카드를 정확히 처리하도록 수정했다.
수정 코드
let lexoRank: string;
const findIndex = cards.findIndex((el) => el.cardId == movedCardId);
if (findIndex === cards.length - 1) {
lexoRank = LexoRank.parse(cards[findIndex].lexoRank).genNext().toString();
} else if (movedCardId == -1) {
lexoRank = LexoRank.parse(cards[0].lexoRank).genPrev().toString();
} else {
lexoRank = LexoRank.parse(cards[findIndex].lexoRank)
.between(LexoRank.parse(cards[findIndex + 1].lexoRank))
.toString();
}
개선 결과
- 안정성 증가: 인덱스 오류 발생 가능성을 크게 줄였으며, LexoRank 값을 보다 안전하게 계산할 수 있었다.
- 명확한 경계값 처리: 마지막 및 첫 번째 카드에 대한 처리가 명확해졌다.
이 과정을 통해 LexoRank와 배열 경계를 다루는 중요성을 다시금 느꼈으며, 더욱 신중하게 데이터 구조와 로직을 설계해야 함을 배웠다.
'개발 기초 다지기' 카테고리의 다른 글
웹소켓 웹 알림 기능 구현(할당받은 멤버에게만) (0) | 2024.07.16 |
---|---|
댓글/상태변화 알림 기능 구현 (왜 http 요청이 아닌 웹소켓인가?) (0) | 2024.07.12 |
NestJS 서버 포트 충돌 문제 해결(기존 포트 프로세스 죽이기) (0) | 2024.07.10 |
공연 예매하기 (nest.js transactionalEntityManager) (0) | 2024.07.09 |
예매 가능여부 반환(메모리 내 계산 vs 데이터베이스 필드) (0) | 2024.07.08 |
댓글