개요
살면서 한 번 쯤은 url을 보낸 경험이 있을 것 같다. 나에게 보내기든, 남에게 보내기든 카톡이나 슬랙 등에 url을 공유하면 미리보기가 뜬다.
이런 미리보기 데이터는 어떻게 출력되는 걸까? 그리고 이 데이터들을 어떻게 하면 가져다 쓸 수 있을까? 🤔
미리보기가 출력되는 방식을 관리하는 OG태그에 대해 알아보고, Jsoup 라이브러리를 이용해 데이터를 수집해보자.
OG (Open Graph) 프로토콜
대부분의 콘텐츠는 URL로 Facebook에 공유되므로, Facebook에 콘텐츠가 표시되는 방식을 관리하기 위해 오픈 그래프 태그로 웹사이트를 마크업하는 것이 중요합니다.
- Meta for Developers
Open Graph는 페이스북(메타)에서 개발한 메타데이터 프로토콜이다. 위 인용에 기재된 것처럼 콘텐츠가 표시되는 방식을 관리하여 웹 페이지 공유 방식을 개선하는 것이 Open Graph 개발의 목적이라고 볼 수 있다.
우리에겐 OG를 이용한 미리보기 방식이 익숙하지만, OG 개발 이전에는 크롤러가 경험을 바탕으로 공유된 콘텐츠의 제목, 설명, 썸네일을 추측하여 끌어와야 했다고 한다. 이 과정에서 원하는 데이터를 가져오지 못 할 수도 있고, 잘못된 데이터를 가져와 의도와 다르게 미리보기가 출력되는 이슈도 종종 있었다. 또한 콘텐츠마다 제목, 설명 등 정보를 나타내는 방식이 다르므로 크롤러를 개발하는 개발자도 고생을 할 수 밖에 없는 구조였다.
<meta property="og:url" content="http://www.nytimes.com/2015/02/19/arts/international/when-great-minds-dont-think-alike.html" />
<meta property="og:type" content="article" />
<meta property="og:title" content="When Great Minds Don’t Think Alike" />
<meta property="og:description" content="How much does culture influence creative thinking?" />
<meta property="og:image" content="http://static01.nyt.com/images/2015/02/19/arts/international/19iht-btnumbers19A/19iht-btnumbers19A-facebookJumbo-v2.jpg" />
따라서 위와 같이 OG를 이용, HTML 문서의 메타 정보를 통일하여 ( = 마크업) 콘텐츠의 미리보기 내용을 쉽고 간단하게 가져올 수 있게 되었다. 미리보기가 제대로 출력될 가능성이 높아져 사용자도 편하고, 크롤링 해 올 데이터가 명확해져 개발자도 편해진 훌륭한 기술이다 👍
OG의 메타 태그의 종류는 아래와 같다.
태그 | 설명 |
og:url | 페이지 표준 URL. 세션 변수, 사용자 매개변수, 카운터 등이 포함되지 않은 순수한 URL. |
og:title | 사이트 이름과 같은 콘텐츠의 제목. |
og:description | 콘텐츠에 대한 간략한 설명. 보통 2-4 문장으로 이루어지며, 본문의 일부를 보여주는 것이 일반적. |
og:image | 사용자가 콘텐츠를 공유할 때 표시되는 이미지. 보통 썸네일. |
fb:app_id | facebook 인사이트를 사용하기 위해 추가하는 ID. 트래픽 분석 결과를 확인할 때 사용된다. |
og:type | 콘텐츠의 미디어 유형. 기본값은 website이며, URL이 단일 개체이기에 type 값 또한 하나만 가질 수 있다. |
og:locale | 리소스의 지역 정보. 기본값은 en_US이며, 다른 언어 번역이 가능한 경우 og:locale:alternate 사용 가능. |
그럼 개발자 도구(F12 또는 마우스 우클릭 - 검사)를 이용해 직접 콘텐츠의 HTML에서 og 태그를 확인해보자.
위에서 확인한 OG 태그들이 마크업 된 모습을 확인할 수 있다. 그럼 이제 이 친구들을 내 DB 또는 서비스로 가져와보자!
Jsoup
jsoup은 실제 HTML로 작업하기 위한 Java 라이브러리입니다. HTML5 DOM 메서드와 CSS 셀렉터를 사용하여 URL을 가져오고 데이터를 추출 및 조작할 수 있는 매우 편리한 API를 제공합니다.
- Jsoup 공식 문서
즉, Jsoup은 HTML 문서를 파싱하고 조작하는 기능을 제공하는 자바 오픈 소스 라이브러리이다. 이러한 기능적 특성으로 보통은 웹 스크래핑 (크롤링)이나 데이터 추출에 많이 사용되는 편이다.
공식 문서에 따르면 좀 더 다양한 기능이 있는 듯 하지만, 본 포스트의 목적은 OG 태그 크롤링이니 생략하겠다. 만약 Jsoup의 구체적인 기능이 궁금하시다면 더보기를 참고하세요!
- URL, file, string으로부터 HTML을 스크랩하고 파싱한다.
- DOM traversal 또는 CSS selectors을 이용해 데이터를 찾고 추출한다.
- HTML elements, attributes, 그리고 텍스트를 조작한다.
- 사용자가 제출한 콘텐츠를 safelist에 따라 정리하여 XSS 공격을 방지한다.
- 동적으로 HTML을 생성하거나 템플릿에 데이터를 적용할 수 있다.
보통 크롤링은 파이썬의 셀레니움 등을 많이 사용하는 것으로 알고 있는데, 자바에도 비슷한 라이브러리가 있어 참 다행이다.
Jsoup으로 OG 태그 크롤링하기
그럼 이제 본격적으로 Spring Boot 위에서 OG 태그를 Jsoup 라이브러리를 이용해 크롤링해보자!
Java 17, Spring Boot 3, Gradle 8을 이용하였으나 딱히 버전을 타지는 않는 코드입니다.
1. build.gradle에 Jsoup 의존성 추가
build.gradle의 dependencies에 아래 의존성을 추가한다.
// jsoup
implementation 'org.jsoup:jsoup:1.16.1'
만약 maven을 사용한다면 아래와 같이 추가하면 된다.
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.16.1</version>
</dependency>
위 버전은 2023.06.14일 기준의 최신 버전이므로, 만약 다른 버전을 원한다면 여기를 참고하면 되겠다. mvn 기준, 제일 많이 쓰인 버전은 1.13.1 버전이다.
2. url을 이용, 원하는 게시글 크롤링
먼저 Jsoup의 사용 방법에 대해 알아보자. 아래는 공식 문서에서 제공하는 예제이다.
// "https://en.wikipedia.org/"에서 웹 페이지를 가져온다.
// 응답 받은 HTML 문서를 Document 객체로 파싱한다.
Document doc = Jsoup.connect("https://en.wikipedia.org/").get();
// 파싱한 HTML 문서의 제목을 출력한다.
log(doc.title());
// 가져온 HTML 문서에서 CSS selector "#mp-itn b a"에 해당하는 모든 요소를 선택한다.
Elements newsHeadlines = doc.select("#mp-itn b a");
for (Element headline : newsHeadlines) {
// 각각의 요소에 대해 아래 두 가지 값을 가져온다.
// attr("title") : 선택된 요소의 'title' 속성 값을 가져온다.
// absUrl("href") : 선택된 요소의 'href' 속성 값을 절대 URL로 변환한다.
log("%s\n\t%s", headline.attr("title"), headline.absUrl("href"));
}
쉽게 말해, url을 이용해 Document 객체를 만든 후, 해당 객체에서 원하는 값을 뽑아다 쓰면 된다. 우리가 원하는 건 og 태그이고, 해당 메타 태그가 어떻게 표현되는지 이미 위에서 살펴봤다. 이번엔 OG 태그를 끌어오는 코드를 직접 작성해보자.
try {
Document doc = Jsoup.connect(url).get();
String title = doc.select("meta[property=og:title]").attr("content");
String previewImageUrl = doc.select("meta[property=og:image]").attr("content");
log.info("제목 = {}", title);
log.info("썸네일 = {}", previewImageUrl);
} catch (IOException e) {
log.error(e.getMessage());
}
아까 확인했던 OG 태그 예시를 보자.
og:title의 예시를 보자. 해당 라인은 <meta> 태그로 이루어졌으며, 'data-rh', 'property', 'content' 속성을 갖는다. 여기서 Open Graph 프로토콜에서 사용되는 속성은 다음 두 가지 이다.
- property = "og:title" : OG 프로토콜에서 사용하는 태그를 나타낸다. title은 단어 그대로 제목.
- content = "코루틴.. (생략" : property 속성에 대응되는 값을 나타낸다.
String title = doc.select("meta[property=og:title]").attr("content");
따라서 위와 같이 작성하면, HTML 객체 (Document)에서 meta 태그의 property = og:title 속성에 대응하는 content 값을 가져온다 < 는 의미가 된다. 동일한 방식으로 description, image 등 원하는 미리보기 정보를 원하는 대로 가져다 쓰면 된다.
3. 결과물 확인
로그가 찍힌 것을 보니 값을 잘 가져오고 있다 😎. 만약 게시글에 요청 태그에 대한 값이 없다면 빈 스트링 ("")을 리턴한다.
마무리
오늘은 OG 프로토콜과 Jsoup 라이브러리에 대해 알아보았다. 확실히 OG 태그가 값을 가져오기 아주 쉬운 포맷이라 처음 Jsoup을 사용하는 것임에도 불구하고 빠르게 성공할 수 있었다!
이렇게 추출해낸 OG 태그 데이터는 사이드 프로젝트에서 잘 활용할 예정이다 😁 Jsoup도 다양한 방식으로 활용할 수 있게 연습해보자!
레퍼런스
- 웹 마스터용 공유 가이드 : https://developers.facebook.com/docs/sharing/webmasters
- Jsoup 공식 문서 : https://jsoup.org/
'Develop > Spring' 카테고리의 다른 글
[Spring Boot] Auto Increment PK Id를 노출하지 않으면서 API에 활용하는 방법 (4) | 2023.06.28 |
---|---|
[Spring Boot] 자바 스프링에서 처리율 제한 기능을 구현하는 4가지 방법 (2) | 2023.06.21 |
[Spring Boot] count를 구현하는 5가지 방법 (2) | 2023.05.24 |
[Spring Boot] ConstraintValidator를 이용해 나만의 validator annotation 만들기 (1) | 2023.05.15 |
[Spring Boot] 테스트 컨테이너로 테스트하기 (3) | 2023.04.17 |