[입 개발] Kotlin으로 Google Sheet 열어보기

Java/Kotlin 으로 Google Sheet 에 접속하는 예제는 사실 구글에 아주 잘 나와있다. https://developers.google.com/sheets/api/quickstart/java?hl=ko 를 보면 샘플이 있는데, 이걸 돌려보면 되는 사람도 있고 잘 되지 않는 경우도 있을 텐데… 그 이유에 대해서 살짝 적어볼려고 한다.

구글 인증 방식은 두 가지(OAuth 클라이언트ID, ServiceAccount)

위의 링크를 잘 읽어보면 인증 정보 만들기에서 OAuth 클라이언트 ID로 만들어진 경우이다. 그런데, python 등에서 사용하다보면 보통 ServiceAccount 를 이용하는 형태를 스게 되는데, 이 두가지가 서로 달라서 위의 샘플로 ServiceAccount 형태의 인증을 요청하면 InvalidArgumentException을 만나게 된다.

위의 링크에서 전자(OAuth 클라이언트ID)의 방식을 잘 설명하고 있으므로 여기서는 후자만 다룬다.

접속 방법

간단한 접속 코드는 다음과 같다. (GoogleCredential 이 그런데 deprecated 되는 건 함정)

import com.google.api.client.auth.oauth2.Credential
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.json.gson.GsonFactory
import com.google.api.services.sheets.v4.Sheets
import com.google.api.services.sheets.v4.SheetsScopes
import org.springframework.context.annotation.Configuration
import java.io.IOException
import java.security.GeneralSecurityException
import java.util.*

@Configuration
class GoogleAuthorizationConfig {
    private val applicationName: String = "test-api"

    private val credentialsFilePath: String = "/credentials.json"

    private val tokensDirectoryPath: String = "tokens"
    @Throws(IOException::class, GeneralSecurityException::class)
    private fun authorize(): Credential {
        val inputStream = GoogleAuthorizationConfig::class.java.getResourceAsStream(credentialsFilePath)
        val googleCredential = GoogleCredential.fromStream(inputStream)
            .createScoped(Collections.singleton(SheetsScopes.SPREADSHEETS_READONLY))
        return googleCredential
    }

    @get:Throws(IOException::class, GeneralSecurityException::class)
    val sheetsService: Sheets
        get() {
            val credential: Credential = authorize()
            return Sheets.Builder(
                GoogleNetHttpTransport.newTrustedTransport(),
                JSON_FACTORY, credential
            )
                .setApplicationName(applicationName)
                .build()
        }

    companion object {
        private val JSON_FACTORY: com.google.api.client.json.JsonFactory = GsonFactory.getDefaultInstance();
    }
}

그리고 이제 각 sheet 정보와 각각의 데이터를 가져오는 걸 알아보자.

    fun getSpreadSheets(page: String) {
        val sheetsService = googleAuthorizationConfig.sheetsService
        val sheets = sheetsService.spreadsheets().get(page).execute()

        sheets.sheets.map {
            println(it.properties.title)
            val sheet = sheetsService.spreadsheets().values().get(page, it.properties.title).execute()
            val values = sheet.getValues()

            values.map { //row 별로 가져오는 코드
                it.map { // 각 라인의 컬럼별로 가져오는 코드
                    print(it)
                    print(",")
                }
                println("-----")
            }
        }
    }