K8s에 Next.js CDN 구성과 무중단 배포 전략 (3)

1편에서는 Kubernetes에서 Next.js를 배포할 때 무중단 배포가 어떤 것인가에 대해서 다루었습니다. https://x2bee.tistory.com/462

2편에서는 무중단 배포 중 정적인 파일을 CDN에 올려서 하는 방법에 대해서 다루었습니다. https://x2bee.tistory.com/459

3편에서는 2편에서 적용한 무중단 배포 후 public 폴더의 처리에 대해서 다루겠습니다.

문제점

무중단 배포를 위해 static files를 아래처럼 CDN url로 바라보게 하기 위해 next.config.js에 코드를 넣었다.

  assetPrefix: (() => {
    switch (process.env.APP_ENV) {
      case 'stage':
        return 'https://cdn.example.co.kr/stg_files/x2bee-fo-cdn'
      case 'production':
        return 'https://cdn.example.co.kr/files/x2bee-fo-cdn'
      default:
        return ''
    }
  })()

(참고로 위에 NODE_ENV를 APP_ENV로 customizing한 코드는 생략)

아무튼 정적인 파일(.css, .js파일들)은 잘 동작하지만, .css에서는 문제가 생겼다.

퍼블리셔가 icon들의 이미지 파일을 '/public'에 넣어놓고, '/src'폴더에 있는 .css 파일에 이를 참조하기 위해 아래와 같은 경로로 코딩을 해놓았다.
예를들어 아래 src/assets/styles/common/icon.css 파일의 일부

.icon-arrow-right-12 {
  background-image: url('/images/icons/common/ico_chevron_right_all_12.svg');
}

일반적인 경우 위 코드를 build하면 /public 폴더를 바라보게되어 브라우저에서 http://example.co.kr/images를 바라보지만,
위에서 설정해 준 assetPrefix는 빌드 프로세스에 globally 적용되어 위 .css파일을 import 해 올 때 Next.js에 내재된 CSS loader를 통해 /로 시작하는 URL을 CDN주소로 prefix로 붙어 rewrite 된다.

즉, 다시 말하면 배포 후에, https://example.co.kr/images 를 바라보아야하지만 https://cdn.example.co.kr/images을 바라본다는 것이다.

게다가 또 하나의 문제는 여러가지 이유로 인해 CDN의 root에 images folder를 우리팀이 쓸 수 없다. files라는 폴더에 넣어야한다.

일단은 그 폴더에 이미지들이 있으니 우선 public 폴더의 이미지들을 CDN에 올려놓는다. 

 

그리고 이제 해결방법은 3가지 정도가 있을 수 있다.

1번 방법: CSS 파일에 적용 url('/images'로 시작되는 경로는 위에 next.config.js에 설정된 assetPrefix를 거치지 않게 하는 것이다. 그래서 cdn.example.com이 아닌 그냥 example.com (즉 localhost)를 바라보게 하는 것이다. 그러나 이것은 사실상 불가능하다. 그 이유는 바로 위에 적은대로 assetPrefix가 globally 적용되기 때문.

2-1번 방법: CSS 파일에 있는 모든 url('/images'를 '모두찾아바꾸기'를 이용해 하도코딩 형식으로 전부 url('https://cdn.example.co.kr/files/x2bee-fo-cdn/public/images로 바꾸는 방법이다. 이 방법은 동작은 하겠지만 퍼블리셔들이 코드를 추가할 때 불만이 쌓일 수도 있겠다.

2-2번 방법: 위 1번 방법이 동작하지 않은 이유는 Next.js에 내장된 자체 CSS loader때문이다. 이를 customizing해서 '.css'파일의 코드를 전혀 수정하지 일괄적으로 한 방에 prefix를 붙여주기 위해서는 아래 방법대로 하면 된다.

 

적용

postcss-url 설치.

pnpm add --save-dev postcss-url

postcss.config.js에 다음 코드를 추가

module.exports = {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
    'postcss-url': {
      url: ({ url }) => {
        if (process.env.APP_ENV === 'stage' && url.startsWith('/images/')) {
          return `https://cdn.example.co.kr/stg_files/x2bee-fo-cdn/public${url}`
        } else if (
          process.env.APP_ENV === 'production' &&
          url.startsWith('/images/')
        ) {
          return `https://cdn.example.co.kr/files/x2bee-fo-cdn/public${url}`
        }
        return url
      }
    }
  }
}

 

(물론 실제로 적용된 코드는 위에 url을 '.env'에 넣어서 더 refactoring을 하였으나 위 코드가 이해가 더 쉽게 때문에 풀어썼다.)

 

결론

너무 복잡하게 설명했지만, 위와 같이 해주면 결국 .css 파일의 경로 코드를 수정하지 않고

내가 원하는 url에 public 폴더의 이미지들을 바라보게 할 수 있다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유