https://developers.google.com/sheets/api 를 사용하여 비공개(private) Google Sheet 에 접근해야할 때, 인증부분에서 겪은 삽질을 공유한다.
먼저 알아야 할 것은 API KEY로 접근하는 것은 공개(public) sheet 만 read-only 권한으로 가능하다. 그 이외의 접근에는 API KEY를 사용할 수 없다.
비공개 sheet에 접근할 때는 Google Cloud Platform 에서 발급할 수 있는 서비스 계정(Service Account)이 필요하다.
Google Sheet를 접근하고자 하는 프로젝트로 이동하여 API 및 서비스 > 라이브러리 메뉴를 선택한다.

Google Sheet API를 검색한 후 사용설정을 한다. 그 후 관리 버튼을 눌러 서비스 계정을 생성한다.

사용자 인증 정보 를 선택한다.

그 후 + 사용자 인증 정보 만들기 를 선택하고 서비스 계정을 선택한다.

서비스 계정 이름과 서비스 계정 ID를 입력하고 완료 버튼을 누른다. 서비스 계정 ID가 중요하다. 나중에 문서 공유를 설정할 때, 여기에서 생성한 이메일이 필요하기 때문이다.

서비스 계정 생성이 완료되면 해당 서비스 계정을 선택하여 상세 화면으로 진입한다. 그리고 키 메뉴를 선택하고 키 추가 > 새 키 만들기 를 선택한다.

이어 나오는 모달 화면에서 JSON 을 선택하면 서비스 계정 키가 JSON 형식으로 생성되고 로컬 컴퓨터로 다운로드 된다.

해당 파일에는 아래와 같은 정보가 포함되어 있다.
{
"type": "service_account",
"project_id": "...",
"private_key_id": "...",
"private_key": "...",
"client_email": "my-google-sheet-bot@youtext-dashboard.iam.gserviceaccount.com",
"client_id": "...",
"auth_uri": "...",
"token_uri": "...",
"auth_provider_x509_cert_url": "...",
"client_x509_cert_url": "..."
}위 정보를 바탕으로 google-spreadsheet 라이브러를 사용하여 문서에 접근해 보자.
const creds = require('./my-project-service-account-key.json');
const { GoogleSpreadsheet } = require('google-spreadsheet');
(async () => {
try {
// Initialize the sheet - doc ID is the long id in the sheets URL
const doc = new GoogleSpreadsheet('Google Sheet ID');
await doc.useServiceAccountAuth(creds);
await doc.loadInfo();
console.log(doc.title);
} catch (error) {
console.log(error.message);
}
})();
실행해 보면 Google API error - [403] The caller does not have permission 오류가 발생한다.
그 이유는 Google Sheet 에 접근하기 위해서는 위 서비스 계정과 문서를 공유해야 하기 때문이다. API 접근하려는 Google Sheet로 이동한다.
문서에서 공유 버튼을 누른다.

사용자 및 그룹 추가 란에 서비스 계정의 이메일을 추가한다.

보내기 버튼을 눌러 공유를 완료한다.

사용자 및 그룹과 공유에 방금 추가한 서비스 계정이 추가되었음을 알 수 있다. 필요에 따라 공유 타입을 뷰어, 댓글 작성자, 편집자 중에 하나로 변경한다.

이제 다시 아래 코드를 실행해 보자.
const creds = require('./my-project-service-account-key.json');
const { GoogleSpreadsheet } = require('google-spreadsheet');
(async () => {
try {
// Initialize the sheet - doc ID is the long id in the sheets URL
const doc = new GoogleSpreadsheet('Google Sheet ID');
await doc.useServiceAccountAuth(creds);
await doc.loadInfo();
console.log(doc.title);
} catch (error) {
console.log(error.message);
}
})();
$ node index.js
테스트용문서의 제목이 출력됨을 확인할 수 있다.