JS | 쿼리스트링을 객체로 변환하기

DongHee Kim·2021년 9월 12일
3

Javascript

목록 보기
9/9
post-thumbnail

쿼리스트링이란?

쿼리 파라미터(Query Parameter)라고도 하며, 사용자가 URL 주소 뒤에 입력 데이터를 전달하는 방법 중 하나이다. 해당 웹 페이지의 엔드포인트에 대해 질의문(query)를 보내는 요청으로, 사용자가 특정한 값을 URL 주소로 쉽게 전달할 수 있다.

예를 들어 localhost:8000/product?limit=20&order-by=grade에서 ?limit=20&order-by=grade부분이 쿼리스트링이다.


왜 쿼리스트링을 객체로 변환하는가?

한 마디로 말하면, 쉽게 수정하려고 !

예를 들어 쿼리스트링이 아래와 같고 여러 번 반복되어 사용된다고 하자.
아래 쿼리스트링에서 category의 값 수정이 필요하다면, 긴 쿼리에서 category의 값 부분을 찾고 다른 값에 영향을 주지않게 한땀 한땀.. 번거로운 과정을 거쳐 수정해야 한다.

const query = "order-by=${this.state.filter}&category=${this.props.match.params.id}&limit=20";

하지만 위의 쿼리스트링을 아래와 같이 객체로 변환한다면?

const queryObj = {
'order-by': '${this.state.filter}',
category: '${this.props.match.params.id}',
limit: '20',
}

queryObj.category = 수정값 형태로 손쉽게 수정할 수 있다!


어떻게 쿼리스트링을 객체로 변환할 수 있는지, 또 객체로 변환해 수정한 다음 어떻게 합쳐 다시 사용할 수 있는지 차근차근 정리해보자.


첫 번째 방법 : 객체와 배열 속성 이용

1. 문자열 => 객체 변환

const query = "order-by=${this.state.filter}&category=${this.props.match.params.id}&limit=20";

위 쿼리스트링을 객체로 변환하는 함수 queryToObj()를 구현해보자.

Step. 1

& 로 텍스트를 나눈 배열을 만들어준다.
큰 배열(list)안의 값은 아래와 같이 각각의 배열로 반환된다.

[order-by=${this.state.filter}],
[category=${this.props.match.params.id}],
[limit=20]

Step. 2

이중 배열 안의 값을 map 함수를 통해 =로 나누고, 이후 작업을 위해 이 값을 [key, val] 라고 할당한다. 아래에서 key는 이중 배열 안의 전자 값, val은 이중 배열 안의 후자 값이라고 생각하면 된다.

[order-by, ${this.state.filter}], 
[category, ${this.props.match.params.id}],
[limit, 20]

Step. 3

각각의 key, val 값을 {property:key, value:val} 값으로 반환해준다.
여기까지가 map함수 끝!

{property: order-by, value: ${this.state.filter}}, 
{property: category, value: ${this.props.match.params.id}}, 
{property: limit, value: 20}

Step. 4

map함수의 결과값인 각각의 객체를 reduce(콜백함수,초기값) 를 통해 하나의 결과값으로 축약해준다. 그러면 객체 형태로 변환된 값이 나온다.

{
'order-by': '${this.state.filter}',
category: '${this.props.match.params.id}',
limit: '20',
}

위의 과정을 한 눈에 보기 위한 코드 전문은 아래와 같다.

const queryToObj = query => {
  
// 1. "&" 로 텍스트를 나눈 배열을 만들어준다.
  const list = query.split("&");
  
// 2. 배열 값을 map 함수를 통해 "="로 다시 나눈 뒤 이걸 [key, val] 형태라 하자. 
// 3. 각각의 key, val 값을 {property:key, value:val} 값으로 반환해준다.
// 4. map함수의 결과값인 각각의 객체를 reduce를 통해 하나의 결과값으로 축약해준다. 
  
  const objQuery =  list.map(item => {
    const [key, val] = item.split("=")
    return {property:key, value: val}
  }).reduce(
    (acc,cur) => {acc[cur.property]=cur.value;
                 return acc;},{})

  return objQuery
};

//   반환값 = {
//  'order-by': '${this.state.filter}',
//  'category': '${this.props.match.params.id}',
//  'limit': '20',
//  }

2. 객체 => 문자열 변환

쿼리스트링을 객체로 변환했다면, 다시 문자열로 합쳐주어야 사용할 수 있다.
이 과정은 지금껏 해왔던 과정을 반대로 다시 해준다고 생각하면 쉽다.

Step. 1

Object.entries()를 통해 객체를 이중 배열의 형태로 만들어준다.

[ ['order-by', '${this.state.filter}'],
['category', '${this.props.match.params.id}'],
['limit', '20'] ]

Step. 2

map 함수를 통해 각각의 이중 배열 안의 배열 값을 =로 연결한 스트링으로 합쳐준다.

[ 'order-by=${this.state.filter}', 'category=${this.props.match.params.id}', 'limit=20' ]

Step. 3

join("&")으로 각각의 값을 합쳐주면 정말 끝!
문자열 => 객체 변환 때 처음에 &으로 스트링을 분리했던 걸 생각하면 정말 모든 과정을 거꾸로 거슬러왔구나 느낄 수 있다.

'order-by=${this.state.filter}&category=${this.props.match.params.id}&limit=20'

위의 과정을 한 눈에 알 수 있는 코드 전문은 아래와 같다.

  const objToQuery = objQuery => {
  stringQuery = Object.entries(objQuery).map(([key, value]) => `${key}=${value}`).join("&");
  return stringQuery;
}

두 번째 방법 : URLSearchParams()

긴 풀이가 무색하게도.. 첫 번째 방법의 모든 과정은 하나의 메서드로 해결 가능하다 ^^.. 참 좋아진 세상~
하지만 배열과 객체의 속성을 제대로 공부할 수 있기에 학습 과정에선 첫 번째 방법을 추천하고, 실제 적용할 땐 두 번째 방법을 추천한다. 원리를 알고 사용하는 것과 모르고 사용하는 건 하늘과 땅 차이이니까 😎

profile
일상의 성실이 자존감을 만드는 성취주의자

1개의 댓글

comment-user-thumbnail
2021년 9월 12일

이해를 해보기 위해서 댓글 달아두려구요!
좋은 글 감사합니다

답글 달기