문제점

현재 웹서비스를 이용하려면 클라이언트가 200MB가 넘는 파일을 node.js로부터 전송받고 있다. node.js 는 싱글스레드이다. 이러한 단일 처리가 오래 걸리는 대용량 파일 전송은 적합하지 않기 때문에 빨리 대책을 모색하고자 했다. 수치적으로 보이는 문제점이 아래와 같았다.

높은 CPU 사용량

단일 클라이언트가 204MB 파일을 요청해 node.js 가 response 해주는데 CPU 사용량이 순간적으로 121% 까지 치솟는다. 눈대중으로 봐도 엄청난 과부하가 발생되는 것을 확인할 수 있다. 단 한 명의 클라이언트의 단 한 번의 요청으로 121%까지 치솟는 건 엄청난 문제가 아닐 수 없다. 만약 동시에 여러 명의 클라이언트가 동시에 요청을 한다면 서버가 어떻게 됐을지 상상이 가지 않는다. 물론 node.js는 싱글 스레드이기에 여러 요청이 들어와도 하나씩 처리하지만 단일 요청에 100%가 넘는 CPU 사용량은 엄청난 문제점을 가지고 있다는 경각심을 가지게 되었다.

느린 전송 속도

해당 사이트는 웹 기반의 그래픽 서비스를 제공하고있어 대용량의 WebGL.data를 받아야 한다. 위 사진을 보면 클라이언트가 응답받는 204MB 크기의 WebGL.data 파일을 다운로드하는데 1.3분이 소요된다. 그럼 사용자는 약 80초동안 로딩 화면을 바라보고 있어야 한다. 이로 인해 서비스 이탈률이 증가하고 좋지 못한 사용자 경험을 제공한다.

해결책

물론 위와 같은 문제점들도 한번 다운로드가 완료된다면 캐시에 저장되어 ms 단위로 로드가 끝나게 된다. 하지만 서비스의 첫 경험부터 1분 이상을 기다리게 된다면 나였어도 서비스를 이탈하게 될 것이다. 그리고 현재 사용하는 EC2 t3.medium의 네트워크 대역폭의 문제도 있었다. 물론 AWS 공식문서에는 5 Gbps라고 쓰여있지만 실제로는 1 Gbps 도 나오지 않는다.

EC2 인스턴스 종류별 네트워크 대역폭 참고 자료
[소개] AWS EC2 Network성능에 대해

그래서 node.js 에서 용량이 큰 파일을 전송하는 것은 무리라고 판단했다. 따라서 대용량 파일 배포에 걸맞은 AWS S3를 사용해보고자 한다.

구현

S3 bucket 만들기

새로운 버킷을 생성한다. 기본 값으로 생성하되 원활한 테스트를 위해 퍼블릭 액세스 차단을 모두 설정 해제한다.

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET",
            "HEAD"
        ],
        "AllowedOrigins": [
            "*"
        ],
        "ExposeHeaders": [
            "x-amz-server-side-encryption",
            "x-amz-request-id",
            "x-amz-id-2"
        ],
        "MaxAgeSeconds": 3000
    }
]

그 후 버킷 -> 권한 -> CORS의 설정을 위의 Json으로 수정한다.
(만약 바로 테스트할 URL이 있다면 AllowedOrigins에 "*" 값을 본인 URL로 수정한다.)

CloudFront Distribution 생성

그 후 CloudeFront에서 Create Distribution 하여 새로운 Distribution을 만든다. 설정은 위와 같이 새로 만든 버킷을 선택한 뒤 Restrict Bucket Access를 Yes로 설정하여 S3 Policy를 자동으로 수정하게 한다.

그리고 하단부에 Price Class는 Use All Edge Locations를 설정하고 distribution을 생성한다.

생성한 Distributions를 바로 확인하면 Status 가 In Progress 상태인데 약 2~3분 뒤면 Deployed 상태가 될 때까지 기다린다.

테스트

테스트를 위해 먼저 S3 bucket에 테스트할 파일을 위와 같이 업로드한다. 그리고 앞서 만든 Distribution의 도메인 주소 뒤에 업로드한 파일 이름을 적는다.

예시
http://d3dte465uzyglx.cloudfront.net/logo.png

만약 오브젝트가 S3 bucket 폴더 안에 있다면 URL + /폴더이름/logo.png 식으로 접속하면 정상적으로 확인할 수 있다.

적용

이제 S3와 CloudFront 를 사용하여 앞에서 언급한 200MB가 넘는 WebGL 파일을 클라이언트로 배포하였다. 이제 다시 테스트를 진행했다.

CPU 사용량

대용량의 파일을 보내는 과부하를 S3 가 도맡아 하기 때문에 보다시피 CPU 사용량은 121% -> 3% 로 대폭 줄은 것을 확인할 수 있다.

전송 속도

그리고 다운로드 속도도 훨씬 증가한 모습을 볼 수 있다. S3와 CloudFront의 빠른 전송속도로 204MB의 파일을 다운로드하는데 78s -> 12.9s로 엄청나게 빨라진 결과를 볼 수 있다. 다운로드 속도는 2.6 Mbps에서 15 Mbps로 증가했고 약 576% 증가된 성능을 보인다.