Skip to content

Latest commit

 

History

History
352 lines (276 loc) · 14.4 KB

6.sheetsToCafe.md

File metadata and controls

352 lines (276 loc) · 14.4 KB

실습 6에서는 Google Sheets에서 특정 칼럼이 체크되면 ChatGPT API를 통해 내용을 요약하고, 이를 네이버 카페 API를 활용하여 자동으로 게시글을 업로드하는 시스템을 구축합니다. 또한, 추가 실습으로 게시글에 이미지 첨부 기능도 구현해보겠습니다.


1. Google Sheets 설정

1-1. 스프레드시트 생성 및 구성

  1. 스프레드시트 생성:

    • Google Sheets에 접속하여 새로운 스프레드시트를 만듭니다.
    • 예시: 게시글 관리 시트
  2. 시트 구성:

    • 첫 번째 행에 헤더를 추가합니다: 제목, 내용, 요약, 게시 여부
    • 게시 여부 열은 체크박스 형식으로 설정합니다:
      • 해당 열을 선택한 후, 상단 메뉴에서 삽입 > 체크박스를 클릭합니다.

2. ChatGPT API 설정

2-1. OpenAI API 키 발급

  1. OpenAI 계정 생성 및 로그인:

    • OpenAI에서 계정을 생성하고 로그인합니다.
  2. API 키 생성:

    • 로그인 후, API 키 생성 페이지에서 새로운 비밀 키를 생성하고 복사하여 안전한 곳에 저장합니다.

3. 네이버 카페 API 설정

3-1. 네이버 개발자 센터에서 애플리케이션 등록

  1. 네이버 개발자 센터 접속 및 로그인:

  2. 애플리케이션 등록:

    • 상단 메뉴에서 애플리케이션 > 애플리케이션 등록을 클릭합니다.
    • 애플리케이션 이름과 사용 API를 선택합니다. 여기서는 네이버 로그인카페 API를 선택합니다.
  3. Redirect URI 설정:

    • 애플리케이션 등록 시 Redirect URI를 설정해야 합니다. 이는 OAuth 2.0 인증 과정에서 필요합니다.
    • 예시: https://your-redirect-uri.com/callback

3-2. 네이버 카페 API 사용을 위한 인증 토큰 발급

  1. 네이버 로그인 API를 통한 사용자 인증:

    • 네이버 로그인 API를 사용하여 사용자의 인증을 받아 **접근 토큰(access token)**을 발급받습니다.
    • 자세한 내용은 네이버 로그인 개발 가이드를 참고하세요.
  2. 카페 API 권한 요청:

    • 발급받은 접근 토큰을 사용하여 카페 API를 호출할 수 있습니다.
    • 카페에 게시글을 작성하려면 사용자가 해당 카페의 회원이어야 하며, API 사용 권한이 부여되어야 합니다.

4. Google Apps Script 작성

4-1. Apps Script 편집기 열기

  1. 편집기 열기:
    • Google Sheets에서 상단 메뉴의 확장 프로그램 > Apps Script를 클릭합니다.

4-2. 스크립트 작성

  1. ChatGPT를 통한 내용 요약 함수 작성:

    • OpenAI의 ChatGPT API를 호출하여 입력된 내용을 요약하는 함수를 작성합니다.
    /**
     * ChatGPT API를 호출하여 내용을 요약하는 함수
     * @param {string} content - 요약할 원본 내용
     * @returns {string} - 요약된 내용
     */
    function generateSummary(content) {
      const apiUrl = 'https://api.openai.com/v1/completions';
      const prompt = `다음 내용을 요약해 주세요:\n\n${content}`;
    
      const options = {
        method: 'post',
        headers: {
          'Authorization': `Bearer ${OPENAI_API_KEY}`,
          'Content-Type': 'application/json'
        },
        payload: JSON.stringify({
          model: 'text-davinci-003',
          prompt: prompt,
          max_tokens: 150
        })
      };
    
      try {
        const response = UrlFetchApp.fetch(apiUrl, options);
        const json = JSON.parse(response.getContentText());
        return json.choices[0].text.trim();
      } catch (error) {
        Logger.log('요약 생성 오류:', error);
        return '';
      }
    }
  2. 네이버 카페에 게시글을 업로드하는 함수 작성:

    • 네이버 카페 API를 사용하여 게시글을 업로드하는 함수를 작성합니다.
    /**
     * 네이버 카페에 게시글을 업로드하는 함수
     * @param {string} title - 게시글 제목
     * @param {string} content - 게시글 내용
     * @returns {object} - API 응답 객체
     */
    function postToNaverCafe(title, content) {
      const apiUrl = `https://openapi.naver.com/v1/cafe/${NAVER_CAFE_ID}/menu/${NAVER_CAFE_MENU_ID}/articles`;
    
      const options = {
        method: 'post',
        headers: {
          'Authorization': `Bearer ${ACCESS_TOKEN}`,
          'Content-Type': 'application/json',
          'X-Naver-Client-Id': NAVER_CLIENT_ID,
          'X-Naver-Client-Secret': NAVER_CLIENT_SECRET
        },
        payload: JSON.stringify({
          subject: title,
          content: content
        })
      };
    
      try {
        const response = UrlFetchApp.fetch(apiUrl, options);
        return JSON.parse(response.getContentText());
      } catch (error) {
        Logger.log('게시글 업로드 오류:', error);
        return null;
      }
    }
  3. 스프레드시트에서 체크박스 변경을 감지하여 자동으로 처리하는 함수 작성:

    • 스프레드시트의 '게시 여부' 열에서 체크박스가 체크되면 자동으로 요약 및 게시를 수행하는 함수를 작성합니다.
    /**
     * 스프레드시트에서 '게시 여부' 체크박스 변경 시 호출되는 함수
     * @param {Event} e - onEdit 이벤트 객체
     */
    function onEdit(e) {
      const sheet = e.source.getActiveSheet();
      const range = e.range;
      const column = range.getColumn();
      const row = range.getRow();
      const postColumn = 4; // '게시 여부' 열 번호
    
      // '게시 여부' 열에서 체크박스가 체크된 경우
      if (column === postColumn && range.getValue() === true) {
        const title = sheet.getRange(row, 1).getValue();
        const content = sheet.getRange(row, 2).getValue();
        const summary = generateSummary(content);
    
        // 요약된 내용을 '요약' 열에 입력
        sheet.getRange(row, 3).setValue(summary);
    
        // 네이버 카페에 게시글 업로드
        const postContent = `요약: ${summary}\n\n원문: ${content}`;
        const response = postToNaverCafe(title, postContent);
    
        if (response) {
          Logger.log('게시 성공:', response);
        } else {
          Logger.log('게시 실패');
        }
      }
    }

