구글시트 데이터 연동하기 (with.코틀린)

Sejong Park·2022년 2월 5일
1
post-thumbnail

진행중인 사이드 프로젝트에서 구글시트를 어드민으로 사용하고 있습니다.

어드민을 만드는게 사이드프로젝트보다 공수가 더 크기도 하고, 변경거리가 있을때마다 DB를 업데이트하는것은 편하진 않습니다. 매번 툴을 이용하여 변경이 필요하고, 기획이나 디자인의 룰을 가진사람들이 작업을 하기 쉽지 않았었습니다.

구글시트를 이용하여 프로젝트에 들어가는 동적 정보들을 빠르게 변경할 수 있도록 만들어 이를 해결해보는건 어떨까 싶어 적용해보았고, 사용성이 나쁘진 않아 이걸 정리해보고자 합니다.

구글시트 만들기

배너를 관리하는 요구사항이 있다고 합니다.
그래고 배너는 "일정기간"동안 노출되며 "이미지URL"과 "타이틀"을 가집니다.

우선 구글시트를 먼저 만들어봅시다.

이쁘진 않지만, 필요한 작업을 하는덴 충분합니다.

서비스 계정만들기 & 구글 시트 공유설정

애플리케이션은 데이터를 조회할 수 있어야 합니다. 다시말해 권한을 가진 API가 시트를 조회할 수 있어야 한다. 우선 서비스계정을 만들고 시트에 권한을 설정해봅시다.

우선 구글 개발자 콘솔에서 서비스계정을 만들어봅시다.
https://console.developers.google.com/iam-admin/serviceaccounts

계정을 만든이후 키탭으로 이동하여 키를 만든다음 다운로드받도록 합시다. 해당 키파일은 앞으로 API에서 인증시 사용하게 됩니다.

마지막으로 서비스계정이 구글시트에 접근이 가능하도록 공유설정을 해봅시다.

만들어놓은 시트에서 공유버튼을 누른다음에 우리가 만든 서비스계정을 추가합시다.

코드에서 시트 데이터 가져오기

구글에선 우리가 만든 구글시트에 접근할 수 있는 API를 제공합니다.

https://developers.google.com/sheets/api

이제 시트의 데이터를 가져올 수 있도록 코드를 작성해봅시다.
코드작성에 앞서서 구글클라이언트 라이브러리를 필요로 합니다. gradle에서 아래와 같이 의존관계를 추가해줍시다.

// ...

dependencies {
// ...
    implementation("com.google.api-client:google-api-client:1.30.4")
    implementation("com.google.apis:google-api-services-sheets:v4-rev581-1.25.0")
}

다음으로 구글시트로 인증하는 함수부터 만들어봅시다.

import com.google.api.client.auth.oauth2.Credential
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential


fun connectGoogleCredentials(): Credential {
    val inputStream = this::class.java.getResourceAsStream("/credentials.json")
    return GoogleCredential.fromStream(inputStream)
           .createScoped(listOf(SheetsScopes.SPREADSHEETS_READONLY))
}
  • 앞서서 다운받은 키파일을 바탕으로 인증을 진행합니다. resource 폴터 하위에 credentials.json 파일을 추가해줍시다.

다음으로 반환된 Credential을 바탕으로 구글시트에 접근하는 함수를 만들어봅시다.

import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport
import com.google.api.client.json.JsonFactory
import com.google.api.client.json.jackson2.JacksonFactory
import com.google.api.services.sheets.v4.Sheets
import com.google.api.services.sheets.v4.SheetsScopes



fun connectSheetsService(credential: Credential): Sheets {
    val httpTransport = GoogleNetHttpTransport.newTrustedTransport()
    val jsonFactory: JsonFactory = JacksonFactory.getDefaultInstance()

    return Sheets.Builder(httpTransport, jsonFactory, credential)
        .setApplicationName("GoogleSheet Sample Reader")
        .build()
}
  • 앞선 함수에서 만든 Credential객체를 인자로 받습니다.
  • 구글시트 client를 연결하고 sheets 객체를 반환합니다.

마지막으로 우리가 만든 구글시트에 접근하여 필요한 데이터를 추출하는 함수를 만들어봅시다.

import com.google.api.services.sheets.v4.model.ValueRange

// (1)
fun readValueRange(sheets: Sheets, range: String): List<List<String>> {
    val response: ValueRange = sheets.spreadsheets().values()
        // (2)
        .get("1e4St5P7bwtP4Mf3lW_MRE3s15xrQEZNpvUiub-iv6Wg", range)
        .execute()

    // (3) 단순하게 문자열 리스트로 반환하자..
    return response.getValues().map { row -> row.map { value -> value.toString() } }
}
  • (1) 앞선 함수에서 받은 sheets 객체와 범위를 함께 인자로 받습니다.
  • (2) get의 인자에는 우리가 만든 구글시트의 ID값을 넣어줍니다.
    • 구글 시트의 URL이 https://docs.google.com/spreadsheets/d/1e4St5P7bwtP4Mf3lW_MRE3s15xrQEZNpvUiub-iv6Wg 라면 url의 가장 마지막 path 값이 시트의 ID값입니다.
  • (3) 구체적으로 타입을 가져올수 있지만, 지금은 단순하게 문자열로 결과를 꺼냈습니다. 아래와 같은 형태로 결과가 반환됩니다.
    • [["1", "타이틀", "2022-01-03", "2022-01-05", ""], ["2", "타이틀2", "2022-02-03", "2022-02-05", ""], ]

이제 다 되었습니다. 모든정보를 합쳐서 우리가 원하는 결과로 만들고 반환해봅시다.

fun fetchSheets(): List<Banner> {
    // 구글 인증처리
    val credential = connectGoogleCredentials()
    println("[GoogleSheetFetchService] google 인증 완료")

    // sheets 서비스 연결
    val sheetsService = connectSheetsService(credential)
    println("[GoogleSheetFetchService] google sheets 서비스 연결")

    // 배너 결과 객체 리스트 반환
    return readValueRange(sheetsService, "배너!A4:E").map {
        Banner(
            id = it[0].toLong(),
            title = it[1],
            startDateTime = LocalDateTime.parse(it[2]),
            endDateTime = LocalDateTime.parse(it[3])
        )
    }
}

최종적으로 객체가 만들어진 모습을 확인할 수 있습니다.
좀 더 자세한 확인이 필요하시다면 아래의 샘플코드를 확인해주세요.

https://github.com/devsejong/googlesheet-connect-demo

마무리

아마 실무에서는 이러한 방법을 사용하기는 쉽지 않아보입니다.
구글시트이기에 정합성이 맞지않는 데이터가 들어가며, 읽는 속도도 느리기 때문입니다.

타임어택과 같은 상황이 벌어지는 사이드프로젝트에서는 이러한 방법은 충분히 유용할것으로 생각합니다.
어드민을 만들고 서버를 띄우고.. 기나긴 과정을 충분히 생략할 수 있을것이니깐요.

이상으로 해당 글을 마무리짓고자 합니다. 조금이나마 도움이 되셨으면 좋겠네요.
읽어주셔서 감사합니다.

profile
게으름뱅이 프로그래머

0개의 댓글

관련 채용 정보