@@ -27,6 +27,8 @@ interface AddWineModalProps {
2727 setShowRegisterModal : ( state : boolean ) => void ;
2828}
2929const AddWineModal = ( { showRegisterModal, setShowRegisterModal } : AddWineModalProps ) => {
30+ const ALLOWED_IMAGE_TYPES = [ 'image/png' , 'image/jpeg' , 'image/webp' ] ;
31+
3032 const [ category , setCategory ] = useState ( '' ) ;
3133 const fileInputRef = useRef < HTMLInputElement | null > ( null ) ;
3234 const [ previewImage , setPreviewImage ] = useState < string | null > ( null ) ;
@@ -38,6 +40,14 @@ const AddWineModal = ({ showRegisterModal, setShowRegisterModal }: AddWineModalP
3840 const handleImageChange = ( e : React . ChangeEvent < HTMLInputElement > ) => {
3941 const file = e . target . files ?. [ 0 ] ;
4042 if ( file ) {
43+ if ( ! ALLOWED_IMAGE_TYPES . includes ( file . type ) ) {
44+ setPreviewImage ( null ) ;
45+ setError ( 'wineImage' , {
46+ type : 'manual' ,
47+ message : '지원하지 않는 이미지 형식입니다. (png, jpg, webp)' ,
48+ } ) ;
49+ return ;
50+ }
4151 const renamedFile = renameFileIfNeeded ( file ) ; //이미지파일 이름 정규화
4252 const imageUrl = URL . createObjectURL ( renamedFile ) ;
4353 setPreviewImage ( imageUrl ) ;
@@ -52,6 +62,7 @@ const AddWineModal = ({ showRegisterModal, setShowRegisterModal }: AddWineModalP
5262 clearErrors,
5363 trigger,
5464 setValue,
65+ setError,
5566 reset,
5667 } = useForm < WineForm > ( {
5768 mode : 'onBlur' ,
@@ -97,11 +108,31 @@ const AddWineModal = ({ showRegisterModal, setShowRegisterModal }: AddWineModalP
97108 } ,
98109 } ) ;
99110 const onSubmit = async ( form : WineForm ) => {
100- let file = form . wineImage [ 0 ] ;
101- file = renameFileIfNeeded ( file ) ; //이미지파일 이름 정규화
111+ const file = form . wineImage ?. [ 0 ] ;
112+
113+ // 1. 이미지 없을 때 막기 (선택사항: 이미 react-hook-form required로 막고 있음)
114+ if ( ! file ) {
115+ setError ( 'wineImage' , {
116+ type : 'manual' ,
117+ message : '이미지를 업로드해 주세요.' ,
118+ } ) ;
119+ return ;
120+ }
121+
122+ // 2. 확장자 제한
123+ if ( ! ALLOWED_IMAGE_TYPES . includes ( file . type ) ) {
124+ setError ( 'wineImage' , {
125+ type : 'manual' ,
126+ message : '지원하지 않는 이미지 형식입니다. (png, jpg, webp)' ,
127+ } ) ;
128+ return ;
129+ }
130+
131+ // 3. 파일 정규화 및 제출
132+ const renamedFile = renameFileIfNeeded ( file ) ;
102133 postWineMutation . mutate ( {
103134 ...form ,
104- wineImage : [ file ] as unknown as FileList ,
135+ wineImage : [ renamedFile ] as unknown as FileList ,
105136 } ) ;
106137 } ;
107138 const categoryOptions = [
@@ -207,7 +238,7 @@ const AddWineModal = ({ showRegisterModal, setShowRegisterModal }: AddWineModalP
207238 } ) }
208239 id = 'wineImage'
209240 type = 'file'
210- accept = 'image/* '
241+ accept = '.png, .jpg, .jpeg, .webp '
211242 className = 'hidden'
212243 ref = { ( e ) => {
213244 register ( 'wineImage' ) . ref ( e ) ;
0 commit comments