쿼리 파라미터(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 = 수정값
형태로 손쉽게 수정할 수 있다!
어떻게 쿼리스트링을 객체로 변환할 수 있는지, 또 객체로 변환해 수정한 다음 어떻게 합쳐 다시 사용할 수 있는지 차근차근 정리해보자.
const query = "order-by=${this.state.filter}&category=${this.props.match.params.id}&limit=20";
위 쿼리스트링을 객체로 변환하는 함수 queryToObj()
를 구현해보자.
&
로 텍스트를 나눈 배열을 만들어준다.
큰 배열(list)안의 값은 아래와 같이 각각의 배열로 반환된다.
[order-by=${this.state.filter}],
[category=${this.props.match.params.id}],
[limit=20]
이중 배열 안의 값을 map 함수를 통해 =
로 나누고, 이후 작업을 위해 이 값을 [key, val]
라고 할당한다. 아래에서 key는 이중 배열 안의 전자 값, val은 이중 배열 안의 후자 값이라고 생각하면 된다.
[order-by, ${this.state.filter}],
[category, ${this.props.match.params.id}],
[limit, 20]
각각의 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}
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',
// }
쿼리스트링을 객체로 변환했다면, 다시 문자열로 합쳐주어야 사용할 수 있다.
이 과정은 지금껏 해왔던 과정을 반대로 다시 해준다고 생각하면 쉽다.
Object.entries()를 통해 객체를 이중 배열의 형태로 만들어준다.
[ ['order-by', '${this.state.filter}'],
['category', '${this.props.match.params.id}'],
['limit', '20'] ]
map 함수를 통해 각각의 이중 배열 안의 배열 값을 =
로 연결한 스트링으로 합쳐준다.
[ 'order-by=${this.state.filter}', 'category=${this.props.match.params.id}', 'limit=20' ]
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;
}
긴 풀이가 무색하게도.. 첫 번째 방법의 모든 과정은 하나의 메서드로 해결 가능하다 ^^.. 참 좋아진 세상~
하지만 배열과 객체의 속성을 제대로 공부할 수 있기에 학습 과정에선 첫 번째 방법을 추천하고, 실제 적용할 땐 두 번째 방법을 추천한다. 원리를 알고 사용하는 것과 모르고 사용하는 건 하늘과 땅 차이이니까 😎
이해를 해보기 위해서 댓글 달아두려구요!
좋은 글 감사합니다