Google Cloud 서비스 계정으로 Google API 사용하기

Google Sheet API를 사용하기 위해서 Google cloud console에서 서비스 계정을 만들어 진행하는 과정을 정리합니다.

준비 사항

Google cloud console 에서 프로젝트 & 서비스 계정 생성 처리

  1. Project 생성
  2. LEFT MENU >> APIs & Services 선택
  3. ENABLE APIS AND SERVICES. 클릭
  4. API 항목에서 Google Sheets API 활성화 처리
  5. LEFT MENU >> APIs & Services >> Credentials >> Manage service accounts >> Create Service Accounts 선택
  6. 계정 정보 입력 후 계정 생성 완료(2, 3 단계는 옵션이라 그냥 완료 하면 됩니다.)
  7. 생성된 계정(email) 정보 클릭 >> KEYS 선택
  8. ADD KEY >> Create new key 선택
  9. JSON TYPE 선택 하여 파일 다운로드

첨부된 파일의 형태는 아래와 같습니다.

{
  "type": "service_account",
  "project_id": "keen-clarity-323809",
  "private_key_id": "cd53576f5c47b2b654605c8a7528cabd87bdee93",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQClhKfQF6zmI34T\nuetB4vZullnrXI65fkH1/YusnE/uU1rzmWPNarBqhbxzGeSJf0xedVvSW4cNavkG\nDHu3+inlbbieX9xh++2lNGpYwA5BsXPA3xD1lcaWyc71gk6V6kVtHJMFSocLCYZ/\nDCvGfYEcCiZRsrro1M6AuGy6Nug1qld7utCHJY8OwBp/KLyCmpmhXZE5qim8eul/\nLssM2QizCVxegXS3sH6BCUBZOJVVFXvfNveXc23TWvBQJP85/vaJARjVOJeNJbFQ\nObPOdvEo9RYEfmkrIaaFq/natGP/buBYLdPNnS6+x+6fKRyT5rm1q5LUrpyYKadi\nl40HJFNNAgMBAAECggEAHScTQ5SX8GT59NF/PTiTfQDgT5Ma1FMHnSMOMdXKQkjO\nMS+oI2sSLYDmo0NBPHJ+afiztoZGcDeSKt2SAOJ/9Jfxt3tc3qk3vyxPOtiA6lMt\n9x+S5h5+PtrGp/lOjBsaJVCuGHV6+Zew57mmECzUy7KB80vOnem1gXh6NgYruh/A\ntOATcB7BVk7DEDu7mUAM4BPBWb946WeCUr1L4ZD5VM8YdLAydTCGL39/6TKIDAGl\njDEe+x9IK6DTjm0JHsY9orTDzBLzMCRulOLeAIFzZxpnUnihafk/IQ9+l8SH+rkM\nc/008CMOnUpySLx6wwdCvz+TOhucW1a2RfbGYFUExQKBgQDivirN1jvMzzyQIu8U\nzaNsNPVNIMktLSUNzQEnZsMUGXBUfnAszi3OAHY6NYSEJjYMBFThIvuHqhZCUStV\nNPFTzuHx6mg5Oi4QQC8iW/x9mbeQNBsTiY/nZomgnVS8Kko2SKmINxOf1WkGFcyV\nKk+porKTIkW/m7AEsYLzby07wwKBgQC64BkyQib1sxS1hMVhP3l+A+m7OdbWLDDO\nDRJpxHNZW/Svs1egSF2wNqPZFKJ/LHwAPKxNaBCnfQMjxweDY9VzKBIwXl3boJ7m\nvRulzFsBTwRtYG9QKXYLRhvyZRHFs12XV3KISAy5X+kWG7JeZOj4jeAr0N0Qun6F\n9M+THYMTrwKBgAWTv+HIPzhOcKLq+Q598GMc+lunTst5rMumGz0o3euEpKqvYXr4\np0/F2yKbZmMJvZKWGLBg9+biXCHNdU9nOfhhwlT8+wtNTwy/R2mE8bT1LvqxDWlx\nnMSIVSJKPGdUcvba2rCrCiSIT0kDCEEzBTqa8eGEmkqYPcAfzaTHO0mZAoGADGJD\naTA3ErsuWSUWS26AZ5hsycp4cTL2fQEiwj2Rg09ztJ0G5olFJCNK0lzqs9DH2uAq\nburBh8fiCGHtHojkIUB7jBcE00Qeo53OkjsroLeSzIjCd6Z3uyGHQpXuCpLrVdcm\nsN9NcI9pi9yEAntfcPE99MlfjPc+4TOq+c3P3OMCgYB6YFCFBNpPdYqc8EkQ8OUc\nA2MDWRcCW9oKYvu2zvDLjq9zkznUMcW5PaPql1nIEfNW9LNzn/Bc3nSQ1iHaulGZ\nZjaCKdD6pftkMYC73FWIZXIsvmyC8T7TvRvFppdBHjPcSurOJi6ot74MHKhFudm6\nezS2Wh+8ABQ+ucrWUxpMOw==\n-----END PRIVATE KEY-----\n",
  "client_email": "sheetapi@keen-clarity-323809.iam.gserviceaccount.com",
  "client_id": "114733049967179666126",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/sheetapi%40keen-clarity-323809.iam.gserviceaccount.com"
}

