구글 앱스 스크립트로 블로그 글쓰기 아이디어 만들어보기 (Feat 구글스프레드시트)

소개

구글 앱스 스크립트로 블로그 글쓰기 아이디어 만들어보기 (Feat 구글스프레드시트)

블로그 글을 쓸 때 빠르고 간편하게 서론, 본론, 결론을 얻어내기 위함입니다.

진행 방법

ChatGPT O3-mini를 사용하였습니다.

Tip: 사용한 프롬프트 전문을 꼭 포함하고, 내용을 짧게 소개해 주세요.

프롬프트들

1) 역할: 당신은 대한민국에서 가장 유명한 구글 앱스 스크립트 전문가입니다. 전세계에서도 알아주는 전문가입니다. 당신은 자바스크립트 관련해서 뛰어난 능력을 가지고 있습니다.
2) 질문 이유: 코딩과 관련하여 잘 모르는 저에게 당신은 아주 훌륭한 코드를 제공해줄수 있습니다. 당신을 통해 코딩을 배우고 활용하고자 합니다.
3) 말투와 어조: 현명하고 친절한 말투로 부탁합니다. 구체적인 정보가 좋습니다.
4) 양식: 우선 당신은 방법을 저에게 알려주고 그 방법을 코드로 제공을 원하는지 저에게물어보셔야 합니다. 해당 [아이디어]를 실현시킬 수 있는 적절한 방법을 차근차근 제안해 주세요.
5) 지시문: 나는 당신에게 나의 [아이디어]를 줄 것입니다. 그럼 당신은 나의 [아이디어]에 알맞게 구글 앱스 스크립트 코드를 제작하는 방법을 먼저 알려줍니다. 그 뒤에 저에게코드를 원하는지 물어봅니다. 내가 원한다고 답할 때만 코드를 주세요. 만약 코드를 달라
는 별도의 말이 없는 경우는 절대 전체 코드를 주지 마세요
내가 원하는건 
주제를 내가 정하면
서론 , 본론1, 본론2, 본론3, 결론의 형태로 열을 달리해서 정리해주는거야 
필요하다면 chatgpt api 혹은 제미나이 api를 쓰도록 해
전체 코드를 주세요
단 아래 6개의 지시문을 반드시 준수해주세요
6개의 지시문을 단계적으로 읽고 이를 고려하여 코드를 생성합니다.

1) 코드에 있어서 오류가 나오지 않도록 천천히 차근차근 작성해주세요.

2) 사용자가 입력해야 하는 것이 있다면 맨 위에 표시해주세요. 변수를 관리하기 쉬워야 합니다. 

3) 구글 관련 문서를 생성한 경우 log에 생성된 구글 관련 문서 링크를 알려줄 수 있도록 구글 앱스 스크립트 코드를 작성하세요. 단 log 링크는 함수의 맨 하단에 있어야 합니다. 

4) 저는 코딩 초보라는 걸 명심하세요. 사용자가 쉽게 적용할 수 있는 내용으로 코드를 구성하세요.

5) 구글 관련 파일을 생성하는 함수를 작성하는 구글 앱스 스크립트 코드라면 항상 최상단에 해당 함수를 위치시켜주세요

6) 주석을 초등학생도 이해하기 쉽게 자세히 달아주세요.
예를 들어 a1에 주제를 입력했으면 b1~b5까지 서론 본론1, 본론2, 본론3, 결론을 200자 이상으로 만들어줘
a2에 주제를 입력하면 b2~b6에 만들어주는 방식이야 

Tip: 활용 이미지나 캡처 화면을 꼭 남겨주세요.

Tip: 코드 전문은 코드블록에 감싸서 작성해주세요. ( / 을 눌러 '코드 블록'을 선택)

최종 코드

/*******************************************************
 * [사용자 입력 변수]
 * 아래에 본인의 OpenAI API 키와 사용할 모델명을 입력하세요.
 *******************************************************/
const OPENAI_API_KEY = 'YOUR_OPENAI_API_KEY_HERE';  // 예: "sk-xxxxxxxxxxxxxxxxxxxx"
const OPENAI_MODEL = 'gpt-3.5-turbo';  // 예: "gpt-3.5-turbo"


/*******************************************************
 * [함수 1: createGoogleDoc]
 * 이 함수는 생성된 블로그 글 내용을 바탕으로
 * 새로운 구글 문서를 생성하고, 그 링크(URL)를 반환합니다.
 * (구글 관련 파일 생성 함수는 항상 최상단에 위치합니다.)
 *******************************************************/
