서론 (들어가기 앞서)
- 현재 제가 재직 중인 회사는 온라인 강의 서비스와 커뮤니티 서비스를 운영합니다. 저희 고객 분들은 온라인으로 줌 강의를 수강하고, 모임 인증 사진을 커뮤니티에 사진을 업로드하곤 합니다. 문제는 모임이 끝나는 시점에 여러 명의 사용자가 동시 다발적으로, 동시에 업로드를 진행한다는 점입니다. 이로 인해 짧은 시간에 서버로 부하가 몰렸습니다. 특히 독서모임 등 1000명 가량의 인원이 동시에, 강의를 같은 시간에 수강한 이후, 인증을 진행하는 경우, 504 Timeout 에러로 인해 업로드 자체가 실패하는 경우도 많았습니다.
- 현재 AWS S3 서비스를 이용 중인데, 기존에는 S3로 파일을 업로드할 때 WAS를 경유하는 구조였습니다. 특히 요청이 밀리다보면 뒤 요청은 TimeOut 에러로 인해, 아예 처리되지 않는 문제가 발생했습니다. 프론트엔드 서버에서부터 백엔드 서버, S3로 업로드 하는 각 단계에서 네트워크 송/수신을 처리하기 위한 시간이 들며, 업로드를 처리하는 평균 속도가 1초 정도로 느린 편이었습니다. 이로 인해 해당 이벤트가 있는 날, 별도의 백엔드 서버(WAS) 증설을 해야 했습니다.
실제 이벤트가 있었던 날의 데이터
7/18(목) 기준
- 호출횟수 : 4500번 호출
- 소요시간 : 평균 1초 소요, 최대 100초 소요
- 합계 처리시간 : 92분 소요
- 이전에는 사용자가 파일을 업로드하기 위해 프론트엔드 -> 백엔드(WAS) -> S3로 파일을 전송하는 구조였습니다. 이 과정에서 WAS가 모든 업로드 요청을 처리하느라 부하가 집중되어, 대량의 요청이 들어오는 시간에 서버가 과부하에 걸리게 되었습니다.
- 이를 PresignedUrl을 활용하여 WAS를 거치지 않고 클라이언트에서 S3 파일을 직접 업로드함으로써 서버 부하도 줄이고, 서버에서 S3로 통신하는 과정을 줄임으로써, 업로드 API의 성능도 개선할 수 있었습니다. 오늘은 이 PresignedUrl에 무엇이며, 위 문제를 해결할 수 있었던 배경에 대해서 자세하게 알아보도록 하겠습니다.
성능개선 결과
이러한 결과로, 아래와 같은 결과를 낼 수 있었습니다.
API 응답 시간 개선과 원활한 모니터링
기존에는 파일업로드 API가 응답속도가 느린 API TOP 100 중 90% 이상을 차지할 정도로, 속도가 느리며, 자주 호출되는 API 였습니다. 적용 전 10개 파일을 업로드하는 시간이 1초였으나, 적용 후에는 업로드까지 평균 0.2초로 5배 향상되었습니다. 개선 이후, 다른 느린 API 모니터링이 횔씬 수월해지며, 문제가 되는 케이스를 횔씬 빠르게 확인할 수 있게 되었습니다. 또한 피크 트래픽이 요청이 몰리며 1~20초가까지 걸리던 요청들 역시도 0.5초 이내에 처리됨으로써 최대 50배 가까운 성능 개선효과가 있었습니다.
비용 절감 효과 및 개발자 리소스 감소
기존에는 이벤트 대응을 위해 FE/BE/RDS까지 별도로 각각 5대, 5대, 3대 증설하였습니다. 그렇지만 해당 작업을 통해, 평시 스펙으로도 이벤트에 대응 할 수 있게 되었습니다. 57% 가량 클라우드 사용 비용을 줄일 수 있게 됐습니다. 또한 별도의 서버 증설 없이, 평시 스펙으로 작업 가능하여 모니터링 및 증설/감축에 드는 별도의 리소스 필요 없어져, 지표 개선 및 다른 기술부채 업무에 집중할 수 있게 되었습니다.
에러율 감소 및 사용자 만족도 향상
적용 전에는 트래픽이 급격히 몰리는 시기에, 1% 가량의 높은 에러율을 보였으나, 적용 후에는 0.0001% 미만으로 감소했습니다. 업로드 속도 향상 및 에러율 감소를 통해, 사용자 만족도가 높아졌습니다. 실제로, 매번 만족도 조사에서 빠짐 없이 등장하던 다량의 이미지를 동시다발적으로 올리는 게 불편하다는 VOC가 많았으나, 이번 개선 작업 이후 그러한 VOC는 한 건도 인입되지 않았습니다.
서버 부하 감소
Presigned URL 적용 전에는 서버가 모든 파일 업로드 요청을 처리해야 했지만, 적용 후에는 클라이언트가 직접 S3에 업로드하여 서버의 CPU 및 메모리 사용량이 현저히 감소했습니다.
이러한 성과를 낼 수 있었던 Presigned URL에 대해 알아봅시다. Presigned URL이 뭘까요? Presigned URL은 AWS S3를 대표로, 여러 클라우드 제공 업체에서 제공하는 기능입니다. Azure에서는 SAS (Shared Access Signature)라는 이름으로, Google Cloud에서는 Signed URL이란 이름으로 기능을 제공합니다.
PresignedUrl 이란
Presigned URL은 특정 사용자에게 제한된 시간 동안 유효한 URL을 제공하여, 클라이언트가 해당 URL을 통해 파일을 직접 클라우드 스토리지에 업로드하거나 다운로드할 수 있도록 하는 방식입니다. 일반적으로 서버를 거치지 않고 클라이언트와 스토리지 간 직접적인 파일 전송이 이루어지기 때문에 서버의 부담을 줄일 수 있습니다.
장점
- 서버 부하 감소 : 파일을 클라이언트가 직접 S3와 같은 클라우드 스토리지로 전송하기 때문에 서버 리소스 사용을 최소화 할 수 있습니다.
- 보안 : Presigned URL에는 유효 기간이 있고, 이 기간이 지나면 URL이 만료되어 더 이상 접근할 수 없습니다. 또한, 특정 권한을 설정할 수 있어 필요한 작업에만 제한적으로 사용됩니다.
- 효율성 : 파일을 업로드할 때, WAS를 거치지 않고 직접 스토리지 서비스로 전송하다보니, 네트워크 자원을 최적으로 사용할 수 있습니다. 특히 대용량 파일을 처리할 때 유용합니다.
사용 사례
주요한 사용 사례는 다음과 같습니다.
동시 요청자 수가 많은 어플리케이션의 미디어 파일 업로드
Instagram과 같이, 동시 접속자가 많은 소셜 미디어 앱에서도 presigned URL을 적극 활용 할 수 있습니다. 클라이언트가 사진이나 동영상을 클라우드 서버에 직접 업로드함으로써, 동시 요청 처리량을 높일 수 있습니다. 2가지 측면에서 장점이 있습니다. 첫번째론 API 서버 측면, 두번째론 클라우드 스토리지 측면입니다. 전자에선 서버가 presigned URL 생성에만 관여하기 때문에, 부하가 크지 않습니다. 후자에선 AWS S3와 같은 스토리지 서비스에선 수백만 건의 동시 파일 업로드를 처리할 수 있는 자동 확장성을 제공하므로, 이론적으로 동시 요청의 한계가 거의 없습니다.
대용량 파일 업로드
실제 저희 고객 분들은 부동산 임장을 다녀 온 후, 30-50 페이지에 달하는 임장보고서를 작성하여 업로드 하는 경우가 있습니다. 이 때, 파일 용량은 1GB에 달합니다. 이 때, Presigned URL을 사용해 파일을 S3 같은 스토리지에 직접 업로드하게 하여, 서버는 파일 자체를 처리하지 않고 URL 생성과 인증만 담당합니다. 서버 부하가 줄어들고 클라이언트가 직접 스토리지에 파일을 전송할 수 있어 성능이 향상될 수 있습니다. 실제, 저희 회사 외에도 Youtube나 Vimeo 같은 서비스에서는 특히, 큰 용량의 비디오 파일을 처리해야 하므로, 스토리지 서버에 직접 업로드 하는 것이 효율적일 것 입니다.
제한된 시간 동안의 안전한 파일 공유
저희 서비스에서도 강의를 결제한 고객들만 볼 수 있는 자료들이 있습니다. 이러한 자료들은 Public bucket 안에 보관하지 않고 Private bucket에 보관합니다. 이 때, PresignedUrl을 활용하여, 제한된 시간 동안 파일에 접근 가능한 링크를 제공할 수 있습니다. 일정 시간이 지나면, 링크가 더 이상 유효하지 않기 때문에, 보안을 높일 수 있습니다. 그 외에도 법률 문서, 의료 기록, 계약서와 같은 민감한 데이터를 클라이언트와 한정된 시간 동안만 공유하고 싶을 때, 활용할 수 있습니다.
파일 업로드 기본 흐름
Presigned URL을 활용한 파일 업로드의 흐름은 다음과 같습니다. 이론만 다루면 아쉬우니, 실습까지 원하시는 분들은 아래 링크를 참고해주시기 바랍니다.
- 클라이언트가 파일 업로드 요청: 사용자가 파일을 업로드하려는 요청을 서버에 보냅니다.
- 서버에서 Presigned URL 생성: 서버는 클라이언트의 요청을 받아 AWS S3와 같은 스토리지에 파일을 업로드할 수 있는 Presigned URL을 생성합니다.
- 클라이언트에 Presigned URL 반환: 서버는 생성된 URL을 클라이언트에 반환합니다.
- 클라이언트가 URL을 통해 파일 업로드: 클라이언트는 해당 URL을 이용해 직접 S3에 파일을 업로드합니다.
- 업로드 완료 후 확인 작업: 클라이언트는 업로드가 성공적으로 완료되었는지 확인하고, 필요한 후속 처리를 합니다.
단점
그렇다면 장점만 있는 걸까요? 몇 가지 한계점이 존재합니다.
- 서버 측에서의 추적 및 모니터링의 어려움 : 파일 업로드 실패와 같은 문제를 서버 측에서 실시간으로 추적하고 모니터링하기 어렵기 때문에, 실패를 감지하고 알리거나 필요한 로깅을 수행하는 데 제한이 있습니다. 현재 기업에서는 프론트엔드 서버 모니터링이 제공되어, 추적을 대체하여 추적이 가능했습니다.
- URL 탈취 가능성 존재 : PresignedUrl에 1분이라는 짧은 시간을 부여했지만, 해당 URL이 해커로 인해 탈취된다면 보안 상 문제가 발생할 수 있습니다. HTTPS 적용이 되어 있어, 보안 리스크를 해소 할 수 있었습니다.
- 후속 작업 처리의 어려움 : 후속 작업을 처리하기 어렵습니다. 가령 업로드된 이미지를 리사이징하거나 다른 서비스에 알람을 보내는 등의 작업을 처리할 수 없습니다. 또한 실패 후 재처리 로직 등도 클라이언트에서 처리해줘야 합니다.
결론
Presigned URL을 사용한 파일 업로드 방식을 통해, 클라이언트가 서버를 거치지 않고 AWS S3와 같은 스토리지에 직접 파일을 업로드할 수 있었습니다. 클라이언트-서버 간 네트워크 부담을 줄이고, 서버에서 복잡한 파일 관리 로직을 최소화함으로써, 비즈니스에 효과적으로 대응할 수 있었습니다. 이 글을 읽는 분들께서도 비슷한 상황이라면, 고려해보시는 것을 권해봅니다.
'Infra' 카테고리의 다른 글
간단하게 실습하며 배우는 Kubernetes와 Terraform (1) 로컬 Kubernetes 클러스터에 웹 서버 배포 자동화하기 (0) | 2025.02.08 |
---|
댓글