Showing posts with label nodejs. Show all posts
Showing posts with label nodejs. Show all posts

Thursday, December 26, 2019

AWS API Gateway와 Lambda를 이용한 Multipart 데이터 업로드 문제 해결

AWS API Gateway와 Lambda를 이용한 Multipart 데이터 업로드 문제 해결

AWS API Gateway와 Lambda(Node.js)를 사용하여 multipart 데이터를 업로드하는 방법에 대해 여러가지 방식을 찾아보았습니다. 제가 이전에 작성한 내용이 있으니 아래 링크를 참고하시면 도움이 될 것입니다.

AWS API Gateway + Lambda Multipart/Form-data

그런데 위에서 설명한 방식으로 설정을 하니, 일반 텍스트 필드와 이미지 파일이 함께 업로드되면 오류가 발생했습니다. 설정이나 전송 과정에서 문제가 있는 줄 알고 몇일 동안 고민하며 다양한 테스트를 진행했지만, 해결하지 못했습니다.

결국 사용하던 'parse-multipart' 패키지의 내용을 확인해보니, 해당 패키지는 파일만 지원하는 것이었습니다. 따라서 다른 패키지인 lambda-multipart-parser를 사용하여 다시 구성하기로 결정했습니다.

Lambda multipart upload example
Lambda에서의 multipart 데이터 업로드 예시

다만 대부분의 예제들은 API Gateway에서 Lambda proxy를 사용하는 경우였습니다. 그래서 Proxy를 사용하지 않는 제 경우처럼 구성해야 하는 분들을 위해 간략하게 구성 방법을 설명합니다. 우선, API Gateway 설정은 위 링크대로 하시면 되고, Lambda에서는 위 이미지와 같이 작성하면 됩니다.

Saturday, May 11, 2019

AWS Lambda와 API Gateway 활용, S3에 Multipart 이미지 업로드 시 파일 깨짐 문제 해결

AWS API Gateway와 Lambda
AWS API Gateway와 Lambda

서비스 개발 중에 클라이언트에서 multipart로 사진을 AWS Lambda로 보내고, Lambda에서 S3로 다시 사진을 업로드하는 작업이 필요했습니다. Flutter를 이용해 서비스를 개발하려 했으나 아직 Flutter용(dart) SDK가 없어서 우리쪽 서버를 거쳐서 보내기로 결정했습니다.

미디어 타입 설정

Lambda 코드 작성 전에 API gateway에서 미디어 타입을 추가해야 합니다.

API Gateway 미디어 타입 설정
API Gateway에서 미디어 타입 설정하기

코드 작성 및 팁 공유

인터넷에서 여러 자료를 참고하여 아래와 같은 코드를 작성했습니다. 이 예제는 여러 장의 사진을 받아 1장만 S3로 업로드하는 방법입니다. 한 가지 팁으로는, AWS SDK가 이미 설치되어 있으므로 별도의 설치가 필요하지 않다는 점입니다.


//const AWS = require('aws-sdk');
const multipart = require('parse-multipart');
exports.handler = (event, context, callback) => {
    const s3 = new AWS.S3({
        credentials: {
            accessKeyId: 'your accessKeyId',
            secretAccessKey: 'your secretAccessKey',
        },
        params: { Bucket: 'your Bucket' }
    });

    let bodyBuffer = Buffer.from(event['body-json'], 'base64');
    let boundary = multipart.getBoundary(event.params.header['content-type']);
    let parts = multipart.Parse(bodyBuffer, boundary);
    let data = {
        Key: 'your path',
        Body: parts[0].data,
        ContentEncoding: 'base64',
        ContentType: 'image/jpeg'
    };

    s3.putObject(data, function (err, data) {
      if (err) {
          callback(null, err);
      } else {
          callback(null, data);
      }
   });
};

테스트 및 문제 해결


<html>
<body>
<form action="https://your-url" enctype="multipart/form-data" method="post">
    <input multiple="" name="body-json" type="file" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

위와 같이 웹페이지를 만들어 테스트를 진행했지만 어떤 때는 동작하고 어떤 때는 동작하지 않는 이상한 상황이 발생했습니다. 원인을 찾기 위해 여러 가지 시도를 해봤지만 결국 문제의 원인은 웹에서 보낼 때 캐릭터셋 지정이 없어서 한글 파일의 경우 파일명이 깨지고 전송 후에 파일 자체가 깨지는 것이었습니다. 이를 해결하기위해 form 태그 안에 accept-charset="UTF-8"속성을 추가하고 다시 테스트해 보니 문제가 해결되었고, S3 업로드도 잘 실행되었습니다.


<html>
<body>
<form action="https://your-url" enctype="multipart/form-data" method="post" accept-charset="UTF-8">
    <input multiple="" name="body-json" type="file" />
    <input type="submit" value="Submit" />
</form>
</body>
</html>

사실상 코드는 큰 문제가 없었는데 캐릭터셋을 생각하지 못하고 코드 문제인 줄 알아서 이것저것 시도하느라 시간을 많이 잡아먹었습니다. 혹시 같은 작업이나 비슷한 문제를 겪는 사람들에게 조금이라도 도움이 되길 바랍니다.

참고 : 여러 형식의 파일 multipart upload 방법(https://blogdeveloperspot.blogspot.com/2019/12/aws-apigateway-lambdanodejs-multipart.html)

Thursday, December 27, 2018

AWS Lambda에서 Node.js에 Firebase 패키지 설치 문제 해결 방법

AWS Lambda에서 Node.js에 Firebase 패키지 설치 문제 해결 방법

AWS Lambda에서 Node.js 환경으로 설정하고 Firebase 패키지를 사용하는 과정에서 문제가 발생하는 경우가 있습니다. 이 문제를 해결하기 위한 방법을 알아보겠습니다.

문제 상황

AWS Lambda에 Node.js 8.10 환경으로 세팅하고 여러 패키지를 zip 파일로 업로드하는 중에 Firebase 패키지 설치에 문제가 발생합니다. 구글링 결과, 대부분의 경우 'npm rebuild' 명령어를 사용하여 해결할 수 있다고 언급하지만, 해당 방법으로는 문제가 해결되지 않았습니다.

https://github.com/grpc/grpc-node/issues/121 링크에서 확인한 바에 따르면, 버전 호환성 문제일 수 있습니다. 따라서 Firebase 패키지의 버전을 명시적으로 지정하여 설치해야 합니다. 현재 설치된 Node.js 버전은 8.10입니다.

해결 방법

위 링크에서 제시된 내용을 참고하여 npm을 사용하여 firebase@4.12.1 버전을 명시적으로 설치하면 문제가 해결됩니다. 아마도 Node.js와 Firebase 패키지 간의 버전 호환성 문제일 것입니다. 비슷한 문제를 겪는 사람들은 버전을 체크해보는 것이 좋습니다.