feat(member): 회원 썸네일 최소 해상도와 설정 보정 추가

아바타 업로드 시 최소 해상도 조건을 검증하고 리사이즈/품질 설정값을 안전 범위로 보정해 운영 설정 오입력에도 안정적으로 동작하도록 개선한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-11 17:27:47 +09:00
parent 65af30724c
commit ede272e7b1
8 changed files with 59 additions and 8 deletions

View File

@@ -25,6 +25,29 @@ const sanitizePathPart = (value) => value
.replace(/-+/g, '-')
.replace(/^-|-$/g, '')
/**
* 숫자 설정값을 최소/최대 범위로 보정한다.
* @param {number} value - 원본 값
* @param {number} minimum - 최소값
* @param {number} maximum - 최대값
* @returns {number} 보정된 값
*/
const clampNumber = (value, minimum, maximum) => {
if (!Number.isFinite(value)) {
return minimum
}
if (value < minimum) {
return minimum
}
if (value > maximum) {
return maximum
}
return Math.round(value)
}
/**
* 회원 썸네일 업로드 API
* @param {import('h3').H3Event} event - 요청 이벤트
@@ -42,9 +65,11 @@ export default defineEventHandler(async (event) => {
const config = useRuntimeConfig()
const maxFileSize = Number(config.maxFileSize || 10485760)
const avatarMaxWidth = Number(config.avatarMaxWidth || 512)
const avatarMaxHeight = Number(config.avatarMaxHeight || 512)
const avatarWebpQuality = Number(config.avatarWebpQuality || 82)
const avatarMinWidth = clampNumber(Number(config.avatarMinWidth || 96), 1, 4096)
const avatarMinHeight = clampNumber(Number(config.avatarMinHeight || 96), 1, 4096)
const avatarMaxWidth = clampNumber(Number(config.avatarMaxWidth || 512), avatarMinWidth, 4096)
const avatarMaxHeight = clampNumber(Number(config.avatarMaxHeight || 512), avatarMinHeight, 4096)
const avatarWebpQuality = clampNumber(Number(config.avatarWebpQuality || 82), 1, 100)
const formData = await readMultipartFormData(event)
const file = (formData || []).find((part) => part.name === 'file' && part.filename)
@@ -91,6 +116,13 @@ export default defineEventHandler(async (event) => {
})
}
if (metadata.width < avatarMinWidth || metadata.height < avatarMinHeight) {
throw createError({
statusCode: 400,
message: `최소 ${avatarMinWidth}x${avatarMinHeight} 이상 이미지만 업로드할 수 있습니다.`
})
}
const resizedBuffer = await sharp(file.data)
.rotate()
.resize({