queryString, 바닐라JS url Parameter, 성능 개선

Rock Kyun·2023년 10월 6일
1

부트캠프 3일 차

오늘은 팀원들과 GitHub에 코드를 합치고 또 각자의 역할을 담당하러 갔다.

오늘의 문제

  • 상세페이지는 한 페이지에 이미지 슬라이드 형태의 팀원 프로필이 나옴.
  • 메인페이지에 누구의 프로필을 누르든 상세페이지의 순서는 변함없이 떠버림.

어떤 팀원을 누르면 그 사람의 프로필 UI가 제일 먼저 보여지게 수정하자!

접근 방식

  • 서버가 있다면 클릭된 사용자의 dataset이나 임의의 id나 어떤 정보를
    url parameter를 받아와 처리할 수 있을텐데 싶음.
  • 그래서 순수 JS에도 URL의 정보를 찾아오는 것이 있나 찾아봄. (못 찾았다.)
  • 결국 튜터님께 질문드리고 queryStringURLSearchParams에 대해 배워왔다.

해결 요약

  • JS 파일의 팀원 프로필 데이터에 고유 id 값을 추가해준다.
  • HTML에서 /:변수명 같은 url parameter 대신 url?변수명=값 형태의 쿼리스트링을 사용
  • JS 파일에서 new UrlSearchParams(window.location.search) 클래스 사용하여
    queryString에 담겨온 데이터를 받는다.
  • 변수에 query String의 값을 저장하고 이용하여 팀원 프로필 UI의 순서를 정렬한다.

해결 과정

  1. 먼저 HTML에서 클릭 시 전달 될 경로와 query String을 설정했다
    아래와 같이 href를 설정하면
    디테일 페이지의 url 창에는 ~경로/detail.html?id=0 이렇게 뜬다.
<.html>
  
<a href="./Pages/detailPage/detail.html?id=0">
  <div class="image" style="text-align: center; height: 200px">
    <img src="image/city-3764330_1280.jpg" alt="" class="p1" />
    <img src="image/pop-art-2706464_1280.jpg" alt="" class="p2" />
  </div>
</a>
  1. JS 파일에서 query String 값을 추출한다.
<.js>
  
const urlParams = new URLSearchParams(window.location.search);
const initValue = urlParams.get('id');
  • window.location.search
    • 현재 페이지의 url을 가져온다
    • window.location에 다양한 속성이 있는데 url을 다룰 때 유용하니 참고하면 좋겠다.
      hianna님의 tstory
  • URLSearchParams
    • URLSearchParams()는 인자로 전달한 url을 다룰 수 있는 인스턴스를 생성한다.
    • URLSearchParams에서 생성 된 인스턴스에는 다양한 method가 있다.
      URLSearchParams 인스턴스의 method들

위와 같이 url parameter를 받아와 변수에 initValue로 저장했다.

  1. 팀원의 데이터를 기반으로 반복적으로 프로필을 생성하는 함수가 작동될 때
// 현재 페이지의 URL을 다루는 인스턴스 생성
const urlParams = new URLSearchParams(window.location.search); 
// 인스턴스의 get 메소드를 사용하여 id라는 이름의 값을 추출하여 변수에 저장
const initValue = urlParams.get('id');

// url Parmaeter의 값을 참조하여 profile이라는 팀원 데이터를 정렬 후 UI 생성 진행

// Array의 요소를 정렬하기 위해 고유 id가 url Parameter 값과 같은 값을 가진 요소를 추출
const selected = profile.filter(el => el.id === parseInt(initValue))
// 고유 id가 url Parameter 값과 다른 값을 가진 요소를 추출하여
const other = profile.filter(el => el.id !== parseInt(initValue))
// 정렬 된 Array로 반복문을 진행
const sorted = selected.concat(other);
  sorted.forEach(data => {
    const { name, github, blog, MBTI, goal, hobby } = data
    
    ///// ......UI 생성 코드 ///////////

배운 것

  • 서버가 없어도 URL을 다룰 수 있다.
  • 처음에 난 dataset 속성에 값을 담아서 보낼까 고민하며
    dataset 값을 보면 디테일 페이지 url이 잘못됐다고 페이지가 안 뜨고 엄청 혼란했는데
    이렇게 좋은 객체나 메소드가 준비되어 있다는 것을 알았고.
    공식 문서를 공부하는 법을 익혀야겠다.

알고 있는 지식 외에 더 좋은 방법들이 많으니 늘 다양한 접근 방식을 고려해보자.

+추가 성능 개선

  • 계기

    • 아무래도 프로필을 재정렬 하는 데에 있어, filter를 두 번, concat을 한 번 썼는데
      뭔가 성능이 조금 떨어질 거 같아 GPT 찬스를 썼다.
  • 해결 방법

    • 첫째로 GPT의 답변을 더 좋게 하기 위해 페르소나를 줬다. (넌 성능을 아주 중요하게 생각하는 개발자야! 라는 역할)
    • GPT는 배열 재정렬 코드를 아래와 같이 짜줬다.
const sorted = profile.slice().sort((a, b) => {
	const aId = a.id;
	const bId = b.id;

 	if (aId === parseInt(initValue)) return -1;
  	if (bId === parseInt(initValue)) return 1;

	return 0;
});

사전지식: sort()

sort(콜백함수)는 Array의 요소들을 하나씩 돌며 비교해주는데
이때 인자로 들어가는 콜백함수의 return 값에 따라
요소의 위치를 바꿀지 그대로 둘지 결정되는 메소드다.

sort MDN 문서

  • 코드 해석
    • profile.slice()를 통해 profile Array데이터를 변경하지 않고 복제한다.
    • 복제 된 Array에 sort()를 사용.
    • sort()의 콜백 함수는 (a, b) => {} 형태로 a,b는 각각 Array의 요소(오브젝트 자료형)이다.
    • 데이터의 id의 값을 가지고 비교할 것이기에 a.id, b.id로 변수를 설정하고 비교를 진행.
    • a.id가 urlParam과 같다면 b.id 보다 앞에 있는 상태 그대로 둬야하니 -1을 return,
      b.id가 urlParam과 같다면 b.id가 a 앞으로 가야하니 1을 return,
      그 외의 경우라면 정렬이 필요없으니 0을 return 한다.

성능개선 결과

  • 초 단위 환산하면 나의 PC 기준으로 0.000025초 빨라졌다😅
  • 유의미한 개선은 아니었지만 큰 프로젝트에서 다량의 데이터를 다룬다면.. 도움이 될 수도...😀

0개의 댓글