Skip to content

next/image가 문제였다고요?

지난 6개월 동안 열심히 만든 welcome 서비스를 드디어 운영 환경에 정식으로 배포했어요. 그런데 배포 하고 하루 뒤 사용자 수가 예상보다 훨씬 빠르게 증가하면서, 서버에 부하가 걸리기 시작했죠. 처음엔 코드 최적화가 부족했거나 API에 병목이 생긴 줄 알았고 FE들이 해결 할 수 있는 방법이 있을까 멘탈이 흔들리던 차에 이미지 처리가 주요 원인이라는 걸 알아냈어요.

원인 분석 – Next.js의 이미지 최적화 기능

Next.js는 next/image 컴포넌트를 통해 이미지 관련 작업을 처리하는데요, 기본적으로 자동 이미지 최적화(Image Optimization) 기능이 작동해요. 사용자 입장에서는 UX가 정말 좋아지지만, 문제는 이 이미지 처리를 운영 서버에서 직접 수행한다는 거예요. 이미지 리사이징이나 포맷 변환 같은 작업이 모두 서버 리소스를 사용하니까, CPU 사용률이 급격히 올라갈 수밖에 없어요.

특히 저희 서비스는 다음과 같은 조건들이 맞물리면서 과부하가 발생했어요:

  • 이미지가 외부(origin) 도메인에서 로드됨
  • 이미지 최적화가 서버 사이드에서 수행됨
  • 트래픽 증가로 동시에 많은 이미지 요청이 발생함

이런 상황에서는 자연스럽게 서버에 무리가 갈 수밖에 없겠죠.

해결 – next.config.js에서 unoptimized: true 설정

해결 방법은 의외로 간단했어요. 바로 next.config.js 파일에서 아래처럼 설정을 추가한 거예요:

jsx
// next.config.js
module.exports = {
  images: {
    unoptimized: true,
  },
};

이 설정은 Next.js의 이미지 최적화 기능을 완전히 꺼버리는 거예요. 즉, 이제부터는 서버가 이미지를 리사이징하거나 변환하지 않고, 클라이언트가 원본 이미지를 그대로 받게 되는 거죠.

그 결과는 정말 극적이었어요. 서버는 더 이상 이미지 처리에 리소스를 쓰지 않게 되었고, CPU 사용률 10%이하로 유지되었어요. 실제로 와탭에서도 극적인 변화가 보였어요. 그리고 다행히 우려했던 것보다 로딩 처리가 느리지 않았답니다..

고려해야 할 점

물론 unoptimized: true 설정이 완전한 해결책은 아니에요. 이걸 적용하면 Next.js가 제공하는 이미지 최적화 이점(빠른 로딩 속도나 이미지 용량 절감) 들을 포기하는 셈이니까요.

그래서 함께 고려해볼 수 있는 방안들도 정리해봤어요:

  • Vercel을 사용 중이라면 자체 이미지 최적화 서비스를 활용하기
  • Cloudinary, imgix 같은 외부 이미지 CDN과 연동해서 처리
  • sharp, imagemin 같은 도구를 사용해서 빌드 시점에 미리 최적화 진행하기

결론적으로는, 서버에서 직접 처리하지 않도록 구성하면서도 최적화는 유지할 수 있는 방법들을 병행하는 게 좋을거같아요.

마무리하며

이번 경험을 통해 느낀 건, 아무리 좋은 프레임워크를 사용하더라도 운영 환경에서의 리소스 사용을 세밀하게 조정하는 게 정말 중요하다는 점이에요. 특히나 서비스가 성장하거나 트래픽이 빠르게 늘어나는 경우, 성능 병목을 빠르게 파악하고 대응하는 능력이 진짜 중요하다는 걸 다시 한 번 느꼈어요.