저번엔 자바스크립트로 API연동을 해봤으니 이번엔 JAVA로 데이터 불러오는걸 해보자.
구글API에서 프로젝트 생성 및 OAuth설정이 끝났다는 가정하에 진행
나는 maven프로젝트라 API연동을 하려면 구글 API 라이브러리, oauth 인증을 위한 라이브러리, calendar 서비스를 위한 라이브러리를 pom.xml에 추가해준다.
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.22.0</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-jetty</artifactId>
<version>1.22.0</version>
</dependency>
<dependency>
<groupId>com.google.http-client</groupId>
<artifactId>google-http-client-jackson2</artifactId>
<version>1.41.0</version>
</dependency>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-calendar</artifactId>
<version>v3-rev235-1.22.0</version>
</dependency>
그 다음 구글 Oauth 인증을 통해 Calendar서비스를 생성하는 코드를 짜준다. 나는 GoogleCalendarService라는 파일 만든 후 작업진행.
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.List;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.calendar.Calendar;
import com.google.api.services.calendar.CalendarScopes;
import com.google.api.services.calendar.model.CalendarList;
import com.google.api.services.calendar.model.CalendarListEntry;
public class GoogleCalendarServiceImpl {
private static final String APPLICATION_NAME = "Google Calendar API Java Quickstart";
// 데이터 저장 경로 설정
private static final java.io.File DATA_STORE_DIR = new java.io.File(
System.getProperty("user.home"),
".credentials/calendar-java-quickstart");
// 데이터 저장소 팩토리
private static FileDataStoreFactory DATA_STORE_FACTORY;
// JSON 팩토리
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
// HTTP 통신을 위한 Transport
private static HttpTransport HTTP_TRANSPORT;
// 필요한 Google Calendar API 범위 설정
private static final List<String> SCOPES = Arrays.asList(CalendarScopes.CALENDAR);
static {
try {
// HTTP 전송을 위한 트러스트된 Transport 생성
HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
// 파일 저장소 팩토리 설정
DATA_STORE_FACTORY = new FileDataStoreFactory(DATA_STORE_DIR);
} catch (Throwable t) {
t.printStackTrace();
System.exit(1);
}
}
public static Credential authorize() throws IOException, GeneralSecurityException {
// client_secret.json 파일을 클래스 경로에서 읽기
try (InputStream in = GoogleCalendarService.class.getResourceAsStream("/client_secret.json")) {
if (in == null) {
throw new FileNotFoundException("Resource '/client_secret.json' not found. Ensure the file exists in the classpath.");
}
// GoogleClientSecrets 객체 생성
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// GoogleAuthorizationCodeFlow 객체 생성
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT,
JSON_FACTORY,
clientSecrets,
SCOPES
)
.setDataStoreFactory(DATA_STORE_FACTORY)
.setAccessType("offline")
.build();
// Credential 객체 생성
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
System.out.println("Credentials saved to " + DATA_STORE_DIR.getAbsolutePath());
return credential;
} catch (IOException e) {
// JSON 파일을 읽거나 GoogleClientSecrets 로드 중 문제가 발생했을 때 예외 처리
System.err.println("Error reading client_secret.json: " + e.getMessage());
throw e;
}
}
/**
* Google Calendar API 사용을 위한 Service 객체 생성
*/
public static Calendar getCalendarService() throws IOException, GeneralSecurityException {
Credential credential = authorize();
return new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
}
}
위 코드를 간단하게 설명하자면 Google Calendar API 인증 과정에 필요한 코드이며 client_secret.json
파일을 읽고 Credential 객체를 생성하는 역할을 한다. 여기서 중요한 부분은 자바로 구글 API연동을 하게되면 처음 실행 시 웹 페이지가 호출이 되며 승인하라는 안내창이 나오는데 한번 생성이 되면 다음 실행 시에는 바로 API데이터를 불러오는게 가능하다.
참고사진
그다음 실행 코드를 작성한다. 나같은 경우 해당 메뉴이동 시 호출하게끔 만들었다. main메서드 만들어서해도 상관은 없다.
// 캘린더 목록 출력
for (CalendarListEntry calendar : calendarList.getItems()) {
System.out.printf("ID: %s | Summary: %s\n", calendar.getId(), calendar.getSummary());
if(calendar.getSummary().equals("test") || calendar.getSummary().equals("연구소")) {
Events event2 = service.events().list(calendar.getId())
.setOrderBy("startTime") // 시작 시간 기준으로 정렬
.setSingleEvents(true) // 반복 이벤트를 개별적으로 표시
.execute();
for (Event event : event2.getItems()) {
System.out.printf("Event Title: %s\n", event.getSummary());
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
// 이벤트 생성 시간 (UTC -> KST)
DateTime createdTime = event.getCreated();
if (createdTime != null) {
Instant createdInstant = Instant.ofEpochMilli(createdTime.getValue());
ZonedDateTime createdZonedTime = ZonedDateTime.ofInstant(
createdInstant,
ZoneId.of("Asia/Seoul")
);
System.out.printf("Created At (KST): %s\n", createdZonedTime.format(formatter));
}
// 이벤트 수정 시간 (UTC -> KST)
DateTime updatedTime = event.getUpdated();
if (updatedTime != null) {
Instant updatedInstant = Instant.ofEpochMilli(updatedTime.getValue());
ZonedDateTime updatedZonedTime = ZonedDateTime.ofInstant(
updatedInstant,
ZoneId.of("Asia/Seoul")
);
System.out.printf("Last Updated At (KST): %s\n", updatedZonedTime.format(formatter));
}
// 이벤트 시작 시간 (start)
EventDateTime start = event.getStart();
if (start.getDateTime() != null) {
System.out.printf("Start: %s\n", start.getDateTime());
} else if (start.getDate() != null) {
System.out.printf("Start (All-day): %s\n", start.getDate());
}
// 이벤트 종료 시간 (end)
EventDateTime end = event.getEnd();
if (end.getDateTime() != null) {
System.out.printf("End: %s\n", end.getDateTime());
} else if (end.getDate() != null) {
System.out.printf("End (All-day): %s\n", end.getDate());
}
System.out.println("-------------------------");
}
}
}
} catch (IOException | GeneralSecurityException e) {
System.err.println("An error occurred: " + e.getMessage());
e.printStackTrace();
}
실행을 해보자.
첫 실행 시 이런 에러가 나올 것이다. 이건 따로 설정을 해주어야한다.
테스트 사용자를 넣어줘야 access_denied 에러가 안나올 것이다. 근데 이 에러가 아닌
redirect_uri_mismatch 에러가 나온다면 승인된 리디렉션 URI 설정을 해주어야한다.
나는 로컬에서 개발중이라 저렇게 넣어주었다. 저런 오류까지 잡아준 후 실행시켜보면
이렇게 데이터값을 받아올 수 있다. 이제 이 데이터로 DB에 넣어도 되고 다양하게 사용할 수 있다.
끝