Sparta/TIL

24.03.21 TIL - LexoRank(2)

jskim4695 2024. 3. 22. 01:47

먼저 LexoRank의 공식 문서를 보던 중, 그 전 포스팅에 잊고 명시하지 않은 점이 있다는 것을 깨달았다. LexoRank는 kanban board로 널리 쓰이는 JIRA의 알고리즘이라는 점이다. 

 

설치 명령어는 다음과 같다. 아래의 명령어로 package.json에 설치되어 프로젝트에 이용할 수 있다.

더보기
npm install lexorank
yarn add lexorank

 

 

메소드는 두가지 형태로 나뉘는데,

import {LexoRank} from "lexorank";

// public method
// min
const minLexoRank = LexoRank.min();
// max
const maxLexoRank = LexoRank.max();
// middle
const middleLexoRank = LexoRank.middle();
// parse
const parsedLexoRank = LexoRank.parse('0|0i0000:');


// static method
// any lexoRank
const lexoRank = LexoRank.middle();

// generate next lexorank
const nextLexoRank = lexoRank.genNext();

// generate previous lexorank
const prevLexoRank = lexoRank.genPrev();

// toString
const lexoRankStr = lexoRank.toString();

 

 

프로젝트에 적용하는 것은 쉽지 않았는데, 라이브러리를 쓰면 그 자체로 의존성을 가지기 때문에 메서드의 이해도가 낮으면 쉽게 타입에러를 발생시키곤 했다. 여러 번의 시도 끝에 create와 get의 코드를 짤 수 있었다. github에 있는 test 코드를 참고하여 쓰다보니 static method인 middle()을 써서 만들어봤는데, 계속 같은 값을 만들어서 당황했다. 공식 문서를 보고서야 static이라는 것을 깨닫고 genNext로 생성시마다 다른 값을 db에 저장해줄 수 있었다.

    async createCard(createCardDto: CreateCardDto) {
      let lexoRank;
      const existingCard = await this.cardRepository.findOne({ where: {}, order: { lexo: "DESC" } })
      if (existingCard && existingCard.lexo) {
        lexoRank = LexoRank.parse(existingCard.lexo.toString()).genNext();
      } else {
        lexoRank = LexoRank.middle();
      }
    
      const newCard: Card = this.cardRepository.create({
        title: createCardDto.title,
        description: createCardDto.description,
        color: createCardDto.color,
        dead_line: createCardDto.dead_line,
        lexo: lexoRank.toString()
      });
    
      const savedCard = await this.cardRepository.save(newCard);
      return savedCard;
    }

 

 

 

순서를 바꾸는 코드는 오히려 beween() 메서드를 이용하여 쉽게 구현할 수 있었다. 생성되는 lexoRank값만 바꿔주면 되는 로직이라 github의 코드와 별반 다를 바가 없었는데, 리스트를 불러와서 정렬하는 코드가 말썽이었다. 분명히 순서를 바꾸는 코드에서 lexo값이 변경되고 있는데 리스트를 불러오면 순서는 바뀌지 않는 것이다. parse 메서드를 통해 파싱이 필요한 값이라는 부분도 console.log를 찍어보고 나서야 알 수 있었고, toString() 메서드를 사용해야 하는 부분도 쉽게 깨닫기 힘들어서 여러 시행착오를 겪었다. 

  // 카드 목록 보기
  async findAll() {
    const cards = await this.cardRepository.find()

    const sortedCards = cards
    .sort((a, b) => {
      if (a.lexo && b.lexo) {
        const lexoA = LexoRank.parse(a.lexo.toString());
        const lexoB = LexoRank.parse(b.lexo.toString());
        return lexoA.compareTo(lexoB);
      }
      return 0; // lexo 값이 없는 경우 정렬하지 않음
    })
    .map((card) => ({
      data: {
        id: card.id,
        title: card.title,
        description: card.description,
        color: card.color,
        dead_line: card.dead_line,
        lexo: card.lexo.toString(),
      },
    }));

    return sortedCards
  }

 

 

순서를 바꾸는 부분의 코드는 다소 난잡하게 구현된 관계로 포스팅에는 포함시키지 않겠다. 하지만, 이번 기회에 느낀 점은 처음 보는 라이브러리도 공식문서를 읽고 이해하면서 사용하면 프로젝트에 녹여낼 수 있다는 점이다. 지난 해에 진행했던 nest.js 프로젝트에서 react관련 라이브러리를 사용했는데, 그때는 코드를 읽어낼 능력도 없었고 구글링만 해서 해결하려고 하니 쉽사리 쓰기가 어려웠는데 이번에는 성공해서 다행이라는 생각이 먼저 들었다.