@@ -138,51 +138,59 @@ public ItemCreateResponse createItem(ItemCreateRequest request,Long userId) {
138138 private String extractOgImage (String url ) {
139139 if (url == null || url .isBlank ()) return null ;
140140
141- // 유튜브 전용 처리
141+ // 유튜브 처리
142142 if (url .contains ("youtube.com" ) || url .contains ("youtu.be" )) {
143143 String videoId = extractYoutubeVideoId (url );
144- if (videoId != null ) {
145- return "https://img.youtube.com/vi/" + videoId + "/mqdefault.jpg" ;
146- }
144+ if (videoId != null ) return "https://img.youtube.com/vi/" + videoId + "/mqdefault.jpg" ;
147145 }
148146
149- // 네이버 블로그 전용 처리
147+ // 네이버 블로그 모바일 주소 변환 (우회 및 데이터 접근용)
150148 if (url .contains ("blog.naver.com" ) && !url .contains ("m.blog.naver.com" )) {
151149 url = url .replace ("blog.naver.com" , "m.blog.naver.com" );
152150 }
153151
154- // 사이트 메타 태그 추출 시도 (Jsoup 활용)
155152 try {
156- // Jsoup 연결 설정 보강
157153 Document doc = Jsoup .connect (url )
158154 .userAgent ("Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1" )
159155 .referrer ("https://m.naver.com" )
160156 .timeout (10000 )
161157 .get ();
162158
163- // og:image 추출 시도
159+ // 블로그 작성자가 설정한 공식 썸네일(OG Tag) 우선 추출
164160 Element metaOgImage = doc .selectFirst ("meta[property=og:image]" );
165161 if (metaOgImage != null && !metaOgImage .attr ("content" ).isBlank ()) {
166- String ogImageUrl = metaOgImage .attr ("content" );
162+ String ogContent = metaOgImage .attr ("content" );
163+ // 네이버 기본 텍스트 썸네일(합성 이미지)이 아닐 때만 반환
164+ if (!ogContent .contains ("static.naver.net" )) {
165+ return ogContent ;
166+ }
167+ }
167168
168- // 네이버 블로그 이미지 주소가 상대 경로일 경우를 대비해 절대 경로로 변환
169- if (ogImageUrl .startsWith ("/" )) {
170- ogImageUrl = doc .baseUri () + ogImageUrl ;
169+ // 공식 썸네일이 없거나 기본 이미지일 경우, 본문의 첫 번째 실제 사진 탐색
170+ if (url .contains ("m.blog.naver.com" )) {
171+ Element firstRealImg = doc .selectFirst (".se-main-container img, .se-image-resource" );
172+ if (firstRealImg != null ) {
173+ String src = firstRealImg .hasAttr ("data-lazy-src" )
174+ ? firstRealImg .attr ("data-lazy-src" )
175+ : firstRealImg .attr ("src" );
176+
177+ if (src != null && !src .isBlank () && !src .contains ("static.naver.net" )) {
178+ return src ;
179+ }
171180 }
172- return ogImageUrl ;
173181 }
174182
175- // twitter:image 추출 시도
183+ // 트위터 카드 이미지 확인
176184 Element metaTwitterImage = doc .selectFirst ("meta[name=twitter:image]" );
177185 if (metaTwitterImage != null && !metaTwitterImage .attr ("content" ).isBlank ()) {
178186 return metaTwitterImage .attr ("content" );
179187 }
180188
181189 } catch (Exception e ) {
182- System .err .println ("Thumbnail extraction failed for: " + url + " | " + e .getMessage ());
190+ System .err .println ("Thumbnail extraction failed: " + e .getMessage ());
183191 }
184192
185- // 최종 실패 시 파비콘 반환
193+ // 모든 추출 실패 시 파비콘 반환
186194 return "https://www.google.com/s2/favicons?domain=" + url + "&sz=128" ;
187195 }
188196
0 commit comments