Explanation
구글 캘린더 API를 활용하여 구글 사용자 인증과 캘린더의 이벤트를 받아오고 캘린더를 추가 및 삭제하는 방법입니다. 내용을 구글 API 사이트의 'Quickstart'를 기반으로 하였습니다.
참고 : 구글 Quickstart (node.js)
1. 시작하기전에
node.js 와 npm이 설치 되어있다면
npm install googleapis --save
npm install google-auth-library --save
위와 같이 클라이언트 라이브러리를 설치합니다.
그리고 구글에 로그인한 후 https://console.developers.google.com/flows/enableapi?apiid=calendar로 이동하여 API 프로젝트를 생성하고 API키를 발급 받습니다.
2. 시작
프로젝트를 생성하여 API를 발급 받은 후 '사용자 인증 정보' 페이지의 'OAuth 2.0 클라이언트 ID' 가장 오른쪽에 있는 다운로드 아이콘을 클릭하여 'client_secret_xxxx.json' 다운로드 합니다. 그리고 파일 이름을 'client_secret.json'으로 변경하여 node의 디렉토리에 넣습니다. 그리고 아래와 같은 'quickstart.js' 파일을 만들어보겠습니다.
var fs = require('fs');
var readline = require('readline');
var google = require('googleapis');
var googleAuth = require('google-auth-library');
var SCOPES = [
'https://www.googleapis.com/auth/calendar.readonly', // 캘린더 정보의 읽기 권한? 입니다.
'https://www.googleapis.com/auth/calendar' // 캘린더 정보의 편집 권한? 입니다.
];
var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
process.env.USERPROFILE) + '/.credentials/';
// 토큰이 저장될 디렉토리
var TOKEN_PATH = TOKEN_DIR + 'calendar-nodejs-quickstart.json';
// 토큰 파일 명
fs.readFile('client_secret.json', function processClientSecrets(err, content) {
// 로컬의 client_secret.json 파일을 읽고 'authorize' 함수 실행
if (err) {
console.log('Error loading client secret file: ' + err);
return;
}
authorize(JSON.parse(content), listEvents);
});
function authorize(credentials, callback) {
var clientSecret = credentials.installed.client_secret;
var clientId = credentials.installed.client_id;
var redirectUrl = credentials.installed.redirect_uris[0];
// client_secret.json 파일에서 시크릿키, 클라이언트 아이디, 리다이렉트 URI를 받습니다.
// 웹 어플리케이션으로 만들었을 때에는 'installed' -> 'web' 으로 수정합니다.
// ex 'var clientSecret = credentials.web.client_secret;'
var auth = new googleAuth();
var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);
fs.readFile(TOKEN_PATH, function(err, token) {
// 앞서 지정한 디렉토리와 파일명으로 토큰 파일을 읽습니다.
if (err) {
getNewToken(oauth2Client, callback); // 토큰이 없다면 만듭니다.
} else {
oauth2Client.credentials = JSON.parse(token); // 토큰이 있다면 정보를 객체에 담습니다.
callback(oauth2Client);
}
});
}
function getNewToken(oauth2Client, callback) {
var authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
// 브라우저에 'authUrl'의 링크로 접근하여 데이터 접근에 동의한 후 리다이렉트 되는 URL의
// 'code=' 다음 부분을 복사합니다.
console.log('Authorize this app by visiting this url: ', authUrl);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
// 복사한 'code=' 다음 부분을 입력합니다.
// 로컬에서 테스트 할때에는 code= 다음 부분의 값이 URL 인코딩이 되어 있을 수 있으니
// URL 디코딩한 후에 입력합니다.
rl.question('Enter the code from that page here: ', function(code) {
rl.close();
oauth2Client.getToken(code, function(err, token) {
if (err) {
console.log('Error while trying to retrieve access token', err);
return;
}
oauth2Client.credentials = token;
storeToken(token);
callback(oauth2Client);
});
});
}
function storeToken(token) {
try {
fs.mkdirSync(TOKEN_DIR);
} catch (err) {
if (err.code != 'EEXIST') {
throw err;
}
}
fs.writeFile(TOKEN_PATH, JSON.stringify(token)); // 토큰을 만듭니다.
console.log('Token stored to ' + TOKEN_PATH);
}
function listEvents(auth) {
// 토큰 인증이 완료되면 최종적으로 실행되는 함수 입니다.
// 아래의 예제는 구글 캘린더에 등록된 이벤트 10개의 정보를 출력합니다.
var calendar = google.calendar('v3');
calendar.events.list({
auth: auth,
calendarId: 'primary', // 이곳에 이벤트를 가져올 캘린더 id를 입력해야 합니다.
timeMin: (new Date()).toISOString(),
maxResults: 10,
singleEvents: true,
orderBy: 'startTime'
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
var events = response.items;
if (events.length == 0) {
console.log('No upcoming events found.');
} else {
console.log('Upcoming 10 events:');
for (var i = 0; i < events.length; i++) {
var event = events[i];
var start = event.start.dateTime || event.start.date;
console.log('%s - %s', start, event.summary);
}
}
});
// 다음은 구글 캘린더에 'CHEOLGUSO' 라는 이름의 캘린더가 있는지 확인하여
// 없다면 만들고 있다면 삭제해보겠습니다.
calendar.calendarList.list({
auth : auth
}, function(err, calendarList){
if(err) console.log(err);
var deleteCalendarId; // 캘린더 삭제를 위한 아이디 변수
var isCGSCalendar = false; // 'CHEOLGUSO' 캘린더가 존재하는지 확인하기 위한 변수
// 'CHEOLGUSO' 캘린더가 있는지 확인
for(var i=0; i<calendarList.items.length; i++){
if(calendarList.items[i].summary === 'CHEOLGUSO'){
isCGSCalendar = true;
deleteCalendarId = calendarList.items[i].id;
}
}
if(isCGSCalendar){
// 'CHEOLGUSO' 캘린더가 있다면 캘린더를 지움
calendar.calendars.delete({
auth : auth,
calendarId : deleteCalendarId
}, function(err, calendars){
if(err) console.log(err);
});
}else{
// 'CHEOLGUSO' 캘린더가 없다면 캘린더를 만듬
calendar.calendars.insert({
auth : auth,
resource : {
summary : 'CHEOLGUSO'
}
}, function(err, calendars){
if(err) console.log(err);
});
}
});
}
실행은
node quickstart.js
3. 참고
구글 Quickstart (node.js)
https://github.com/google/google-api-nodejs-client/#authorizing-and-authenticating
https://github.com/wanasit/google-calendar




