프로젝트 알고리즘 적용

Imnottired·2023년 5월 8일
0
post-thumbnail

공부를 하다보면 알고리즘에 대해 의문이 들었다
알고리즘을 어디에 써야할까?라는 생각을 했고, 계속해서 알고리즘 활용에 관한 생각들을 갖고 있었다.

근래 들어 백엔드 분들과 많이 소통하면서 알게된 사실인데, 데이터 처리와 관련된 작업을 수행할때 알고리즘을 활용한다고 한다. 예를 들어 이분 검색을 통해서 id를 더 빠르게 찾거나 검색 알고리즘을 최적화에서 더 빠르게 찾을 수 있겠다.

그러면 프론트엔드에서 쓰는 것은 어디일까? 라고 고민하던 참,
최근 코드의 영역을 나누기 위해서 함수를 작성하였는데, 여러 경우의 수에 대처하려다보니 알고리즘을 작성하게 되었고, 나의 고민을 해결할 수 있었다.

나의 고민을 알고리즘을 통해 해소했던 경험에 대해 정리하겠다.




페이지 네이션

페이지네이션을 구현할 때 어려웠던 포인트가 있다.
total값과 current 값을 주면
current를 이용하여서 양 끝에는 2만큼 크고 반대쪽에는 2만큼 작은 값을 주면 된다.
그런데 문제는 시작마지막이다.

시작 1일 경우에 이렇게 작성해면- 0 1 2 3 이오는데

나는 1 2 3 4 5가 오길 원했다.

또한 끝이 12이라면
10 11 12 13 14가 아니라
8 9 10 11 12가 오길 원했다.

처음에는 복잡하다고 생각하였는데,
단계별로 나누어서 생각해보니 이 문제를 해결하였다.

  const [isPage, setIsPage] = useState(currentPage);
  const prevPage = isPage > 1 ? isPage - 1 : null;
  const nextPage = isPage < totalPages ? isPage + 1 : null;
  const pageRange = 2;
  let startPage = isPage - pageRange;
  let endPage = isPage + pageRange;

  const pages = Array.from(
    { length: endPage - startPage + 1 },
    (_, i) => startPage + i
  );

먼저 초기값으로 currentpage를 넘겨주고
두번째로는 왼쪽과 오른쪽이 있는지 확인하였다.
(null일 경우 화살표 x)
그 다음으로는 pageRange로 양쪽에 보여줄 갯수를 정하고
현재 값에서 범위를 더하고 빼는 방식으로 시작과 끝을 찾았다.

이후 끝에서 시작을 뺀다음 +1 한 방식으로 length를 찾았다.

  • Range에서 양쪽을 포함하면 +1, 한쪽만 포함하면 x 양쪽다 포함안하면 -1을 해주어야한다

5라고 넣을 수도 있었지만, Range가 3개일 경우 4개일 경우에도 처리하기 위해서 빼는 방식을 사용하였다.
하지만 위의 로직의 문제점은 current가 1일 경우 -2, -1, 까지 보여준다.
또는 total이 12 여도 그 이상의 수 (13,14)가 나와서 문제가 생긴다.

해결하기 위해서 두 상황을 나누어서 작성하였다.

  const pageRange = 2;
let startPage = isPage - pageRange;
let endPage = isPage + pageRange;
console.log(startPage, endPage);

if (startPage < 1) {
  endPage += 1 - startPage;
  startPage = 1;
}

if (endPage > totalPages) {
  startPage -= endPage - totalPages;
  endPage = totalPages;
}

const pages = Array.from(
  { length: endPage - startPage + 1 },
  (_, i) => startPage + i
);

그전 로직이라면 만약에 start가 -1이라면
-1 0 1 2 3이 나온다.
그래서 이런 경우에 2개를 추가해주어야하는데,
-1 인 경우에는 2개를
0 1
startPage가 0인 경우에는 1개를 더 주어야해서
endPage += 1 - startPage;(음수)
1을 디폴트로 주고 양수로 바꿔서 더하는 방식을 사용하였다.
(0,1 경우에는 startPage가 0이어서 더하지않는다)

그리고 마지막으로 뒷페이지가 부족할 경우에는
endPage - totalPages; 끝페이지에서 토탈을 빼준 차만큼을
startpage에게 빼주어서
endpage와 startpage의 거리를 늘렸고 이러한 방식을 통해
5개의 페이지로 늘릴 수 있었다.