4-3. 트리거 설정

  1. 트리거 추가:

    • Apps Script 편집기에서 상단의 시계 아이콘(트리거)을 클릭합니다.
    • 트리거 추가 버튼을 눌러 새로운 트리거를 생성합니다.
    • 다음과 같이 설정합니다:
      • 함수: onEdit
      • 이벤트 소스: 스프레드시트
      • 이벤트 유형: 수정 시
  2. 권한 부여:

    • 트리거를 설정하면 해당 스크립트가 외부 서비스(API)에 접근할 수 있도록 권한을 부여해야 합니다.
    • 권한 요청 창이 나타나면 지시에 따라 권한을 승인합니다.

5. 테스트 및 검증

  1. 테스트 데이터 입력:

    • 스프레드시트에 테스트용 데이터를 입력합니다.
      • 예시:
        • 제목: 새로운 제품 출시
        • 내용: 저희 회사에서 새로운 제품을 출시했습니다. 많은 관심 부탁드립니다.
        • 요약: (비워둠)
        • 게시 여부: (체크박스 미체크)
  2. 게시 여부 체크:

    • 해당 행의 '게시 여부' 열에 체크박스를 체크합니다.
    • 잠시 후 '요약' 열에 요약된 내용이 입력되고, 네이버 카페에 게시글이 업로드되었는지 확인합니다.

추가 실습: 게시글에 이미지 추가하기

네이버 카페 API를 통해 게시글에 이미지를 첨부하려면 multipart/form-data 형식으로 요청을 보내야 합니다. 그러나 Google Apps ScriptUrlFetchApp은 기본적으로 multipart/form-data 형식의 요청을 직접 지원하지 않습니다. 따라서, 이를 구현하기 위해서는 수동으로 HTTP 요청의 본문을 작성해야 합니다.

1. Google Drive에 이미지 저장

우선, 첨부할 이미지를 Google Drive에 저장하고, 해당 이미지 파일을 스크립트에서 접근할 수 있도록 합니다.

  1. 이미지 업로드:

    • Google Drive에 접속하여 첨부할 이미지를 업로드합니다.
  2. 파일 ID 확인:

    • 업로드한 이미지 파일을 마우스 오른쪽 버튼으로 클릭하고, 공유를 선택합니다.
    • 공유 설정에서 링크가 있는 모든 사용자에게 공개로 설정하여 링크 복사를 클릭합니다.
    • 복사한 링크에서 파일 ID를 추출합니다. 파일 ID는 URL 중간의 고유한 문자열입니다. 예: https://drive.google.com/file/d/FILE_ID/view에서 FILE_ID 부분이 파일 ID입니다.

2. Google Apps Script 수정

