마이크로프론트엔드 CI/CD Pipelines 구축

Dan·2022년 11월 28일
1

웹팩

목록 보기
7/8
post-thumbnail

Micro-Frontend CI/CD

이제 마이크로 프론트엔드 서비스를 깃헙 action을 가지고 AWS에 배포를 자동화할 수 있도록 파이프라인을 구축해보도록 하자.

먼저 프로젝트마다 웹팩의 배포 환경을 설정해줘야 한다.

  • container/config/webpack.prod.js
const { merge } = require("webpack-merge");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const commonConfig = require("./webpack.common");
const packageJson = require("../package.json");

const domain = process.env.PRODUCTION_DOMAIN;

const prodConfig = {
  mode: "production",
  output: {
    filename: "[name].[contenthash].js",
    publicPath: "/container/latest/",
  },
  plugins: [
    new ModuleFederationPlugin({
      name: "container",
      remotes: {
        marketing: `marketing@${domain}/marketing/remoteEntry.js`,
      },
      shared: packageJson.dependencies,
    }),
  ],
};

module.exports = merge(commonConfig, prodConfig);

그리고 package.js 에서 빌드 커맨드를 설정해주자.

  • container/package.json
  "build": "webpack --config config/webpack.prod.js"

위와 똑같은 과정을 remote 프로젝트에도 설정을 해줘야한다.

  • marketing/config/webpack.prod.js
const { merge } = require("webpack-merge");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const packageJson = require("../package.json");
const commonConfig = require("./webpack.common");

const prodConfig = {
  mode: "production",
  output: {
    filename: "[name].[contenthash].js",
  },
  plugins: [
    new ModuleFederationPlugin({
      name: "marketing",
      filename: "remoteEntry.js",
      exposes: {
        "./MarketingApp": "./src/bootstrap",
      },
      shared: packageJson.dependencies,
    }),
  ],
};

module.exports = merge(commonConfig, prodConfig);

npm run build 커맨드를 통해 dist폴더가 잘 생성되는지 확인해볼 필요가 있다. 이제 프로젝트 레포에 소스를 푸시할 때마다 자동 배포가 되도록 설정을 해보자.

Github Actions

프로젝트 최상단에 아래와 같이 폴더를 생성하고 코드를 추가하자.

  • .github/workflows
# container actions
name: deploy-container

on:
  # container 폴더안에 있는 내용이 변경이 main 브랜치에 push 되었을 떄 발동 된다.
  push:
    branches:
      - main
    paths:
      - "container/**"

# container안에서 아래의 jobs에 해당하는 작업들이 이루어지며
defaults:
  run:
    working-directory: container

# aws s3에 해당하는 명령어들 추가
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: npm install
      - run: npm run build

      - uses: shinyinc/action-aws-cli@v1.2
      - run: aws s3 sync dist s3://${{ secrets.AWS_S3_BUCKET_NAME }}/container/latest
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
		  AWS_DEFAULT_REGION: ap-northeast-2

AWS Setup

AWS S3 Buckets

  1. 아마존 S3 콘솔 에 접속해서 버킷을 만들어주도록 하자.
  2. 만들어진 버킷 속성 들어가서 static website hosting에 index document를 index.html로 설정 하자.
  3. 버킷의 permission 탭의 Block public access (bucket settings)에 들어가서 아래와 같이 설정을 풀어주도록 하자.
  4. 버킷의 permission 탭의 Bucket policy 또한 생성/설정해주도록 하자.
    • actions 는 getObjects
    • ARN(Bucket policy에 잇는 ARN)값 + /*

AWS Cloudfront

  • Create distributions
  1. Origin Domain Name을 방금 만든 버킷으로 설정해준다.
  2. View Protocol Policy를 Redirect HTTP to HTTPS로 설정해준다.
  3. 생성한 distritubtion이 deployed 상태가 되면 general탭에서 Default Root Object를 /container/latest/index.html 로 설정해주도록 하자.
  4. error page 텝을 다음과 같이 수정해주자

AWS IAM

이제 깃헙 actions를 실행할 때 필요한 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_S3_BUCKET_NAME 를 IAM을 통해 발급받자.

  1. AWS IAM users에 접속하여 create user을 해준다.
  2. Set permissions에서 attach existing policies diretly 옵션을 통해 만들어주자.
  3. CloudFrontFullAccess 와 AmazonS3FullAccess를 policy로 넣고 user를 만들어주자.
  4. 생성된 user를 통해 access key id 와 secret access key를 사용할 수 있게 되었다.
  5. 프로젝트의 github repo의 settings에 들어가서 key를 아래 사진처럼 설정해주도록 하자.

그리고 container 폴더 내용을 조금 수정하고 push해보면 github actions가 성공적으로 도는것을 볼 수 있다. 하지만 새로운 소스를 올려도 배포된 소스가 최신화가 안되는 현상이 발생한다. 이를 해결하기 위해선 Cloudfront가 새로운 소스가 업데이트 될 때마다 index.html의 변화를 확인해서 업데이트하게 invalidations 옵션을 활성화 시켜줘야 한다.

아래 aws invalidtaions 설정을 추가해주도록 하자.

  • .github/workflows/container.yml
# container actions
name: deploy-container

on:
  # container 폴더안에 있는 내용이 변경이 main 브랜치에 push 되었을 떄 발동 된다.
  push:
    branches:
      - main
    paths:
      - "container/**"

# container안에서 아래의 jobs에 해당하는 작업들이 이루어지며
defaults:
  run:
    working-directory: container

# aws s3에 해당하는 명령어들 추가
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: npm install
      - run: npm run build
        env:
          PRODUCTION_DOMAIN: ${{ secrets.PRODUCTION_DOMAIN }}

      - uses: shinyinc/action-aws-cli@v1.2
      - run: aws s3 sync dist s3://${{ secrets.AWS_S3_BUCKET_NAME }}/container/latest
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-2

      - run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_DISTRIBUTION_ID }} --paths "/container/latest/index.html"
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-2

이걸로 컨테이너의 설정은 완성되었다. 이제 컨텐츠를 보여줄 수 있게 마케팅 프로젝트도 자동배포화를 설정해주자.

  • .github/workflows/marketing.yml
# marketing actions
name: deploy-marketing

on:
  # marketing 폴더안에 있는 내용이 변경이 main 브랜치에 push 되었을 떄 발동 된다.
  push:
    branches:
      - main
    paths:
      - "marketing/**"

# marketing안에서 아래의 jobs에 해당하는 작업들이 이루어지며
defaults:
  run:
    working-directory: marketing

# aws s3에 해당하는 명령어들 추가
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - run: npm install
      - run: npm run build

      - uses: shinyinc/action-aws-cli@v1.2
      - run: aws s3 sync dist s3://${{ secrets.AWS_S3_BUCKET_NAME }}/marketing/latest
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-2

      - run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_DISTRIBUTION_ID }} --paths "/marketing/latest/remoteEntry.js"
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-2
  • marketing/config/webpack.prod.js
const { merge } = require("webpack-merge");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const packageJson = require("../package.json");
const commonConfig = require("./webpack.common");

const prodConfig = {
  mode: "production",
  output: {
    filename: "[name].[contenthash].js",
    publicPath: "/marketing/latest/",
  },
  plugins: [
    new ModuleFederationPlugin({
      name: "marketing",
      filename: "remoteEntry.js",
      exposes: {
        "./MarketingApp": "./src/bootstrap",
      },
      shared: packageJson.dependencies,
    }),
  ],
};

module.exports = merge(commonConfig, prodConfig);
profile
만들고 싶은게 많은 개발자

0개의 댓글