Tag Archives: 구글

Server to Server 어플리케이션을 위한 Google OAuth 2.0

google_developers_logo

Google OAuth 2.0 시스템은 웹 어플리케이션과 구글 서비스간의 통신과 같은 서버간 통신을 지원합니다. 이러한 시나리오를 위해서는 개별 최종 사용자 대신에 당신의 어플리케이션에 속하는 서비스 계정(Service Account)가 필요합니다. 당신의 어플리케이션은 서비스 계정을 이용하여 구글 API를 호출할 수 있으며 이 경우 사용자가 직접적으로 연관되지 않습니다. 이 시나리오는 “Two-Legged OAuth” 또는 “2LO”로 불립니다. (비슷한 용어로 “Three-Legged OAuth”의 경우에는 최종 사용자가 구글 API를 호출하는 경우를 말하며 이때에 권한 요청 화면이 뜰 수 있습니다)

일반적으로, 어플리케이션이 구글 API를 호출할 때 사용자의 정보보다는 어플리케이션 자체의 정보를 가지고 작업할 때 서비스 계정을 사용합니다. 예를 들어 데이터를 영구적으로 저장하기 위해 Google Cloud Datastore를 사용하는 어플리케이션이 있다면 서비스 계정을 사용하여 인증하여 사용할 수 있습니다.

Google Apps의 도에인 관리자를 이용하면 도메인의 유저들을 대표하여 사용자 정보에 접근할 수 있는 전체 도메인 권한을 부여할 수 있습니다. 이 문서에서는 어플리케이션이 Google APIs 클라이언트 라이브러리 또는 HTTP를 이용하여 OAuth 2.0 서버간(Server to Server) 호출을 하는 방법에 대해 정리합니다.

개요

서버간 상호작용을 지원하기 위해서 먼저 개발자 콘솔에 있는 당신의 프로젝트의 서비스 계정을 만들어야 합니다. 만약 당신이 Google Apps 도메인 내의 사용자 정보에 접근하고자 한다면 도메인 전체(domain-wide) 접근 권한을 서비스 어카운트에 부여해야 합니다.

그다음 당신의 어플리케이션이 OAuth 2.0 인증 서버로부터 엑세스토큰을 요청하기 위해  서비스 계정 자격을 이용하여 인증 API 요청을 만듭니다.

마지막으로  당신의 어플리케이션은 구글 API를 호출할 수 있는 엑세스토큰을 사용할 수 있게 됩니다.

추천 : 당신의 어플리케이션은 이러한 작업을 당신이 사용하는 언어에 적절한 구글 API 클라이언트 라이브러리를 사용하거나 HTTP를 직접 이용하여 OAuth 2.0 시스템과 통신하는 방법을 사용할 수 있습니다. 하지만 서버간 통신을 통한 인증 과정에서 암호화 사인이 된 JSON Web Tokens (JWTs)를 만들어 사용하게 되고 이 부분에서 당신의 어플리케이션의 보안에 치명적인 영향을 끼칠 수 있는 심각한 에러가 발생하기 쉽습니다.

이런 이유로 우리는 구글 API 클라이언트 라이브러리를 사용하여 당신의 어플리케이션 코드에서 암호화 관련 처리를 신경쓰지 않기를 강력하게 추천합니다.

서비스 계정 만들기

서비스 계정 자격은 유니크하게 생성된 이메일주소(email address)와 최소한 한개의 공개/비밀 키쌍(public/private key pair)이 포함됩니다. 만약에 도메인 전체 위임을 활성화 한다면 클라이언트 아이디(client id) 역시 서비스 계정 자격에 포함되어야 합니다.

당신의 어플리케이션이 구글 앱 엔진(Google App Engine)에서 돌아간다면 서비스 계정은 당신의 프로젝트가 생성될 때 자동으로 설정됩니다.

만약 당신의 어플리케이션이 구글 컴퓨트 엔진(Google Compute Engine)에서 돌아간다면 프로젝트 생성시 서비스 계정은 자동으로 설정되지만 어플리케이션이 접근하고자 하는 접근 범위(Scope)를 정의해 주어야 합니다. [참고]

당신의 어플리케이션이 구글 앱엔진 또는 구글 컴퓨트엔진 에서 동작하지 않는다면 구글 개발자 콘솔에서 이러한 자격을 획득하여야 합니다. 서비스 계정 자격을 생성하기 위해서, 혹은 이미 생성된 공개된 자격을 보기 위해서는 다음을 수행합니다.

  1. 개발자 콘솔 권한(Permission) 페이지의 서비스 계정 섹션(Service accounts section)에 진입합니다.

google_api_oauth_01

2. 서비스 계정 만들기 버튼을 누릅니다.

google_api_oauth_02

3. 서비스 계정 만들기 창에서 서비스 계정의 이름을 입력하고, 새 비공개 키 제공을 선택합니다. 만약 구글 앱스 도메인 전체 인증을 허용하려면 Google Apps 도메인 전체 위임 사용을 체크하시면 됩니다. 그리고 만들기를 클릭합니다.

google_api_oauth_03

