@@ -5,7 +5,7 @@ import { useRouter } from "next-nprogress-bar"
55import dayjs from "dayjs"
66import Image from "next/image"
77import Link from "next/link"
8- import { usePathname } from "next/navigation"
8+ import { useSearchParams } from "next/navigation"
99import classNames from "classnames"
1010import ButtonBasic from "@components/atom/ButtonBasic"
1111import LineBasic from "@components/atom/LineBasic"
@@ -25,11 +25,12 @@ const PostList = (): ReactElement => {
2525 const { loginUser, loginState } = useLoginStore ( )
2626
2727 const router = useRouter ( )
28- const pathname = usePathname ( )
29- const page = pathname . split ( "/" ) [ 2 ] || 1
28+ const searchParams = useSearchParams ( )
29+ const page = searchParams . get ( "page" ) || 1
3030
3131 const [ postList , setPostList ] = useState < IPost [ ] > ( [ ] )
3232 const [ pagination , setPagination ] = useState < IPagination < IPost > > ( { } as IPagination < IPost > )
33+ const [ failedImages , setFailedImages ] = useState < Record < string , boolean > > ( { } )
3334
3435 const getPosts = ( page = 1 ) : void => {
3536 if ( page < 1 ) {
@@ -75,9 +76,18 @@ const PostList = (): ReactElement => {
7576 }
7677 }
7778
79+ const handleImageError = ( postId : number ) : void => {
80+ setFailedImages ( ( prev ) => ( {
81+ ...prev ,
82+ [ postId ] : true ,
83+ } ) )
84+
85+ console . error ( "썸네일 로드 실패:" , postId )
86+ }
87+
7888 useEffect ( ( ) => {
7989 getPosts ( Number ( page ) )
80- } , [ pathname ] )
90+ } , [ page ] )
8191
8292 return (
8393 < Wrapper >
@@ -105,6 +115,7 @@ const PostList = (): ReactElement => {
105115 { postList . length > 0 ? (
106116 postList . map ( ( post , index ) => {
107117 const diff = dayjs ( ) . diff ( dayjs ( post . createdAt ) , "hour" )
118+ const imageLoadFailed = failedImages [ post . id ]
108119
109120 return (
110121 < Link
@@ -123,36 +134,38 @@ const PostList = (): ReactElement => {
123134 ) }
124135 >
125136 < div className = { styles . thumbnailWrapper } >
126- < Image
127- className = { styles . thumbnail }
128- src = { handlePostThumbnail ( post . thumbnail ) }
129- alt = { "thumbnail" }
130- fill
131- sizes = "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
132- style = { { objectFit : "cover" } }
133- loading = "eager"
134- placeholder = "blur"
135- blurDataURL = {
136- darkMode ? "/loading-placeholder-dark.svg" : "/loading-placeholder.svg"
137- }
138- onError = { ( e ) => {
139- const target = e . target as HTMLImageElement
140- target . style . display = "none"
141- console . error ( "썸네일 로드 실패:" , target . src )
142- if ( target . src . includes ( "/proxy/" ) ) {
143- console . log (
144- "프록시 URL 로드 실패, 환경 변수 확인 필요:" ,
145- target . src ,
146- )
147- console . log ( "환경 변수:" , {
148- NEXT_PUBLIC_IP : process . env . NEXT_PUBLIC_IP ,
149- } )
137+ { ! imageLoadFailed ? (
138+ < Image
139+ className = { styles . thumbnail }
140+ src = { handlePostThumbnail ( post . thumbnail ) }
141+ alt = { "thumbnail" }
142+ fill
143+ sizes = "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
144+ style = { { objectFit : "cover" } }
145+ loading = "eager"
146+ placeholder = "blur"
147+ blurDataURL = {
148+ darkMode
149+ ? "/loading-placeholder-dark.svg"
150+ : "/loading-placeholder.svg"
150151 }
151- target . parentElement ! . innerHTML = `<div style="display:flex;align-items:center;justify-content:center;width:100%;height:100%;background-color:${
152- darkMode ? "#333" : "#f5f5f5"
153- } ;color:${ darkMode ? "#ccc" : "#666" } ;">이미지 없음</div>`
154- } }
155- />
152+ onError = { ( ) => handleImageError ( post . id ) }
153+ />
154+ ) : (
155+ < div
156+ style = { {
157+ display : "flex" ,
158+ alignItems : "center" ,
159+ justifyContent : "center" ,
160+ width : "100%" ,
161+ height : "100%" ,
162+ backgroundColor : darkMode ? "#333" : "#f5f5f5" ,
163+ color : darkMode ? "#ccc" : "#666" ,
164+ } }
165+ >
166+ 이미지 없음
167+ </ div >
168+ ) }
156169 </ div >
157170 < div className = { styles . itemLeft } >
158171 < div className = { styles . itemTitle } >
0 commit comments