정리하자면

  • 양쪽에 2개 나오는 로직 작성
  • 첫째 페이지가 부족할 경우
  • 끝 페이지가 부족할 경우

3가지 경우로 나누어서 작성하였더니 쉽게 되었다.
위 로직이 복잡하여서 생각을 정리하는데 시간이 오래걸렸고,
알고리즘을 조금이라도 하여서 모든 경우의수를 작성해보고
거기서 공통점을 찾는 방식을 통해 찾을 수 있었다.


토너먼트

월드컵은 32강 16강 8강 4강 이렇게 준비하였다.
만약에 준비된 팀이 18명이면, 32강은 목록에서 제거되고 16강, 8강, 4강만 보여야한다.
그리고 초기값이 16강으로 잡혀야한다.

처음에는 이 로직을 빠르게 작성하려고 브레인 스토밍으로 쭉 작성하였는데 잘처리하지못하였다.
그래서 단계별로 분리하여서 큰 그림을 생각하면서 정리하다보니 로직이 나왔다.


function getInitialRound(candidatesCount: number): Round {
  const rounds = [4, 8, 16, 32]; // 가능한 라운드 수
  let selectedRound: Round = 16; // 기본값은 16강
  for (let round of rounds) {
    if (candidatesCount >= round) {
      selectedRound = round as Round;
    } else {
      break;
    }
  }
  return selectedRound;
}

export { getInitialRound };

먼저 내가 원하는 라운드 수를 배열로 정리하였고,
초기값보다 작은 max값을 찾으면 되는 것이었다.
또한 그 수보다 크다면 이미 최대값을 찾은 것이므로 break로 for문을 작성하여서
빠르게 끝나게 만들었다.

만약에 알고리즘 문제로 나왔다면 쉽게 풀었을테지만,
실제 코딩을 하다가 갑자기 알고리즘을 작성해야할 상황이 오니
상황 정리가 어려웠다

알고리즘은 주어진 문제 조건이 잘 정리된 것과 다르게,
코딩하다 알고리즘을 써야하는 순간이오면 정리되지 않은 조건들 때문에 머리가 혼란스러웠다.

그래서 주어진 조건들을 깔끔하게 정리해주고 나니, 수월하게 풀 수 있었다.




마무리

어려운 경우가 생겨도 주어진 조건들을 정리하고, 단계별로 나누어서 접근한다면
전보다 더 수월하게 해결할 수 있는 경험을 하였다.

생각해보면 알고리즘에서 푼 문제들이 더 어려운 문제들이었지만,
실전은 쉬운 문제라도 그것을 적용하는 것은 또 다른 어려움이었다.

예전에 기사에서 알고리즘을 공부해야하는 이유는 시야가 넓어진다고 하였는데,
오늘을 계기로 다시 한번 알고리즘 공부에 중요성을 느꼈다.

공부 초기에는 여러 경우의 수들이 있는 상황에서 알고리즘과 연관지어서 생각하지 못했고, 복잡하면 복잡한대로 하고, 정리도 안된 상태에서 계속해서 반복했던 것 같다.

그랬던 경험들이 쌓여서 인지 이제는 내가 어려워하는 상황이 오면 주어진 상황을 정리하고,
단계별로 나누어서 문제를 해결하겠다.

profile
새로운 것을 배우는 것보다 정리하는 것이 중요하다.

4개의 댓글

comment-user-thumbnail
2023년 5월 14일

잘보고 갑니다 ㅎㅎ 알고리즘은 일단 의사코드 작성하는게 70%는 되는 거 가탕요.. 어려줘

답글 달기
comment-user-thumbnail
2023년 5월 14일

알고리즘을 되게 별개의 영역이라 생각하고 있었는데... 반성하고 갑니다 쥬륵

답글 달기
comment-user-thumbnail
2023년 5월 14일

알고리즘 공부한게 이렇게 실제 프로젝트에서 적용될 수 있군요.. 짱입니다👍

답글 달기
comment-user-thumbnail
2023년 5월 14일

코테용으로만 생각했는데 이렇게 실제로 코드에 적용하시다니 ... 멋지십니다

답글 달기