이 글에서는 네이버에서 제공하는 검색(뉴스) API 를 활용하여 뉴스 데이터를 수집해보겠습니다. 해당 작업은 NAVER Developers 에서 제공하는 정보를 바탕으로 기능 구현이 되었습니다.
네이버 검색 결과의 목록을 조회하기 까지 약 10분의 시간밖에 소요되지 않으니 지금 바로 도전해보세요!
검색 API를 사용해 뉴스 검색을 실행하려면 먼저 네이버 개발자 센터에서 애플리케이션을 등록하고 클라이언트 아이디와 클라이언트 시크릿을 발급받아야 합니다.


오픈 API 이용 신청 버튼 클릭 > 로그인 > 이용 약관 동의 > 애플리케이션 등록 하는 과정을 순조롭게 진행합니다.

위와 같이 클라이언트 아이디와 클라이언트 시크릿이 발급된 것을 확인할 수 있습니다. API 요청에 필요한 필수 정보입니다.
여기까지 네이버 검색을 위한 사전 준비가 마무리 되었습니다!
네이버에서 제공하는 뉴스 검색 API 에 대한 모든 정보는 아래의 페이지에서 제공합니다.
https://developers.naver.com/docs/serviceapi/search/news/news.md#%EB%89%B4%EC%8A%A4
| 파라미터 | 타입 | 필수 여부 | 설명 |
|---|---|---|---|
| query | String | Y | 검색어. UTF-8로 인코딩되어야 합니다. |
| display | Integer | N | 한 번에 표시할 검색 결과 개수(기본값: 10, 최댓값: 100) |
| start | Integer | N | 검색 시작 위치(기본값: 1, 최댓값: 1000) |
| sort | String | N | 검색 결과 정렬 방법- sim: 정확도순으로 내림차순 정렬(기본값)- date: 날짜순으로 내림차순 정렬 |
| 요소 | 타입 | 설명 |
|---|---|---|
| rss | - | RSS 컨테이너. RSS 리더기를 사용해 검색 결과를 확인할 수 있습니다. |
| rss/channel | - | 검색 결과를 포함하는 컨테이너. channel 요소의 하위 요소인 title, link, description은 RSS에서 사용하는 정보이며, 검색 결과와는 상관이 없습니다. |
| rss/channel/lastBuildDate | dateTime | 검색 결과를 생성한 시간 |
| rss/channel/total | Integer | 총 검색 결과 개수 |
| rss/channel/start | Integer | 검색 시작 위치 |
| rss/channel/display | Integer | 한 번에 표시할 검색 결과 개수 |
| rss/channel/item | - | 개별 검색 결과. JSON 형식의 결괏값에서는 items 속성의 JSON 배열로 개별 검색 결과를 반환합니다. |
| rss/channel/item/title | String | 뉴스 기사의 제목. 제목에서 검색어와 일치하는 부분은 <b> 태그로 감싸져 있습니다. |
| rss/channel/item/originallink | String | 뉴스 기사 원문의 URL |
| rss/channel/item/link | String | 뉴스 기사의 네이버 뉴스 URL. 네이버에 제공되지 않은 기사라면 기사 원문의 URL을 반환합니다. |
| rss/channel/item/description | String | 뉴스 기사의 내용을 요약한 패시지 정보. 패시지 정보에서 검색어와 일치하는 부분은 <b> 태그로 감싸져 있습니다. |
| rss/channel/item/pubDate | dateTime | 뉴스 기사가 네이버에 제공된 시간. 네이버에 제공되지 않은 기사라면 기사 원문이 제공된 시간을 반환합니다. |
| 오류 코드 | HTTP 상태 코드 | 오류 메시지 | 설명 |
|---|---|---|---|
| SE01 | 400 | Incorrect query request (잘못된 쿼리요청입니다.) | API 요청 URL의 프로토콜, 파라미터 등에 오류가 있는지 확인합니다. |
| SE02 | 400 | Invalid display value (부적절한 display 값입니다.) | display 파라미터의 값이 허용 범위의 값(1~100)인지 확인합니다. |
| SE03 | 400 | Invalid start value (부적절한 start 값입니다.) | start 파라미터의 값이 허용 범위의 값(1~1000)인지 확인합니다. |
| SE04 | 400 | Invalid sort value (부적절한 sort 값입니다.) | sort 파라미터의 값에 오타가 있는지 확인합니다. |
| SE06 | 400 | Malformed encoding (잘못된 형식의 인코딩입니다.) | 검색어를 UTF-8로 인코딩합니다. |
| SE05 | 404 | Invalid search api (존재하지 않는 검색 api 입니다.) | API 요청 URL에 오타가 있는지 확인합니다. |
| SE99 | 500 | System Error (시스템 에러) | 서버 내부에 오류가 발생했습니다. "개발자 포럼"에 오류를 신고해 주십시오. |
https://developers.naver.com/docs/serviceapi/search/blog/blog.md#java
네이버 디벨로퍼스에서는 친절하게 다양한 프로그래밍 언어로 구현 예제를 제공합니다. 해당 내용만 보고도 기능을 구현할 수 있을 정도로 정확한 정보를 제공합니다.
API 래퍼런스를 참고하여 네이버 뉴스를 검색한 결과를 수집하는 기능을 구현해보도록 하겠습니다.
package com.ccp.simple.controller;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class NewsApiController {
@GetMapping("/news")
public String collectNews() {
String clientId = ""; //애플리케이션 클라이언트 아이디
String clientSecret = ""; //애플리케이션 클라이언트 시크릿
String searchKeyword = "네이버"; // 검색어
if (searchKeyword == null || searchKeyword.isEmpty()) {
throw new RuntimeException("검색어가 비어 있습니다.");
}
String encodeQuery;
try {
encodeQuery = URLEncoder.encode(searchKeyword, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("검색어 인코딩 실패",e);
}
String apiURL = "https://openapi.naver.com/v1/search/news?query=" + encodeQuery;
Map <String, String> requestHeaders = new HashMap<>();
requestHeaders.put("X-Naver-Client-Id", clientId);
requestHeaders.put("X-Naver-Client-Secret", clientSecret);
String responseBody = get(apiURL,requestHeaders);
//responseBody 의 내용을 db에 insert 하기
return "";
}
private static String get(String apiUrl, Map<String, String> requestHeaders){
HttpURLConnection con = connect(apiUrl);
try {
con.setRequestMethod("GET");
for(Map.Entry<String, String> header :requestHeaders.entrySet()) {
con.setRequestProperty(header.getKey(), header.getValue());
}
int responseCode = con.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
return readBody(con.getInputStream());
} else { // 오류 발생
return readBody(con.getErrorStream());
}
} catch (IOException e) {
throw new RuntimeException("API 요청과 응답 실패", e);
} finally {
con.disconnect();
}
}
private static HttpURLConnection connect(String apiUrl){
try {
URL url = new URL(apiUrl);
return (HttpURLConnection)url.openConnection();
} catch (MalformedURLException e) {
throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
} catch (IOException e) {
throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
}
}
private static String readBody(InputStream body){
InputStreamReader streamReader = new InputStreamReader(body);
try (BufferedReader lineReader = new BufferedReader(streamReader)) {
StringBuilder responseBody = new StringBuilder();
String line;
while ((line = lineReader.readLine()) != null) {
responseBody.append(line);
}
return responseBody.toString();
} catch (IOException e) {
throw new RuntimeException("API 응답을 읽는 데 실패했습니다.", e);
}
}
}
코드에서 변경한 내용은 고작 검색 키워드의 변수 정도입니다. 클라이언트 아이디와 시크릿키의 값만 잘 넣으면 성공적으로 결과를 조회할 수 있습니다.

이와 같이 단 10분만에 네이버에서 뉴스를 검색한 결과를 조회하는 기능을 구현할 수 있었습니다.
네이버 덕분에 쉽고 빠르게 고품질의 데이터를 제공받을 수 있어 기쁩니다.