이전 댓글 4개
cheolguso
안녕하세요? 댓글 확인이 늦었네요. 파일이나 디렉토리를 찾을 수 없다는 것으로 보아, 예제에서 디렉토리 파일을 읽어오는 부분. ' var TOKEN_DIR= ' 토큰을 저장할 디렉토리를 선언하는 부분이나 ' client_secret.json ' 파일의 위치에서 문제가 생긴게 아닐까 싶습니다. 'client_secret.json' 파일을 올바른 디렉토리에 넣었는지, 또는 파일 디렉토리 경로를 수정하시거나 생성하신 서버의 환경에 맞게 토큰을 저장할 디렉토리('TOKEN_DIR')를 새로 지정하시면 되지 않을까 싶습니다.
잘봤습니다!!
글 정말 잘봤습니다 근데... 한대로 그대로 따라했는데 Error: ENOENT: no such file or directory, mkdir 이런오류가 계속 나네요.. 혹시 왜그런지 아세요 ?ㅠㅠ
FALSY LAB
안녕하세요, sofkaints님. 실제로 서비스에서 사용하시려면 몇가지 수정이 필요할 것 같습니다. sofkaints님이 말씀하신 것처럼 구글 사용자 인증을 위해서 (문서상 변수)'authUrl'로 클라이언트에서 새로 페이지를 띄우거나 리다이렉션 시켜서 사용자가 인증절차를 걸칠 수 있게 해야 합니다. 그리고 인증이 완료되면 구글 API 프로젝트에서 사용자 인증에서 '승인된 리디렉션 URI'부분에 등록된 URI로 리다이렉션이 되는데 이때 스트링 파라미터로 ?code=... 라는 값이 함께 옵니다. '승인된 리디렉션 URI'에 등록된 URI의 로직에서는 스트링 파라미터로 code가 있는지 확인하고, 있다면 code를 이용해서 'getToken' 하여 토큰을 만들어서 'storeToken' 토큰을 등록하고 다음 이벤트 로직을 실행하면 됩니다. 짧게 글로만 적으려니, 더 복잡하게 느껴지는거 같네요. 조금이나마 도움이 되었을지 모르겠습니다... 댓글 감사합니다 :)
sofkaints
웹앱에서 본인인증을해야 캘린더 정보를 볼수 있는데 퀵스타터는 실행하면 주는 url접속후 인증하고 뱉어내는 code를 입력해야 정보가 나옵니다. 다른 유저가 이 기능을 쓰려면 어떻게 해야하죠? url을 클라한테 보내줘서 인증하게 해야하나요? 간단히 말해 응용방법을 모르겠습니다 ㅠ