당신의 새로운 공개/비공개 키 쌍이 생성되며 당신의 컴퓨터에 다운로드 됩니다. 이것은 단 하나의 복사본이기에 당신은 안전하게 이 키를 보관할 의무가 있습니다.

당신은 언제든지 이 개발자 콘솔에 돌아와서 이메일 주소, 키 ID와 같은 정보를 확인할 수 있습니다. 또는 추가로 공개/비공개 키를 생성할 수 있습니다. 개발자 콘솔에서의 서비스 계정 자격에 대한 더 자세한 내용은 [참고]를 확인해주세요.

서비스 계정의 이메일 주소를 적어놓고 서비스 계정의 P12 비밀키 파일을 당신의 어플리케이션이 접근할 수 있는 위치에 저장하십시오. 당신의 어플리케이션이 인증 API 호출을 만드는데 이것들이 필요합니다.

참고 : 당신은 개발 환경과 프로덕션 환경 모두에서 이 비밀키를 안전하게 보관하고 관리해야 합니다. 구글은 당신의 비밀키의 복사본을 보관하지 않습니다. 단지 공개키만을 가지고 있습니다.

인증 API 호출을 준비하기

구글에서는 구글 API 호출을 위한 라이브러리로 Java를 비롯한 다양한 언어를 지원하고 있습니다. [참고]를 확인해주세요.

구글 개발자 콘솔에서 이메일 주소와 비밀키를 획득한 뒤 JAVA용 구글 API 클라이언트 라이브러리를 이용하여 서비스 계정 자격 및 어플리케이션이 엑세스를 원하는 범위를 정의하는 GoogleCredential을 생성합니다.

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.sqladmin.SQLAdminScopes;

// ...

