Files
jaejadle/nextjs/components/SignedImage.tsx
Mayne0213 f78454c2a1
Some checks failed
Build Docker Image / build-and-push (push) Has been cancelled
CI / lint-and-build (push) Has been cancelled
CHORE(merge): merge from develop
- Initial setup and all features from develop branch
- Includes: auth, deploy, docker, style fixes
- K3S deployment configuration
2026-01-06 17:29:16 +09:00

71 lines
1.6 KiB
TypeScript

"use client";
import React, { useState, useEffect } from 'react';
import Image from 'next/image';
import { getDownloadUrl } from '@/lib/services';
interface SignedImageProps {
fileKey: string;
alt: string;
className?: string;
fill?: boolean;
sizes?: string;
}
const SignedImage: React.FC<SignedImageProps> = ({
fileKey,
alt,
className = "",
fill = false,
sizes
}) => {
const [signedUrl, setSignedUrl] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const getSignedUrl = async () => {
try {
const downloadUrl = await getDownloadUrl(fileKey);
setSignedUrl(downloadUrl);
} catch (error) {
console.error('서명된 URL 생성 실패:', error);
setError('이미지를 불러올 수 없습니다.');
} finally {
setIsLoading(false);
}
};
getSignedUrl();
}, [fileKey]);
if (isLoading) {
return (
<div className={`flex items-center justify-center bg-gray-200 ${className}`}>
<div className="w-6 h-6 border-2 border-blue-600 border-t-transparent rounded-full animate-spin"></div>
</div>
);
}
if (error || !signedUrl) {
return (
<div className={`flex items-center justify-center bg-gray-200 ${className}`}>
<span className="text-gray-500 text-sm">{error || '이미지 없음'}</span>
</div>
);
}
return (
<Image
src={signedUrl}
alt={alt}
fill={fill}
sizes={sizes}
className={className}
/>
);
};
export default SignedImage;