2021.03.31 추가
serverless-http 라이브러리를 사용할 경우multiValueQueryStringParameters
를 우선 사용하기 때문에 아래에 나온 것처럼 array를 전달하는 방식을 바꾸지 않아도 됩니다.
AWS Lambda 엔드포인트에서 아래 처럼 query string을 통해 array 형태의 값을 전달하게되면 예상과는 달리 맨 마지막 값만 사용됩니다.
클라이언트 요청 GET my-awesome-api?a=1&a=2&a=3
--
실제 요청 GET my-awesome-api?a=3
이러한 사실은 AWS 문서에서도 찾을 수 있습니다.
If you do not enable multi-value header syntax and a header or query parameter has multiple values,
the load balancer uses the last value that it receives.
그렇기 때문에 우리에게는 두 가지 선택지가 있습니다.
1. event.queryStringParameters 대신에 event.multiValueQueryStringParameters를 참조한다.
2. array를 전달하는 방식을 변경한다.
(a[0]=1&a[1]=2와 같이 전달할 경우 서로 키가 다르기때문에 모든 값이 온전하게 전달된다.)
첫번째 방식으로 변경할 경우, 아무런 wrapper 라이브러리 없이 함수를 직접 작성한 경우 단순히 참조하는 대상만 변경하면 됩니다. 만약 aws-serverless-express
라이브러리를 사용한 경우라면 깃허브 이슈를 참조하시기 바랍니다.
이제 두번째 방식인데, 일반적으로 query string에서 array를 표현하는 방식은 크게 네 가지가 있습니다.
1. 같은 키를 반복하는 형식
url?a=1&a=2&a=3
2. json array notation 사용
url?a[]=1&a[]=2
3. json array notation과 함께 인덱스 사용
url?a[0]=1&a[1]=2
4. ,(콤마)로 구분하는 방식
url?a=1,2,3,4
통상적으로 1번 혹은 2번 방식이 많이 사용되지만 1, 2번 방식을 사용할 경우 array로 전달한 파라미터가 스트링이 되거나 array의 일부만 전달되는 현상이 나타날 수 있습니다.
그렇기 때문에 팀의 규칙 혹은 개인적인 선호에 따라서 3번 혹은 4번 방식을 사용할 수 있습니다.
이제 라이브러리 선택 문제입니다.
node.js
환경에서 query string 파싱/직렬화(serialization)를 위한 라이브러리들 중 가장 유명한 두 라이브러리는 qs
와 querystring
(표준 node.js 라이브러리) 입니다.
두 라이브러리에는 많은 차이점이 있지만 그 중 .stringify
메쏘드를 통한 직렬화 결과에서 그 차이가 두드러집니다.
querystring.stringify({ a: [1, 2, 3] }) --> 'a=1&a=2&a=3' (1번 방식)
__
qs.stringify({ a: [1, 2, 3] }) --> 'a[0]=1&a[1]=2&a[2]=3' (기본 3번 방식)
querystring과 달리 두 번째 인자인 options를 통해 다른 방식으로 직렬화하는 것도 가능합니다.
> qs 라이브러리 README에서 발췌
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' })
// 'a[0]=b&a[1]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' })
// 'a[]=b&a[]=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' })
// 'a=b&a=c'
qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'comma' })
// 'a=b,c'
개인적으로는 위와 같은 차이 때문에 qs
를 좀 더 선호하지만 저러한 기능이 필요하지 않다면 굳이 qs
를 사용할 필요는 없습니다.
다음은 axios
와의 연동입니다.
axios
는 get/delete
요청 시 param
을 설정에 넘길 수 있습니다.
axios.get('url', { params: a: [1, 2, 3] })
이 때 아무런 설정을 하지 않았다면 아래와 같이 직렬화됩니다.
url?a[]=1&a[]=2&a[]=3
만약 위의 기본 동작을 변경하고 싶다면 config
에 paramsSerializer
를 사용할 수 있습니다.
axios.get('url', {
params: {
a: [1, 2, 3]
},
paramsSerializer: params => {
return qs.stringify(params)
}
})
이제 qs.stringify
를 직접 사용했을 때와 마찬가지로 'a[0]=1&a[1]=2&a[2]=3'
형태로 직렬화할 수 있습니다.
끝까지 읽어주셔서 감사합니다. 😄
Lambda 없이 express 에는 querystring가 배열로 그대로 잘 들어가는데, Lambda 에서는 왜 모두 인식이 되지 않는지 의문이었습니다.
귀찮아서 기록하지 않을 법 한 내용인데, 덕분에 도움받고 갑니다.