Sharp를 이용해 이미지 Jpeg to WebP 변환 후 S3에 업로드하기
KUKJIN LEE • 6일 전 작성
이미지 용량을 줄이면 페이지 로딩 속도가 개선되고, 사용자 경험도 좋아집니다. Sharp 라이브러리를 사용하면 JPEG, PNG 등 다양한 포맷의 이미지를 WebP로 간단하게 변환하고, 변환된 이미지를 AWS S3에 업로드 할 수 있습니다.
필요
-
@aws-sdk/client-s3
-
AWS SDK v3 버전으로,
S3Client
,PutObjectCommand
등을 사용해 S3에 파일을 업로드합니다.
-
-
sharp
-
Node.js에서 인기 있는 이미지 처리 라이브러리로, 다양한 포맷 변환, 리사이징, 압축 등을 손쉽게 지원합니다.
-
-
환경 변수(AWS_REGION, AWS_ACCESS_KEY_ID 등)
-
S3 업로드를 위해 필요한 AWS 인증 정보(Region, Access Key, Secret Key), 그리고 업로드할 버킷 이름을 설정합니다.
-
코드분석
uploadImageToS3
라는 함수를 만들어 파일 버퍼(Buffer)와 파일 이름, 콘텐츠 타입을 처리한 후, 업로드 하는 구조입니다.
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3'
import sharp from 'sharp'
const region = process.env.AWS_REGION
const accessKeyId = process.env.AWS_ACCESS_KEY_ID
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY
const bucketName = process.env.S3_BUCKET_NAME
let s3: S3Client | null = null
if (region && accessKeyId && secretAccessKey && bucketName) {
s3 = new S3Client({
region,
credentials: {
accessKeyId,
secretAccessKey,
},
})
} else {
console.error('S3 기본 설정에 관한 오류')
}
export async function uploadImageToS3(
fileBuffer: Buffer,
fileName: string,
contentType: string,
): Promise<string> {
if (!s3 || !bucketName) {
throw new Error('파일을 업로드 할 수 없습니다.')
}
try {
let optimizedBuffer: Buffer
if (contentType.startsWith('image/')) {
optimizedBuffer = await sharp(fileBuffer)
.resize(1920, 1080, {
fit: 'inside',
withoutEnlargement: true
})
.webp({ quality: 80 })
.toBuffer()
// 업로드될 파일 이름을 .webp로 교체
fileName = fileName.replace(/\.[^/.]+$/, '.webp')
} else {
// 이미지가 아닌 경우 그대로 업로드(이 부분에선 webp 변환 X)
optimizedBuffer = fileBuffer
}
// S3에 업로드
const command = new PutObjectCommand({
Bucket: bucketName,
Key: `test/${fileName}`,
Body: optimizedBuffer,
ContentType: 'image/webp', // 변환된 이미지의 타입
})
await s3.send(command)
return `test/${fileName}`
} catch (error) {
console.error('에러:', error)
throw new Error('업로드 실패')
}
}
이미지 변환(Sharp)
-
.resize(1920, 1080, { fit: 'inside', withoutEnlargement: true })
-
이미지가 원본보다 클 경우 최대 1920×1080 범위 안으로만 리사이징
-
원본이 이미 작다면 확대하지 않음
-
-
.webp({ quality: 80 })
-
WebP 포맷으로 변환, 품질(quality)을 80으로 지정 → 원본 대비 용량이 상당히 줄면서도 시각적 품질은 크게 떨어지지 않음
-
-
.toBuffer()
-
최종 변환된 이미지를 버퍼 형태로 반환
-
파일 이름 및 S3 업로드
-
기존 파일 이름 확장자를
.webp
로 교체해 업로드 -
ContentType
역시"image/webp"
로 지정해줌 -
Key: 'test/${fileName}'
경로로 S3에 저장 →test/
폴더 하위에 웹 이미지가 생성됨
-
환경 변수 설정
-
AWS_REGION
,AWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
,S3_BUCKET_NAME
가 제대로 설정되어야 정상 작동 -
코드 내에서
region && accessKeyId && secretAccessKey && bucketName
체크 후 S3를 초기화하지 못하면 에러 메시지 출력
-
-
Sharp 설치 버전 확인
-
Node.js 환경에서 Sharp를 설치할 때, OS 및 Node 버전에 따라 바이너리 문제가 날 수 있음(특히 알파인 리눅스에서).
-
로컬에서
sharp
이 정상적으로 동작하는지 확인 필요
-
-
이미지 MIME 타입 처리
-
contentType.startsWith('image/')
로 분기 → 이미지 외에는 변환하지 않고 그대로 업로드 -
이미지가 아닌데 ContentType이
image/
로 넘어올 경우, 의도치 않게 WebP 변환 시도가 일어날 수 있으니 주의
-
-
S3 권한(Policy) 확인
-
S3에 PutObject 권한이 있는지, 버킷이 존재하는지 확인
-
잘못된 IAM Role 또는 권한 정책이면 업로드가 실패할 수 있음
-
전형적인 이미지 최적화 예시로, 웹 서비스에서 이미지 로딩 속도를 높이고, 트래픽 비용을 절감하는 데 도움이 됩니다.