String emailAddress = "123456789000-abc123def456@developer.gserviceaccount.com";
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = new GoogleCredential.Builder()
    .setTransport(httpTransport)
    .setJsonFactory(JSON_FACTORY)
    .setServiceAccountId(emailAddress)
    .setServiceAccountPrivateKeyFromP12File(new File("MyProject.p12"))
    .setServiceAccountScopes(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .build();

만약 도메인 전체 위임을 포함한 서비스 어카운트이고 특정 유저로 가장하여 사용하고 싶을 경우 GoogleCredential 팩토리의 setServiceAccountUser 메소드를 사용하여 사용자 계정의 이메일 주소를 특정해 주시기 바랍니다.

GoogleCredential credential = new GoogleCredential.Builder()
    .setTransport(httpTransport)
    .setJsonFactory(JSON_FACTORY)
    .setServiceAccountId(emailAddress)
    .setServiceAccountPrivateKeyFromP12File(new File("MyProject.p12"))
    .setServiceAccountScopes(Collections.singleton(SQLAdminScopes.SQLSERVICE_ADMIN))
    .setServiceAccountUser("user@example.com")
    .build();

이제 이렇게 만들어진 GoogleCredential 객체를 사용하여 당신의 어플리케이션에서 구글 API를 호출할 수 있습니다.

구글 API 호출

GoogleCredential 객체를 사용하여 구글 API를 다음과 같은 방법으로 호출할 수 있습니다.

1. GoogleCredential 객체를 사용하여 당신이 사용하고자 하는 API의 서비스 객체를 생성합니다.

SQLAdmin sqladmin =
    new SQLAdmin.Builder(httpTransport, JSON_FACTORY, credential).build();

2. 서비스 객체가 제공하는 인터페이스를 사용하여 원하는 API의 요청을 생성합니다. 예를 들어 exciting-example-123 프로젝트의 클라우드 SQL 데이터베이스에 존재하는 리스트를 불러오는 코드는 다음과 같습니다.

SQLAdmin.Instances.List instances =
    sqladmin.instances().list("exciting-example-123").execute();

참고 : Using OAuth 2.0 to Access Google APIs

Google Play 부가가치세(VAT) 및 판매세(Sales Tax) 알아보기

이번에는 구글플레이를 통해서 앱을 판매할 때 겪게 될 세금 정보에 대해서 알아보겠습니다. 국내 또는 해외에 위치한 개발자가 한국의 사용자들에게 앱을 판매할 경우 한국 정부에 부가가치세(VAT)를 내야 합니다. 구글 플레이에서 안내하고 있는 VAT 가이드 라인은 다음과 같습니다.google_play_vat_guidelines

정리해 보자면 한국에 거주하는 개발자의 경우 구글플레이에서 정산받은 수익금중 10%를 개발자가 알아서 송금하시면 됩니다. 말을 좀 더 쉽게 풀어써보면 한국에 거주하는 개발자는 부가가치세 납부를 직접 해야 할 책임이 있다, 정도로 보시면 될 것 같습니다. 하지만 해외에 거주하는 개발자가 한국의 사용자들에게 판매할 때 발생하는 부가세는 구글이 직접 10%의 부가세를 추가로 취한 뒤 직접 정부에 대납 해주는 일을 합니다. 즉 해외 개발사는 한국에 직접 세금 신고를 해야 할 필요는 없습니다.

생각해 보면 국내 사용자를 대상으로 장사하는(?) 해외 개발사는 구글이 알아서 다 처리해 주니 한국의 부가세에 대해 깊이 생각할 필요가 없습니다. 하지만 국내 거주 개발사라면 이야기가 달라집니다. 위의 가이드 라인에 의하면 “대한민국에 거주하는 개발자는 대한민국 고객이 Google Play 스토어에서 디지털 콘텐츠를 구매할 경우 VAT를 결정하고 청구하고 송금할 책임이 있습니다.”라는 말이 있습니다. 개발자는 판매하는 디지털 콘텐츠의 가격에 VAT를 포함시켜야 하며 포함된 가격을 어떻게 책정할 것인지 직접 판단해야 합니다.

즉, 만약 한국에 거주중인 개발자가 1,000원 짜리 디지털 콘텐츠를 판매한다고 할 때 다음과 같은 상황을 고려해야 합니다.

  • 상품 가격 1,000원에 VAT 100원을 더하며 상품을 실제로 1,100원에 판매
  • 상품 가격 909.1원에 VAT 90.9원을 더하여 상품을 실제로 1,000원에 판매

전자는 VAT를 구매자에게 완전히 떠넘기는 셈법이 될 것이고, 후자는 VAT를 개발사가 떠안는 방법이 될 것입니다. 하지만 VAT는 당연히 구매자가 부담해야 하는 것이므로 1,100원에 판매하는게 당연한 이야기일 것 같네요. 무엇보다 구글이 30%를 띄어가게 되는데 세금 설정을 따로 해주셔야 세금은 이 30%에서 빠지게 됩니다.

자 그럼 판매세(Sales Taxes) 설정을 통해서 자연스럽게(?) 사용자에게 VAT를 부과하는 방법에 대해 알아보겠습니다.

google_play_sales_tax_guideline

구글에서 이야기하는 판매세는 위와 같습니다. 개발자는 자신이 판매하는 디지털 콘텐츠의 판매 가격에 붙는 세율을 자유롭게 설정하는 것이 가능합니다. 바로 이 판매세라는것을 이용해서 말이죠.

[Google Play Payments 판매자 센터]에 방문하여 설정 – 판매세 메뉴에 들어갑니다.

google_play_sales_taxes_1

한국은 캐나다도 유럽연합도 미국도 아니므로 기타국가 및 지역의 수정을 눌러서 값을 변경해 보겠습니다.

google_play_sales_taxes_2

대한민국의 값이 비어있네요. 여기에 10%로 설정해 주시면 됩니다.

google_play_sales_taxes_3

네 대한민국이 10%로 추가되었습니다. 이제 앱 내 결제를 구동할 때 다음과 같이 자동으로 10%의 세금이 추가되어 과금되게 됩니다. 별도로 앱 내부에서 판매중인 디지털 콘텐츠의 가격을 10% 붙은 가격으로 노출해 줄 필요도 있겠네요.

google_payment_pop_with_tax

구글 판매자 계정에서 확인할 수 있는 판매 영수증을 보시면 다음과 같이 정상적으로 VAT가 붙어있는것을 확인 하실 수 있습니다.

google_play_payment_receipt

마지막으로 구글에서 발행하는 리포트에 대해서 알아보겠습니다. [Google Play Developer Console]의 보고서 – 재무보고서에 방문하면 관련된 리포트를 다운받아 볼 수 있습니다. 리포트의 내용중에 세금 관련되어 표기된 부분만 확인해 보겠습니다.

google_play_tax_report_korea

하나의 상품이 3개의 행(Row)로 이루어져 있는것을 볼 수 있습니다. 하나의 상품에 대해 Google fee, Charge, Tax로 분류 되어있습니다. 각각은 다음을 의미합니다.

  • Google fee : 구글이 과금한 판매 30%의 수수료, 판매 가격의 30%가 음수로 이곳에 적혀 있습니다.
  • Charge : 유저에게 과금된 금액. 결과적으로 Charge – Google fee가 개발자가 받게 되는 수익금 입니다.
  • Tax : VAT 10%값입니다. Google fee 계산에서 제외되며 국내 거주 개발자의 경우 우선 지급이 되지만 나중에 직접 세금을 정부에 송금하셔야 하는 부분입니다.

여기서 잘 봐두실 부분은 Buyer CurrencyMerchant Currency 입니다. 전자는 구매자의 화폐단위이며 후자는 판매자가 수령하게 될 국가 기준의 화폐단위 입니다. 둘다 한국이므로 KRW로 써있는것을 볼 수 있습니다.

google_play_tax_report_hongkong

이번에는 참고로 해외 판매자의 리포트를 보겠습니다. 한국 사용자들에게 디지털 콘텐츠를 판매중인 홍콩의 개발자의 리포트입니다. 국내 개발자와 다른점은 Tax 항목이 아예 없는것을 볼 수 있습니다. 이는 구글이 직접 10%의 VAT를 직접 추가 징수한 뒤 한국에 납부하게 되므로 세금 정보가 아예 빠져있습니다. 그리고 Merchant Currency를 통해 HKD(홍콩 달러) 로 환전되는 것을 알 수 있습니다. 이를 통해서 개발자가 해외 거주 개발자라는것을 유추해 볼 수 있겠네요.