function createGoogleDoc(subject, contentParts) {
  // 만약 contentParts가 undefined이면, 빈 객체로 만들어줍니다.
  contentParts = contentParts || {};

  // 각 부분(서론, 본론1, 본론2, 본론3, 결론)을 안전하게 읽어옵니다.
  var intro      = contentParts['서론']   || '';
  var body1      = contentParts['본론1']  || '';
  var body2      = contentParts['본론2']  || '';
  var body3      = contentParts['본론3']  || '';
  var conclusion = contentParts['결론']   || '';

  // 새로운 구글 문서를 생성합니다.
  var docTitle = '블로그 글 - ' + subject;
  var doc = DocumentApp.create(docTitle);
  
  // 문서의 본문(body)을 가져옵니다.
  var body = doc.getBody();
  
  // 제목(주제)을 문서에 추가합니다.
  body.appendParagraph('제목: ' + subject)
      .setHeading(DocumentApp.ParagraphHeading.HEADING1);
  
  // 각 부분(서론, 본론1, 본론2, 본론3, 결론)을 순서대로 문서에 추가합니다.
  body.appendParagraph('\n서론:\n' + intro);
  body.appendParagraph('\n본론1:\n' + body1);
  body.appendParagraph('\n본론2:\n' + body2);
  body.appendParagraph('\n본론3:\n' + body3);
  body.appendParagraph('\n결론:\n' + conclusion);
  
  // 문서를 저장하고 닫습니다.
  doc.saveAndClose();
  
  // 생성된 문서의 링크(URL)를 반환합니다.
  var docUrl = doc.getUrl();
  return docUrl;
}


/*******************************************************
 * [함수 2: callOpenAIChat]
 * 이 함수는 OpenAI의 ChatGPT API를 호출하여
 * 주어진 프롬프트에 맞는 응답을 JSON 객체로 반환합니다.
 *******************************************************/
function callOpenAIChat(prompt) {
  // OpenAI API의 URL입니다.
  var url = 'https://api.openai.com/v1/chat/completions';
  
  // API에 보낼 데이터(payload)를 준비합니다.
  var payload = {
    "model": OPENAI_MODEL,
    "messages": [
      {
        "role": "user",
        "content": prompt
      }
    ],
    "temperature": 0.7
  };
  
  // API 호출 옵션을 설정합니다.
  var options = {
    "method": "post",
    "contentType": "application/json",
    "headers": {
      "Authorization": "Bearer " + OPENAI_API_KEY
    },
    "payload": JSON.stringify(payload)
  };
  
  try {
    // API를 호출하여 응답을 받아옵니다.
    var response = UrlFetchApp.fetch(url, options);
    var responseText = response.getContentText();
    var jsonResponse = JSON.parse(responseText);
    
    // ChatGPT의 응답에서 message 내용을 가져옵니다.
    var messageContent = jsonResponse.choices[0].message.content;
    
    // 메시지 내용이 순수 JSON 형식의 문자열인지 확인하고, 객체로 변환합니다.
    var result = JSON.parse(messageContent);
    
    // 만약 result가 객체가 아니라면, 로그에 기록하고 null을 반환합니다.
    if (typeof result !== 'object') {
      Logger.log("API 응답이 올바른 형식이 아닙니다: " + messageContent);
      return null;
    }
    
    return result;
    
  } catch (e) {
    // 오류가 발생하면 로그에 오류 메시지와 응답 내용을 기록합니다.
    Logger.log("API 호출 또는 응답 파싱 중 오류 발생: " + e);
    Logger.log("응답 내용: " + (typeof responseText !== 'undefined' ? responseText : '응답 없음'));
    return null;
  }
}


/*******************************************************
 * [함수 3: generateBlogPost]
 * 이 함수는 스프레드 시트에서 주제를 읽어와서,
 * ChatGPT API를 호출하여 서론, 본론1, 본론2, 본론3, 결론을 생성한 후,
 * 결과를 스프레드 시트에 기록(세로로 한 열에 순서대로 기록)하고,
 * 구글 문서를 생성하여 그 링크를 로그에 출력합니다.
 *******************************************************/
