서비스 계정으로 Google API에 액세스 하기 위해서 OAuth 2.0을 구현하여 액세스 토큰을 발급받아야 한다. 아래 링크인 독스에서도 나와있지만 코드를 직접 작성하는 것보다 라이브러리 사용을 추천한다.
내가 사용한 라이브러리는 apps-script-oauth2로 이슈 관리나 업데이트가 잘 되어 있고, 서비스 계정과 관련된 코드를 지원해서 선택했다. -> https://github.com/googleworkspace/apps-script-oauth2/blob/main/samples/GoogleServiceAccount.gs
1. OAuth 2.0 라이브러리 import
설명이 굉장히 자세하고 쉽게 되어있어서 금방 따라할 수 있다. (아래는 레포지토리 README에서 발췌)
아래와 같이 라이브러리에 OAuth2가 보이면 성공!
2. OAuth 2.0 코드
주의할 점 1
- 다른 점이 있다면 private_key 등의 경우 stack overflow 질문 글을 참고하여, apps script에서 환경변수를 설정했다.
- 아래와 같이 storeSecrets 함수를 만들어서 환경 변수 값들을 세팅한 다음, 함수는 지워도 된다.
- Apps Script의 설정 메뉴에 들어가서 직접 설정해줘도 된다. 어차피 위의 함수로 저장된 값들이 아래의 형태로 저장되기 때문이다.
주의해야 할 점은 private_key를 꺼낼 때 뒤에 replace 메서드를 사용해줘야 한다.
- private_key는 JSON 파일에서 \n(줄 바꿈 문자)가 포함된 채로 저장된다. (PEM 형식의 문자열)
- 이때, PEM 형식의 문자열에서 이스케이프된 줄 바꿈 문자를 실제 줄 바꿈 문자로 변환시켜주지 않으면 에러가 난다.
- 따라서 .replace(/\\n/g, '\n') 를 넣어주어 실제 줄 바꿈 문자로 바꿔준다.
- /: 정규 표현식 패턴의 시작
- \\: JavaScript에서 백슬래시는 이스케이프 문자이기 때문에, 실제로 백슬래시 문자를 찾고 싶을 때 두 번 사용
- n: n 문자 찾기
- /: 정규 표현식 패턴의 끝
- g: 문자열 내에서 패턴과 일치하는 모든 부분 찾기
주의할 점 2
getService_ 함수 뒤에 붙어있는 언더바는 지우면 안 된다. (컨벤션)
- 중요한 정보를 담고 있는 만큼 해당 함수가 외부에서 직접 호출되지 않아야 하기 때문이다.
코드
(1) client_email은 서비스 계정의 메일 / user_email은 권한을 위임받은 나의 이메일 값이다.
(2) setScope 부분은 내가 쓸 'directory.group' url을 적었다.
oauth.gs
/** (환경설정에 해당되는 부분입니다. getService_ 함수명 뒤에 있는 언더바_ 부분 절대 지우지 마세요!) */
function getService_() {
var USER_EMAIL = PropertiesService.getScriptProperties().getProperty('user_email');
var PRIVATE_KEY = PropertiesService.getScriptProperties().getProperty('private_key').replace(/\\n/g, '\n');
var CLIENT_EMAIL = PropertiesService.getScriptProperties().getProperty('client_email');
return OAuth2.createService('GoogleDrive:' + USER_EMAIL)
// Set the endpoint URL.
.setTokenUrl('https://oauth2.googleapis.com/token')
// Set the private key and issuer.
.setPrivateKey(PRIVATE_KEY)
.setIssuer(CLIENT_EMAIL)
// Set the name of the user to impersonate. This will only work for
// Google Apps for Work/EDU accounts whose admin has setup domain-wide
// delegation:
// https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
.setSubject(USER_EMAIL)
// Set the property store where authorized tokens should be persisted.
.setPropertyStore(PropertiesService.getScriptProperties())
// Set the scope. This must match one of the scopes configured during the
// setup of domain-wide delegation.
.setScope('https://www.googleapis.com/auth/admin.directory.group');
}
/** Reset the authorization state, so that it can be re-tested. */
function reset() {
getService_().reset();
}
이렇게 하고 실제 필요한 기능 구현을 위해 API 호출 함수를 작성하면 된다. 끝!
getMyGroup.gs 일부
function getMyGroup() {
var service = getService_();
if (service.hasAccess()) {
// 여기서 필요한 Google API를 호출하여 작업하면 된다.
var getOptions = {
muteHttpExceptions: true,
headers: { Authorization: 'Bearer ' + service.getAccessToken()} // 액세스 토큰 첨부!
};
var response = UrlFetchApp.fetch(getUrl, getOptions);
.
.
.
.
} else {
Logger.log(service.getLastError()); // 예외 처리 로직이 너무 떨어져 있다는 단점이 있는 구조
}
}
가독성을 생각하면 아래와 같은 구조가 더 깔끔한 듯하다. (Early exit pattern)
function getMyGroup() {
var service = getService_();
if (!service.hasAccess()) { // 예외 처리 초반에 하고 깔끔하게 마무리
Logger.log(service.getLastError());
return;
}
}
728x90
'📌 대외 활동 > 2310~ NGO 웹개발 유지보수 봉사' 카테고리의 다른 글
Apps Script로 엑셀 데이터와 Google Groups 자동화하기 (4) 최종 + 리팩토링 (0) | 2023.10.06 |
---|---|
Apps Script로 엑셀 데이터와 Google Groups 자동화하기 (4) 엑셀 -> 그룹스 동기화시키기 (0) | 2023.10.06 |
Apps Script로 엑셀 데이터와 Google Groups 자동화하기 (3) 액셀 시트로 데이터 가져오기 (1) | 2023.10.06 |
Apps Script로 엑셀 데이터와 Google Groups 자동화하기 (1) (0) | 2023.10.05 |