동영상으로 따라 하기

읽거나 쓰려는 sheet에 권한 부여 하기

Google sheet에서 Share 버튼을 누른 이후, 생성한 서비스 계정에 READ/WRITE 권한을 부여 해야됩니다.

sheet 글 읽기

다음 라이브러리를 설치 해야 합니다.

npm install –save googleapis

sheet 읽고 쓰는 예제 코드

import { google, Auth } from 'googleapis';
class SheetApi {
    auth: Auth.GoogleAuth = new google.auth.GoogleAuth({
        keyFile: "credentials.json", //the key file
        //url to spreadsheets API
        scopes: "https://www.googleapis.com/auth/spreadsheets",
    });

    writeSheet() {
        //Auth client Object
        const authClientObject = await this.auth.getClient();
        //Google sheets instance
        const googleSheetsInstance = google.sheets({ version: "v4", auth: authClientObject });
        const spreadsheetId = "sheetId";

        //write data into the google sheets
        await googleSheetsInstance.spreadsheets.values.append({
            auth, //auth object
            spreadsheetId, //spreadsheet id
            range: "Sheet1!A:B", //sheet name and range of cells
            valueInputOption: "USER_ENTERED", // The information will be passed according to what the usere passes in as date, number or text
            resource: {
                values: [["첫번째 A 열 데이터", "1열 B열"], ["두번째 A 열 데이터", "2열 B열"]],
            },
        });
    }

    readSheet() {
        //Auth client Object
        const authClientObject = await this.auth.getClient();
        //Google sheets instance
        const googleSheetsInstance = google.sheets({ version: "v4", auth: authClientObject });
        const spreadsheetId = "sheetId";

        //Read front the spreadsheet
        const { data: { values } } = await googleSheetsInstance.spreadsheets.values.get({
            auth: this.auth, //auth object
            spreadsheetId, // spreadsheet id
            range: "DATA!A:B", //range of cells to read from.
        });

        return values;
    }
}

참고자료

Posted by lahuman

댓글을 달아 주세요

onPaste contentEditable 을 이용한 이미지 붙여 넣기 처리

페이스북 댓글창에서 클립보드에 저장(Ctrl+C) 된 이미지를 붙여넣기(Ctrl+V)를 하면, 이미지가 업로드 되는 것을 확인 할 수 있습니다.

이를 구현 하기 위해서는 우선 다음 HTMLElement.onpaste 이벤트에 대하여 알아야합니다.

간단하게 요약하면 붙여넣기를 처리할때 호출되는 이벤트 인데요. 붙여넣는 이벤트에서 이미지일 경우 업로드 처리를 하면 됩니다.

구현하기

구현은 React.js기반으로 구현 하였습니다.

import React from "react";
import axios from "axios";
import MockAdapter from "axios-mock-adapter";
import "./styles.css";

// 서버 없이 테스트를 위해서 axios-mock-adapter 사용
const mock = new MockAdapter(axios);
mock.onPost("/fileupload").reply(200, {
  seq: 1
});

// 원래 소스는 `<img src="/download/${seq}" width="100%"/>`;
const buildImageHtml = (seq) =>
  `<img src="https://lahuman.github.io/assets/img/logo.png" width="100%"/>`;