이제, 스크립트에서 해당 이미지를 읽어와 네이버 카페에 게시글과 함께 업로드하도록 코드를 수정합니다.

  1. 이미지 파일 읽기 함수 추가:

    Google Drive에 저장된 이미지를 읽어오는 함수를 작성합니다.

    /**
     * Google Drive에서 이미지 파일을 읽어오는 함수
     * @param {string} fileId - 이미지 파일의 ID
     * @returns {Blob} - 이미지 파일의 Blob 객체
     */
    function getImageBlob(fileId) {
      try {
        const file = DriveApp.getFileById(fileId);
        const blob = file.getBlob();
        return blob;
      } catch (error) {
        Logger.log('이미지 파일 읽기 오류:', error);
        return null;
      }
    }
  2. 네이버 카페에 게시글과 이미지 업로드 함수 수정:

    이전에 작성한 postToNaverCafe 함수를 수정하여 이미지도 함께 업로드하도록 합니다.

    /**
     * 네이버 카페에 게시글과 이미지를 업로드하는 함수
     * @param {string} title - 게시글 제목
     * @param {string} content - 게시글 내용
     * @param {string} imageFileId - 첨부할 이미지 파일의 ID
     * @returns {object} - API 응답 객체
     */
    function postToNaverCafeWithImage(title, content, imageFileId) {
      const apiUrl = `https://openapi.naver.com/v1/cafe/${NAVER_CAFE_ID}/menu/${NAVER_CAFE_MENU_ID}/articles`;
      const boundary = '----WebKitFormBoundary' + Math.random().toString(36).substring(2);
      const imageBlob = getImageBlob(imageFileId);
    
      if (!imageBlob) {
        Logger.log('이미지 Blob을 가져오지 못했습니다.');
        return null;
      }
    
      const payload = Utilities.newBlob('', 'multipart/form-data; boundary=' + boundary)
        .setDataFromString(
          '--' + boundary + '\r\n' +
          'Content-Disposition: form-data; name="subject"\r\n\r\n' +
          title + '\r\n' +
          '--' + boundary + '\r\n' +
          'Content-Disposition: form-data; name="content"\r\n\r\n' +
          content + '\r\n' +
          '--' + boundary + '\r\n' +
          'Content-Disposition: form-data; name="image"; filename="' + imageBlob.getName() + '"\r\n' +
          'Content-Type: ' + imageBlob.getContentType() + '\r\n\r\n'
        )
        .getBytes()
        .concat(imageBlob.getBytes())
        .concat(Utilities.newBlob('\r\n--' + boundary + '--').getBytes());
    
      const options = {
        method: 'post',
        contentType: 'multipart/form-data; boundary=' + boundary,
        headers: {
          'Authorization': `Bearer ${ACCESS_TOKEN}`,
          'X-Naver-Client-Id': NAVER_CLIENT_ID,
          'X-Naver-Client-Secret': NAVER_CLIENT_SECRET
        },
        payload: payload
      };
    
      try {
        const response = UrlFetchApp.fetch(apiUrl, options);
        return JSON.parse(response.getContentText());
      } catch (error) {
        Logger.log('게시글 업로드 오류:', error);
        return null;
      }
    }
  3. onEdit 함수 수정:

    스프레드시트에서 '게시 여부' 체크박스가 체크될 때, 이미지도 함께 업로드하도록 onEdit 함수를 수정합니다.

    function onEdit(e) {
      const sheet = e.source.getActiveSheet();
      const range = e.range;
      const column = range.getColumn();
      const row = range.getRow();
      const postColumn = 4; // '게시 여부' 열 번호
      const imageFileIdColumn = 5; // '이미지 파일 ID' 열 번호
    
      if (column === postColumn && range.getValue() === true) {
        const title = sheet.getRange(row, 1).getValue();
        const content = sheet.getRange(row, 2).getValue();
        const imageFileId = sheet.getRange(row, imageFileIdColumn).getValue();
        const summary = generateSummary(content);
    
        sheet.getRange(row, 3).setValue(summary); // 요약 열에 결과 저장
    
        const postContent = `요약: ${summary}\n\n원문: ${content}`;
        const response = postToNaverCafeWithImage(title, postContent, imageFileId);
    
        if (response) {
          Logger.log('게시 성공:', response);
        } else {
          Logger.log('게시 실패');
        }
      }
    }

이제 Google Sheets에서 특정 칼럼을 체크하면 ChatGPT를 통해 내용을 요약하고, 네이버 카페 API를 활용하여 이미지와 함께 자동으로 게시글을 업로드하는 시스템을 구축할 수 있습니다.

중요 참고 사항:

  • 네이버 카페 API 사용 시 주의점: 네이버 카페 API를 통해 이미지를 업로드할 때, 이미지가 본문 상단에 고정되거나 원하는 위치에 삽입되지 않는 이슈가 있을 수 있습니다. 이러한 문제는 네이버 개발자 포럼에서 다루어지고 있으므로, 최신 정보를 확인하시기 바랍니다. citeturn0search5

  • API 사용 정책 준수: 네이버 카페 API를 사용하여 자동으로 게시글을 업로드할 때는 네이버의 API 사용 정책과 카페 운영 원칙을 준수해야 합니다. 자동화된 게시글 업로드는 카페의 스팸 방지 정책에 위배될 수 있으므로, 사용 전에 해당 카페의 운영 방침을 확인하시기 바랍니다.

이러한 시스템을 구축함으로써 업무 효율성을 높일 수 있지만, 항상 플랫폼의 정책과 규정을 준수하는 것이 중요합니다.