[React, typeScript] 실시간 시세표 일정 시간만 border 노출하기

mxxn·2023년 8월 22일
0

React

목록 보기
7/9

문제

  • 기존에 만들었던 시세표 내 border 노출은 1개 값 기준으로 되어 있었기 때문에,
    rabbitMq를 통해 갑자기 여러건의 시세 변경 건이 들어온다면 바뀐 시세의 border가 잠깐 보이고 빛보다 빠르게 사라지는 문제
  • 즉, 현재 시세가 바뀌는 종목이 표시는 되나, 다른 종목에서 시세가 바뀌면 표시칸이 바로 바뀜
  • 현재 시세칸의 border가 바로 바뀌는게 아니라 일정 시간을 두고 차례대로 없어져야함

해결방법

1. 들어온 데이터들의 종목코드를 array에 담았다가, setTimeOut으로 일정 시간 뒤에 삭제하는 방식(push & shift)

const [queue, setQueue] = React.useState<string[]>([]);

React.useEffect( () => {
  
  // 전달 받은 시세 데이터의 종목코드를 push
  setQueue(prev => {
    let newArr = [...prev]
    newArr.push('종목코드')
    return newArr
  })

  // 일정 시간 뒤에 shift
  setTimeout( () => {
    setQueue( prev => {
      let newArr = [...prev]
      newArr.shift()
      return newArr
    })
  },5000)
  
},['전달받은 rabbitMq의 시세 데이터'])

1-1. 1의 작업을 queue class로 구현


class Queue<T> {
  items: T[] = [];

  enqueue(item: T) {
    this.items.push(item);
  }

  dequeue(): T | undefined {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.shift();
  }

  isEmpty(): boolean {
    return this.items.length === 0;
  }

  size(): number {
    return this.items.length;
  }
}
    
const initialQueue = new Queue<string>();
const [queue, setQueue] = React.useState([initialQueue]);

React.useEffect( () => {
  setQueue((prevQueue) => {
    const newQueue = new Queue<string>();
    newQueue.items = [...prevQueue.items];
    newQueue.enqueue('종목코드');
    return newQueue;
  });

  setTimeout(() => {
    setQueue((prevQueue) => {
      const newQueue = new Queue<string>();
      newQueue.items = [...prevQueue.items];
      newQueue.dequeue();
      return newQueue;
    });
  }, 5000);
},['전달받은 rabbitMq의 시세 데이터'])
  1. 여러 데이터가 짧은 시간 내에 여러건 들어오더라도 border가 갑자기 사라지지 않고 일정 시간 동안 유지된다.
  2. 하지만 array의 shift는 배열의 맨 앞의 값을 삭제하고 재배치 하게 되므로 시간복잡도가 O(n)이 되기 때문에, 해결해야 하는 시세 데이터가 늘어난다면 느려질 수 있다고 생각하게 됨

2. Queue 구현을 통해 시간복잡도를 낮춤

class Queue<T> {
  storage = {};
  front = 0;
  rear = 0;

  size() {
    if (this.storage[this.rear] === undefined) {
      return 0;
    } else {
      return this.rear - this.rear + 1;
    }
  }

  add(value) {
    if (this.size() === 0) {
      this.storage['0'] = value;
    } else {
      this.rear += 1;
      this.storage[this.rear] = value;
    }
  }

  popleft() {
    let temp;
    if (this.front === this.rear) {
      temp = this.storage[this.front];
      delete this.storage[this.front];
      this.front = 0;
      this.rear = 0;
    } else {
      temp = this.storage[this.front];
      delete this.storage[this.front];
      this.front += 1;
    }
    return temp;
  }
}

const initialQueue = new Queue<string>();
const [queue, setQueue] = React.useState(initialQueue);

React.useEffect( () => {
  setQueue(prev => {
    const newQue = new Queue<string>();
    newQue.front = prev.front
    newQue.rear = prev.rear
    newQue.storage = {...prev.storage};
    newQue.add('종목코드')
    return newQue;
  });

  setTimeout( () => {
    // queue.popleft()
    setQueue(prev => {
      const newQue = new Queue<string>();
      newQue.front = prev.front
      newQue.rear = prev.rear
      newQue.storage = {...prev.storage};
      newQue.popleft();
      return newQue
    })
  }, 5000)
},['전달받은 rabbitMq의 시세 데이터'])
  1. queue의 storage에 종목코드를 추가/삭제 하는 방식
  2. 빠른 접근을 위해 front와 rear 값을 설정하고 해당 값을 storage의 key값으로 사용

참고 velog [자료구조] JS로 구현하는 큐 (Queue)

profile
내일도 글쓰기

0개의 댓글