메인 콘텐츠로 건너뛰기

옵션 레퍼런스

useDropup 훅의 모든 설정 옵션입니다.

유효성 검사 옵션

accept

허용할 파일 유형입니다.

// 단일 MIME 타입
useDropup({ accept: 'image/png' });

// 여러 MIME 타입
useDropup({ accept: 'image/png, image/jpeg, image/gif' });

// 와일드카드
useDropup({ accept: 'image/*' });

// 확장자로
useDropup({ accept: '.pdf, .doc, .docx' });

// 배열 형식
useDropup({ accept: ['image/*', 'application/pdf', '.txt'] });
타입기본값
string | string[]undefined (모든 파일)

maxSize

최대 파일 크기 (바이트).

useDropup({ maxSize: 10 * 1024 * 1024 }); // 10MB
타입기본값
numberundefined (제한 없음)

minSize

최소 파일 크기 (바이트).

useDropup({ minSize: 1024 }); // 최소 1KB
타입기본값
numberundefined (제한 없음)

maxFiles

허용되는 최대 파일 수.

useDropup({ maxFiles: 5 });
타입기본값
numberundefined (제한 없음)

maxWidth / maxHeight

최대 이미지 크기 (픽셀).

useDropup({
accept: 'image/*',
maxWidth: 4096,
maxHeight: 4096,
});
타입기본값
numberundefined (제한 없음)

minWidth / minHeight

최소 이미지 크기 (픽셀).

useDropup({
accept: 'image/*',
minWidth: 100,
minHeight: 100,
});
타입기본값
numberundefined (제한 없음)

customRules

커스텀 유효성 검사 함수.

useDropup({
customRules: [
// 동기 유효성 검사
(file) => {
if (file.name.includes('draft')) {
return '초안 파일은 허용되지 않습니다';
}
return true;
},
// 비동기 유효성 검사
async (file) => {
const exists = await checkServerDuplicate(file);
return exists ? '파일이 이미 존재합니다' : true;
},
],
});
타입기본값
ValidationRule[][]

ValidationRule 타입:

type ValidationRule = (file: File) => boolean | string | Promise<boolean | string>;

동작 옵션

multiple

여러 파일 선택 허용.

useDropup({ multiple: true });  // 여러 파일
useDropup({ multiple: false }); // 단일 파일만
타입기본값
booleantrue

disabled

드롭 영역 비활성화.

useDropup({ disabled: true });
타입기본값
booleanfalse

autoUpload

파일이 추가되면 자동으로 업로드 시작.

useDropup({
upload: { url: '/api/upload' },
autoUpload: true,
});
타입기본값
booleanfalse

generatePreviews

이미지 파일의 미리보기 URL 생성.

useDropup({ generatePreviews: true });

// 미리보기 접근
files[0].preview // "blob:http://..."
타입기본값
booleantrue

업로드 설정

upload

업로드 대상 및 동작 구성.

URL 기반 설정

useDropup({
upload: {
url: '/api/upload',
method: 'POST',
headers: {
'Authorization': 'Bearer token',
},
fieldName: 'file',
withCredentials: true,
timeout: 30000,
},
});

UploadConfig 속성:

속성타입기본값설명
urlstring필수업로드 엔드포인트 URL
methodstring'POST'HTTP 메서드
headersRecord<string, string>{}요청 헤더
fieldNamestring'file'파일의 폼 필드 이름
withCredentialsbooleanfalse쿠키 포함
timeoutnumber0요청 타임아웃 (ms)
dataRecord<string, unknown>{}추가 폼 데이터

커스텀 업로더

useDropup({
upload: async (file, options) => {
const formData = new FormData();
formData.append('file', file.file);

const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
signal: options.signal,
});

const data = await response.json();
return { url: data.url };
},
});

CustomUploader 타입:

type CustomUploader = (
file: DropupFile,
options: UploadOptions
) => Promise<UploadResult>;

interface UploadOptions {
signal: AbortSignal;
onProgress: (progress: number) => void;
}

interface UploadResult {
url?: string;
response?: unknown;
}

클라우드 업로더

import { createS3Uploader } from '@samithahansaka/dropup/cloud/s3';

useDropup({
upload: createS3Uploader({
getPresignedUrl: async (file) => {
const res = await fetch('/api/s3-presign', {
method: 'POST',
body: JSON.stringify({ filename: file.name, type: file.type }),
});
return res.json();
},
}),
});

콜백 옵션

onFilesAdded

파일이 추가될 때 호출됩니다 (유효성 검사 후).

useDropup({
onFilesAdded: (files) => {
console.log('추가됨:', files.map(f => f.name));
},
});
타입
(files: DropupFile[]) => void

onFileRemoved

파일이 제거될 때 호출됩니다.

useDropup({
onFileRemoved: (file) => {
console.log('제거됨:', file.name);
},
});
타입
(file: DropupFile) => void

onValidationError

파일이 유효성 검사에 실패할 때 호출됩니다.

useDropup({
accept: 'image/*',
onValidationError: (errors) => {
errors.forEach(({ file, errors }) => {
console.log(`${file.name}: ${errors.join(', ')}`);
});
},
});
타입
(errors: ValidationError[]) => void

onUploadStart

파일 업로드가 시작될 때 호출됩니다.

useDropup({
onUploadStart: (file) => {
console.log('업로드 시작:', file.name);
},
});
타입
(file: DropupFile) => void

onUploadProgress

업로드 진행 중에 호출됩니다.

useDropup({
onUploadProgress: (file, progress) => {
console.log(`${file.name}: ${progress}%`);
},
});
타입
(file: DropupFile, progress: number) => void

onUploadComplete

파일 업로드가 완료될 때 호출됩니다.

useDropup({
onUploadComplete: (file, response) => {
console.log('업로드됨:', file.uploadedUrl);
console.log('서버 응답:', response);
},
});
타입
(file: DropupFile, response: unknown) => void

onUploadError

파일 업로드가 실패할 때 호출됩니다.

useDropup({
onUploadError: (file, error) => {
console.error(`실패: ${file.name}`, error.message);
},
});
타입
(file: DropupFile, error: DropupError) => void

onAllComplete

모든 파일 업로드가 완료될 때 호출됩니다.

useDropup({
onAllComplete: (files) => {
const successful = files.filter(f => f.status === 'complete');
console.log(`${successful.length}/${files.length} 성공적으로 업로드됨`);
},
});
타입
(files: DropupFile[]) => void

전체 예제

const { files, actions, state, getDropProps, getInputProps } = useDropup({
// 유효성 검사
accept: ['image/*', 'application/pdf'],
maxSize: 10 * 1024 * 1024,
maxFiles: 5,

// 동작
multiple: true,
autoUpload: false,
generatePreviews: true,

// 업로드
upload: {
url: '/api/upload',
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
},
},

// 콜백
onFilesAdded: (files) => {
toast.info(`${files.length}개 파일 추가됨`);
},
onValidationError: (errors) => {
toast.error(`${errors.length}개 파일 거부됨`);
},
onUploadProgress: (file, progress) => {
console.log(`${file.name}: ${progress}%`);
},
onUploadComplete: (file) => {
toast.success(`${file.name} 업로드됨!`);
},
onUploadError: (file, error) => {
toast.error(`${file.name} 실패: ${error.message}`);
},
onAllComplete: (files) => {
const count = files.filter(f => f.status === 'complete').length;
toast.success(`모두 완료! ${count}개 파일 업로드됨.`);
},
});