AWS 서버비용절감 계획 및 기록 (2) - AWS S3, CloudFront
웹 프로그래밍/배포

AWS 서버비용절감 계획 및 기록 (2) - AWS S3, CloudFront

728x90
반응형

1. 구조 변화

계속 EC2를 사용해왔기에 Lamda의 구조가 잘 그려지지 않는다. 원래의 구조와 비교하여 생각해보려한다.

 

1) 기존구조

: React + DRF + Docker Swarm on EC2

  • React: 앱을 정적파일로 빌드하고 Nginx 컨테이너로 제공함.
  • DRF로 API 제공. /api 엔드포인트로 통일시켜둬서 이걸로 구분하고 Nginx를 이용해 서빙함.
  • Docker Swarm: EC2에서 컨테이너 오케스트레이션 및 확장성을 관리함.

 

2) Lambda로 전환 이후

: Lambda는 서버리스 기반이다.

  • React는 정적파일로 빌드하고 S3와 CloudFront를 사용해서 배포한다. CloudFront는 CDN으로 사용자에게 빠르게 전달.
  • DRF를 Lambda 함수로 분리해서 서버리스로 전환

 

2. Frontend 배포설정(S3, CloudFront)

 1) S3 버킷생성

버킷명은 글로벌리전에서 고유해야한다. Next.js 기반의 앱을 배포할 계획이므로, pnpm run build를 수행해 정적파일을 만들어주었다.

그리고 버킷에 /static, prerender-manifest.json을 올려주었다.

pnpm next build 수행하여 /out을 올렸다. 

S3 버킷

output: export 설정과 assetPrefix 설정을 위해서 next.config.mjs를 추가 설정했다.

  • /out 폴더를 그대로 S3에 업로드했으므로 경로는 /out/index.html이다. cdnUrl에 /out을 추가해줘야 들어감. 이걸 해줌으로써 build했을때 영향은 index.html에서 link경로에 전부 cdnUrl이 포함된다는 것.
  • 이미지도 public에 있는 이미지를 전에는 기본경로에서 가져왔는데, 이러면 경로를 찾을 수 없으니 우선은 process.env.NODE_ENV로 development일때와 아닐때를 분리해 경로 하드코딩했다. 
// @ts-check
import { PHASE_DEVELOPMENT_SERVER } from 'next/constants.js';

export default (phase) => {
  const isDev = phase === PHASE_DEVELOPMENT_SERVER;

  const cdnUrl = 'https://d3h0ehcnk39jwg.cloudfront.net/out';

  /**
   * @type {import('next').NextConfig}
   */
  const nextConfig = {
    assetPrefix: isDev ? undefined : cdnUrl,

    async rewrites() {
      return [
        {
          source: '/api/:path*/',
          destination: 'http://localhost:8000/api/:path*/',
        },
        {
          source: '/media/:path*/',
          destination: 'http://localhost:8000/media/:path*/',
        },
        {
          source: '/cdn/media/:path*/',
          destination: `${cdnUrl}/media/:path*/`,
        },
      ];
    },

    async headers() {
      return [
        {
          source: '/api/:path*/',
          headers: [
            {
              key: 'Access-Control-Allow-Origin',
              value: '*',
            },
            {
              key: 'Access-Control-Allow-Methods',
              value: 'GET, POST, PUT, DELETE, OPTIONS',
            },
            {
              key: 'Access-Control-Allow-Headers',
              value: 'Content-Type, Authorization',
            },
          ],
        },
        {
          source: '/cdn/media/:path*/',
          headers: [
            {
              key: 'Access-Control-Allow-Origin',
              value: '*',
            },
            {
              key: 'Access-Control-Allow-Methods',
              value: 'GET, OPTIONS',
            },
          ],
        },
      ];
    },

    output: 'export',
    trailingSlash: true,
  };

  return nextConfig;
};

 

 

2) CloudFront

 

설정기록

원본엑세스는 "원본엑세스 제어 설정"으로 설정하고, http 설정은 https 리다이렉션없이 둘다 사용으로 설정했다.

리전설정은 아시아를 포함한 영역으로 설정해뒀다.
S3를 여러번 수정하면서 캐시 무효화가 필요했는데 무효화설정에서 /*로 캐시를 전부 미사용 설정했다.

 

3) 기본 루트 객체는 out/index.html로 설정했다.

 


/out을 통째로 넣었다가 아이콘 경로 문제가 발생했다. 기본 루트객체를 out/index.html로 잡아야 시작화면이 index로 갈텐데 그런 경우에 같은 깊이에 있는 다른 이미지 경로가 무시되는 현상이 발생했다. S3에 정적파일과 화면들을 out을 벗겨서 올리고, 기본 루트객체를 index.html로 주어 수정했다.

728x90
반응형