AWS Lambda에서 query string array 사용하기

gompro·2020년 7월 24일
4
post-thumbnail

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)를 위한 라이브러리들 중 가장 유명한 두 라이브러리는 qsquerystring(표준 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 와의 연동입니다.

axiosget/delete 요청 시 param 을 설정에 넘길 수 있습니다.

axios.get('url', { params: a: [1, 2, 3] })

이 때 아무런 설정을 하지 않았다면 아래와 같이 직렬화됩니다.

url?a[]=1&a[]=2&a[]=3

만약 위의 기본 동작을 변경하고 싶다면 configparamsSerializer 를 사용할 수 있습니다.

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' 형태로 직렬화할 수 있습니다.

끝까지 읽어주셔서 감사합니다. 😄

profile
다양한 것들을 시도합니다

1개의 댓글

comment-user-thumbnail
2021년 6월 24일

Lambda 없이 express 에는 querystring가 배열로 그대로 잘 들어가는데, Lambda 에서는 왜 모두 인식이 되지 않는지 의문이었습니다.
귀찮아서 기록하지 않을 법 한 내용인데, 덕분에 도움받고 갑니다.

답글 달기