export default function App() {
  const comment = React.useRef();

  const fileUpload = async (blob) => {
    const formData = new FormData();
    formData.append("file", blob);
    const { data: fileInfo } = await axios.post(`/fileupload`, formData);
    return fileInfo;
  };

  const focusMoveWithFile = () => {
    comment.current.focus();
    if (
      typeof window.getSelection !== "undefined" &&
      typeof document.createRange !== "undefined"
    ) {
      const range = document.createRange();
      range.selectNodeContents(comment.current);
      range.collapse(false);
      const sel = window.getSelection();
      if (!sel) return;
      sel.removeAllRanges();
      sel.addRange(range);
    }
  };

  return (
    <div
      ref={comment}
      contentEditable="true"
      className="comment"
      suppressContentEditableWarning
      onPaste={async (event) => {
        // event.preventDefault(); 이 없을 경우 upload와 상관 없이 이미지가 붙음
        event.preventDefault();
        const item = event.clipboardData.items[0];
        if (item.type.indexOf("image") === 0) {
          const blob = item.getAsFile();
          const { seq } = await fileUpload(blob);
          const text = `${comment.current.innerHTML}${buildImageHtml(seq)}`;
          comment.current.innerHTML = text;
          focusMoveWithFile();
        } else {
          // 이미지가 아닐 경우 text로 처리 
          const paste = event.clipboardData.getData("text");
          if (paste) {
            const selection = window.getSelection();
            if (!selection) return;
            if (selection && !selection.rangeCount) return;
            selection?.deleteFromDocument();
            selection?.getRangeAt(0).insertNode(document.createTextNode(paste));
          }
        }
      }}
      placeholder="글을 작성해주세요 (글 작성 꿀팁 : 여기에 이미지를 Ctrl+C, Ctrl+V로 바로 붙여넣기 할 수 있어요!)"
    />
  );
}

예제 바로가기

기능은 생각보다 어렵지 않았고 재미있었다.

참고자료

Posted by lahuman

댓글을 달아 주세요

WSL 내에서 웹서버를 띄어서 확인이 안되는 경우 다음과 같이 처리 하여 주세요.

port foward를 위해서는 Netsh를 이용할 예정입니다.

1. net-tools를 WSL 안에 설치 하기

ubuntu 기준으로 다음의 명령어를 이용해서 설치 합니다.

sudo apt install net-tools

powser shell 실행 파일 생성하기

Netsh 설정이된 ps1 의 확장자를 가진 파일을 생성합니다.

다음을 network.ps1 이라는 파일을 생성합니다.

If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {   
  $arguments = "& '" + $myinvocation.mycommand.definition + "'"
  Start-Process powershell -Verb runAs -ArgumentList $arguments
  Break
}

$remoteport = bash.exe -c "ifconfig eth0 | grep 'inet '"
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if ($found) {
  $remoteport = $matches[0];
}
else {
  Write-Output "IP address could not be found";
  exit;
}

$ports = @(3000, 5500, 8080);

Invoke-Expression "netsh interface portproxy reset";

for ($i = 0; $i -lt $ports.length; $i++) {
  $port = $ports[$i];
  Invoke-Expression "netsh interface portproxy add v4tov4 listenport=$port connectport=$port connectaddress=$remoteport";
  Invoke-Expression "netsh advfirewall firewall add rule name=$port dir=in action=allow protocol=TCP localport=$port";
}

Invoke-Expression "netsh interface portproxy show v4tov4";

여기서 중요한 것은 $ports = @(3000, 5500, 8080); 부분입니다.

forward 할 port를 작성합니다.

3. 실행하기

powser shell에서 실행을 하면 다음과 같은 오류 메시지를 받을 수 있습니다.

 $> .\network.ps1
.\network.ps1 : 이 시스템에서 스크립트를 실행할 수 없으므로 C:\DEV\network.ps1 파일을 로드할 수 없습니다. 자세한
내용은 about_Execution_Policies(https://go.microsoft.com/fwlink/?LinkID=135170)를 참조하십시오.
위치 줄:1 문자:1
+ .\network.ps1
+ ~~~~~~~~~~~~~
    + CategoryInfo          : 보안 오류: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess

해결을 위해서 powser shell을 관리자 모드로 실행하고, Set-ExecutionPolicy -ExecutionPolicy RemoteSigned 명령어로 실행 규칙을 변경합니다.

$> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

실행 규칙 변경
실행 정책은 신뢰하지 않는 스크립트로부터 사용자를 보호합니다. 실행 정책을 변경하면 about_Execution_Policies 도움말
항목(https://go.microsoft.com/fwlink/?LinkID=135170)에 설명된 보안 위험에 노출될 수 있습니다. 실행 정책을
변경하시겠습니까?
[Y] 예(Y)  [A] 모두 예(A)  [N] 아니요(N)  [L] 모두 아니요(L)  [S] 일시 중단(S)  [?] 도움말 (기본값은 "N"): Y

이후 다시 실행하면 다음과 같이 정상 동작을 확인 할 수 있습니다.

$> .\network.ps1


확인됨


확인됨


확인됨


ipv4 수신 대기:             ipv4에 연결:

주소            포트        주소            포트
--------------- ----------  --------------- ----------
*               5500        192.168.254.148 5500
*               3000        192.168.254.148 3000
*               8080        192.168.254.148 8080

4. 테스트

WSL에서 5500 포트로 웹을 띄우과 브라우져에서 접속하여 확인하면 잘 동작 하는 것을 확인 할 수 있습니다.

참고 자료

Posted by lahuman

댓글을 달아 주세요