function generateBlogPost() {
  // 1. 스프레드 시트와 현재 활성 시트를 가져옵니다.
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getActiveSheet();
  
  // 2. 현재 활성 셀의 행 번호를 가져옵니다.
  var activeRange = sheet.getActiveRange();
  var row = activeRange.getRow();
  
  // 3. A열(첫 번째 열)에 입력된 주제를 가져옵니다.
  var subject = sheet.getRange(row, 1).getValue();
  
  // 주제가 비어 있으면 사용자에게 알리고 함수를 종료합니다.
  if (!subject) {
    SpreadsheetApp.getUi().alert("A열에 주제를 입력한 후 다시 시도해 주세요.");
    return;
  }
  
  // 4. ChatGPT API에 보낼 프롬프트를 작성합니다.
  //    각 부분(서론, 본론1, 본론2, 본론3, 결론)은 반드시 200자 이상으로 작성해줘.
  //    반드시 JSON 형식만 출력해달라고 요청합니다.
  var prompt = 
    "주제: " + subject + "\n" +
    "아래 형식에 맞춰 블로그 글 원고를 작성해줘. 각 부분(서론, 본론1, 본론2, 본론3, 결론)은 반드시 200자 이상으로 작성해줘.\n" +
    "반드시 아래 JSON 형식만 출력해줘 (추가 설명이나 다른 문장은 포함하지 말아줘):\n" +
    "{\n" +
    '  "서론": "서론 내용",\n' +
    '  "본론1": "본론1 내용",\n' +
    '  "본론2": "본론2 내용",\n' +
    '  "본론3": "본론3 내용",\n' +
    '  "결론": "결론 내용"\n' +
    "}";
  
  // 5. API를 호출하여 결과를 가져옵니다.
  var contentParts = callOpenAIChat(prompt);
  
  // 6. API 응답이 예상한 형식(서론, 본론1, 본론2, 본론3, 결론)이 아니라면 사용자에게 알리고 종료합니다.
  if (!contentParts ||
      !contentParts.hasOwnProperty('서론') ||
      !contentParts.hasOwnProperty('본론1') ||
      !contentParts.hasOwnProperty('본론2') ||
      !contentParts.hasOwnProperty('본론3') ||
      !contentParts.hasOwnProperty('결론')) {
    SpreadsheetApp.getUi().alert("API 응답이 예상한 형식이 아닙니다.\n응답 내용: " + JSON.stringify(contentParts));
    return;
  }
  
  // 7. 스프레드 시트에 결과를 기록합니다.
  //    주제가 입력된 행(row)을 시작으로, B열에 순서대로 기록합니다.
  //    예) A1에 주제 입력 시, B1: 서론, B2: 본론1, B3: 본론2, B4: 본론3, B5: 결론
  sheet.getRange(row, 2).setValue(contentParts['서론']);
  sheet.getRange(row + 1, 2).setValue(contentParts['본론1']);
  sheet.getRange(row + 2, 2).setValue(contentParts['본론2']);
  sheet.getRange(row + 3, 2).setValue(contentParts['본론3']);
  sheet.getRange(row + 4, 2).setValue(contentParts['결론']);
  
  // 8. 생성된 내용을 바탕으로 구글 문서를 생성합니다.
  var docUrl = createGoogleDoc(subject, contentParts);
  
  // 9. 생성된 구글 문서 링크를 로그에 출력합니다. (함수의 맨 하단에 위치)
  Logger.log("생성된 구글 문서 링크: " + docUrl);
  
  // 10. 사용자에게 작업 완료 메시지를 알립니다.
  SpreadsheetApp.getUi().alert("블로그 글 생성이 완료되었습니다.\n생성된 구글 문서 링크는 로그(Logger)에서 확인할 수 있습니다.");
}


/*******************************************************
 * [함수 4: onOpen]
 * 이 함수는 스프레드 시트가 열릴 때 자동으로 실행되어
 * 사용자 메뉴에 '블로그 글 생성' 메뉴를 추가합니다.
 *******************************************************/
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('블로그 글 도구')
    .addItem('블로그 글 생성', 'generateBlogPost')
    .addToUi();
}
Google Docs- 스크린 샷 썸네일

3.5 결과

한자가있는 스프레드 시트

4.0-mini 결과 (글자수를 확실히 더 많이 생성해줌)

다수의 점이있는 종이 한 장
그것에 많은 숫자가있는 종이 한 장

실행방법

1) 구글 앱스 스크립트 - 확장프로그램 - 앱스 스크립트 선택

2) code.gs에 위의 코드 복사해서 불여넣기 하고 저장

3) 자신의 api-key로 교체

4) 모델 선택

5) 함수 onOpen 실행

여러 언어를 보여주는 웹 페이지의 스크린 샷

6) 스프레드시트에 다시 돌아가면 메뉴에 블로그 글 도구 생김

7) a1열에 주제 입력 후 a1을 클릭한 뒤 메뉴-블로그 글 도구-블로그 글 생성 클릭

해당 행을 전체를 클릭해야 합니다.

한국어 텍스트가있는 전화 사진

8) 기다리면 b1~b5열에 서론, 본론1, 본론2, 본론3, 결론이 생김

9) a2열에 썼다면 b2~b6열에 써지는 방식

10) 프롬프트를 더 잘 쓰면 더 잘 만들어줌

결과와 배운 점

  • 주제만 입력하면 서론, 본론, 결론을 알려주기 때문에 글의 뼈대를 잡을 때 유용하게 쓸 수 있을 것 같습니다.

  • 3.5를 써서 비용은 거의 안나올 것 같은데 4o-mini를 써서 성능과 가격을 둘다 잡아볼 예정입니다.

  • 프롬프트를 더 개선해볼 예정입니다.

도움 받은 글 (옵션)

14기 사이드 프로젝트 스터디

2

👉 이 게시글도 읽어보세요