포스트

2023-11-17-TIL

2023-11-17-TIL

Today I Learned

File Upload with Presigned URL

pre-signed URL로 클라이언트가 S3에 직접 올리게 하는 구조를 Lambda와 함께 구성하는 예제를 모았다. AWS 코리아 블로그의 흐름은 두 단계다. 프런트엔드가 API Gateway 엔드포인트를 호출하면 Lambda가 서명된 URL을 받아 돌려주고, 프런트엔드가 그 URL로 S3에 파일을 직접 올린다. 애플리케이션 서버는 파일 바이트를 전혀 거치지 않는다.

koo8624의 글은 URL의 구조를 보여 준다. 접근 대상과 만료 시간 같은 조건이 쿼리 스트링(X-Amz-Algorithm, X-Amz-Credential, X-Amz-Expires, X-Amz-Signature 등)에 들어 있고, S3는 서명을 다시 계산해 요청이 변조되지 않았는지 확인한다. URL 자체에 권한이 담긴 stateless 방식이라 만료 전에는 여러 번 쓸 수 있다는 점이 글의 출발점이고, 한 번만 쓰도록 강제하는 방법을 다룬다.

  • https://www.youtube.com/watch?v=gBkYaWfnUjg
  • https://www.youtube.com/watch?v=co4iQUgT2ZY
  • https://www.youtube.com/watch?v=ozX3GbUOfF8
  • https://m.blog.naver.com/demonic3540/221635831475
  • https://aws.amazon.com/ko/blogs/korea/uploading-to-amazon-s3-directly-from-a-web-or-mobile-application/
  • https://velog.io/@kyy00n/AWS-S3-Lambda%EB%A1%9C-Presigned-url-%EB%B0%9C%EA%B8%89%ED%95%B4-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EA%B0%80-%EC%A7%81%EC%A0%91-%EB%B2%84%ED%82%B7%EC%97%90-%EA%B0%9D%EC%B2%B4-%EC%97%85%EB%A1%9C%EB%93%9C%ED%95%98%EA%B2%8C-%ED%95%98%EA%B8%B0
  • https://burning-camp.tistory.com/43
  • https://velog.io/@koo8624/AWS-Presigned-URL-%ED%95%9C-%EB%B2%88%EB%A7%8C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8F%84%EB%A1%9D-%EA%B0%95%EC%A0%9C%ED%95%98%EA%B8%B0
  • https://medium.com/@andrew.s.trigg/using-aws-lambda-to-generate-presigned-urls-c88f01dd867e
  • https://medium.com/@andrew.s.trigg/using-aws-lambda-to-generate-presigned-urls-c88f01dd867e

AWS Lambda

Lambda 개발자 가이드는 Lambda를 서버를 프로비저닝하거나 관리하지 않고 코드를 실행하는 서버리스 컴퓨팅 서비스로 소개한다. 서버 유지보수, 용량 확보, 확장, 패치 같은 인프라 관리는 Lambda가 맡고, 개발자는 이벤트를 처리하는 함수만 작성한다. API 요청, S3 업로드, 큐 메시지 같은 이벤트가 오면 함수가 실행된다.

Go로 작성할 때는 aws-lambda-go 라이브러리를 쓴다. Go 핸들러 문서에 따르면 핸들러는 이벤트를 처리하는 함수이고, 함수는 핸들러가 응답을 반환하거나 종료하거나 시간이 초과될 때까지 실행된다. main()에서 lambda.Start에 핸들러를 넘기면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
	"context"
	"github.com/aws/aws-lambda-go/lambda"
)

type Request struct {
	FileName string `json:"fileName"`
}

func handleRequest(ctx context.Context, req Request) (string, error) {
	return "presigned url for " + req.FileName, nil
}

func main() {
	lambda.Start(handleRequest)
}
  • https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/welcome.html
  • https://seoyeonhwng.medium.com/aws-lambda%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-44df535d5487
  • https://aws.amazon.com/ko/lambda/features/
  • https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/golang-handler.html
  • https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/lambda-golang.html
  • https://github.com/aws/aws-lambda-go
  • https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html
  • https://velog.io/@donggni0712/GoLang-DynamoDB%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%B4-Lambda-%EC%84%9C%EB%B2%84%EB%A6%AC%EC%8A%A4-%EA%B5%AC%EC%B6%95%ED%95%B4%EB%B3%B4%EA%B8%B0
  • https://www.softkraft.co/aws-lambda-in-golang/
  • https://www.youtube.com/watch?v=BcoekcPRKWc
  • https://www.youtube.com/watch?v=13rnse0zYK8
  • https://docs.aws.amazon.com/lambda/latest/dg/getting-started.html

Serverless

서버리스는 서버가 없다는 뜻이 아니라, 서버의 프로비저닝과 확장, 운영을 클라우드 제공자가 맡고 사용자는 코드와 설정만 다룬다는 뜻이다. 요청이 없으면 자원을 쓰지 않고, 요청량에 맞춰 자동으로 늘어난다. AWS의 서버리스 서비스 선택 가이드는 Lambda 같은 컴퓨팅뿐 아니라 API Gateway, S3, DynamoDB, SQS처럼 운영 부담 없이 조합할 수 있는 서비스들을 서버리스 구성 요소로 함께 다룬다. 실행 시간 제한과 콜드 스타트, 디버깅의 어려움은 감수해야 한다.

  • https://docs.aws.amazon.com/serverless/latest/devguide/welcome.html
  • https://frozenpond.tistory.com/181

Multipart Size Limit

Spring Boot로 파일을 받으면 업로드 크기 제한에 먼저 걸린다. Spring Boot 설정 문서 기준으로 두 속성이 있다.

  • spring.servlet.multipart.max-file-size: 파일 하나의 최대 크기다. 기본값은 1MB다.
  • spring.servlet.multipart.max-request-size: multipart 요청 전체의 최대 크기다. 기본값은 10MB다.

park2348190의 글이 둘의 차이를 실험으로 확인한다. 파일 하나하나가 max-file-size 이하여도 합계가 max-request-size를 넘으면 요청이 거부되고, 파일 하나가 max-file-size를 넘으면 합계와 상관없이 거부된다. 기본 1MB는 이미지 한 장도 넘기기 쉬우므로 대부분 조정해야 한다. 위의 pre-signed URL 방식을 쓰면 파일이 애플리케이션 서버를 거치지 않으므로 이 제한과 무관해진다.

1
2
spring.servlet.multipart.max-file-size=20MB
spring.servlet.multipart.max-request-size=100MB
  • https://velog.io/@park2348190/MultipartProperties%EC%9D%98-max-file-size-max-request-size%EC%9D%98-%EC%B0%A8%EC%9D%B4
  • https://stackoverflow.com/questions/34177873/max-limit-of-multipartfile-in-spring-boot
  • https://gksdudrb922.tistory.com/230
이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다