๐Ÿš€ ํšŒ๊ณ  ๋ฆฌํฌํŠธ ์ค€๋น„ 3๋‹จ๊ณ„: ๋ฐ์ผ๋ฆฌ ๋ฆฌํฌํŠธ ๋””์Šค์ฝ”๋“œ ์—ฐ๋™ & ๊ตฌ๊ธ€ ํ•  ์ผ ์ž๋™ํ™”

๐Ÿ“ ์†Œ๊ฐœ

๊ธฐ์กด์— ๋งŒ๋“  '๋ฐ์ผ๋ฆฌ ๋กœ๊ทธ ์ž๋™ ๋ฆฌํฌํŠธ ์‹œ์Šคํ…œ'์€ ๋งค์ผ ์•„์นจ ์ œ ํ•˜๋ฃจ๋ฅผ ๋ถ„์„ํ•ด ์ฃผ์ง€๋งŒ, ๋ช‡ ๊ฐ€์ง€ ์•„์‰ฌ์šด ์ ์ด ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฒซ์งธ, ์ด๋ฉ”์ผ๋กœ ์˜ค๋Š” ๋ฆฌํฌํŠธ์˜ ์›น์•ฑ ๋งํฌ๊ฐ€ ์—ด๋ฆฌ์ง€ ์•Š๋Š” ์˜ค๋ฅ˜๊ฐ€ ์žˆ์–ด ๋ถˆํŽธํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‘˜์งธ, ์ด๋ฉ”์ผ์€ ์ž˜ ํ™•์ธํ•˜์ง€ ์•Š๊ฒŒ ๋˜์–ด, ์ œ๊ฐ€ ์ž์ฃผ ์“ฐ๋Š” Discord๋กœ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค.

์…‹์งธ, AI๊ฐ€ ์ œ์•ˆํ•ด ์ฃผ๋Š” "์˜ค๋Š˜์˜ ์‹ค์ฒœ ์ œ์•ˆ"์„ ๋ˆˆ์œผ๋กœ๋งŒ ๋ณด๊ณ  ๋„˜๊ธฐ๋‹ˆ ์‹ค์ฒœ์œผ๋กœ ์ด์–ด์ง€์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ Google Tasks(์บ˜๋ฆฐ๋”)์— ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•ด ์‹คํ–‰๋ ฅ์„ ๋†’์ด๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค.


โ–ถ๏ธ ์ง„ํ–‰ ๋ฐฉ๋ฒ•

๐Ÿ›  ์‚ฌ์šฉ ๋„๊ตฌ

  • Google Apps Script (GAS): ๋ฆฌํฌํŠธ ์ƒ์„ฑ, ์›น์•ฑ ๋ฐฐํฌ, ๋””์Šค์ฝ”๋“œ ๋ฐœ์†ก

  • Google Sheets: ๋ฐ์ดํ„ฐ ์ €์žฅ ๋ฐ AI ์ธ์‚ฌ์ดํŠธ ๊ธฐ๋ก

  • Discord Webhook: ๋ฆฌํฌํŠธ ์•Œ๋ฆผ ์ˆ˜์‹ 

  • Activepieces: ๊ตฌ๊ธ€ ์‹œํŠธ์˜ AI ์ œ์•ˆ์„ ํŒŒ์‹ฑํ•˜์—ฌ Google Tasks๋กœ ์ž๋™ ๋“ฑ๋ก

  • Gemini: ์ฝ”๋“œ ์—๋Ÿฌ ๋””๋ฒ„๊น…, ์ •๊ทœํ‘œํ˜„์‹ ์ž‘์„ฑ, ์ž๋™ํ™” ๋กœ์ง ์„ค๊ณ„

1. Apps Script: ์›น์•ฑ ๋งํฌ ์˜ค๋ฅ˜ ํ•ด๊ฒฐ & ๋””์Šค์ฝ”๋“œ ์—ฐ๋™

โ‘  ์›น์•ฑ ๋ฐฐํฌ ๋ฌธ์ œ ํ•ด๊ฒฐ

์ด๋ฉ”์ผ ๋งํฌ๊ฐ€ ์—ด๋ฆฌ์ง€ ์•Š๋˜ ๋ฌธ์ œ๋Š” ๋ฐฐํฌ ์‹œ ์•ก์„œ์Šค ๊ถŒํ•œ์ด ์žˆ๋Š” ์‚ฌ์šฉ์ž๋ฅผ ๋‚˜๋งŒ์œผ๋กœ ํ•ด๋†“์•„์„œ ์ด๋ฉ”์ผ์—์„œ ๋ฐ”๋กœ ์—ด๋ฆฌ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ถŒํ•œ์„ Google ๊ณ„์ •์ด ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž๋กœ ์ˆ˜์ • ํ›„ ์žฌ๋ฐฐํฌ๋ฅผ ํ•˜๋‹ˆ ์ œ๋Œ€๋กœ ๋ฐ์ผ๋ฆฌ ๋ฆฌํฌํŠธ ๋งํฌ๊ฐ€ ์—ด๋ ธ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ณ  ์ €์žฅ๋งŒ ํ•ด์„œ๋Š” ์•ˆ ๋˜๊ณ , ๋ฐ˜๋“œ์‹œ [๋ฐฐํฌ] > [์ƒˆ ๋ฐฐํฌ]๋ฅผ ํ†ตํ•ด ๋ฒ„์ „์„ ์—…๋ฐ์ดํŠธํ•ด์•ผ ์ •์ƒ ์ž‘๋™๋ฉ๋‹ˆ๋‹ค.

  • ๋ฉ”์ผ ๋งํฌ๋ฅผ ํด๋ฆญํ–ˆ์„ ๋•Œ

  • ๋ฐฐํฌ์—์„œ ์‚ฌ์šฉ์ž ๊ถŒํ•œ [๋‚˜๋งŒ] -> [Google ๊ณ„์ •์ด ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž]๋กœ ์ˆ˜์ • ํ›„ ์žฌ๋ฐฐํฌ

โ‘ก ๋””์Šค์ฝ”๋“œ ์›นํ›„ํฌ ์—ฐ๋™

์ด๋ฉ”์ผ๋ณด๋‹ค ์ ‘๊ทผ์„ฑ์ด ์ข‹์€ ๋””์Šค์ฝ”๋“œ๋กœ ๋ฆฌํฌํŠธ๋ฅผ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด ์›นํ›„ํฌ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ๋””์Šค์ฝ”๋“œ ์›นํ›„ํฌ ์—ฐ๋™

  • ๋””์Šค์ฝ”๋“œ ์›นํ›„ํฌ ์„ค์ •์„ ์œ„ํ•ด ์™ผ์ชฝ ๋ฐ์‹œ๋ณด๋“œ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ์„ ํƒํ•ด์„œ ์†์„ฑ๊ฐ’ ์ถ”๊ฐ€


์ด๋•Œ AI์˜ ํ”ผ๋“œ๋ฐฑ์ด ๊ธธ์–ด์ง€๋ฉด ๋ฉ”์‹œ์ง€๊ฐ€ ์ž˜๋ฆฌ๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”๋ฐ, Gemini์˜ ๋„์›€์œผ๋กœ Embed ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜์—ฌ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

(ํ™œ์šฉ ํŒ) ๋””์Šค์ฝ”๋“œ Embed์˜ Field ๊ฐ’์€ 1,024์ž ์ œํ•œ์ด ์žˆ์ง€๋งŒ, Description์€ 4,096์ž๊นŒ์ง€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๊ธด AI ํ”ผ๋“œ๋ฐฑ์€ Description์œผ๋กœ ์˜ฎ๊ฒจ์•ผ ์ž˜๋ฆฌ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

JavaScript

// ๋””์Šค์ฝ”๋“œ ๋ฐœ์†ก ํ•จ์ˆ˜ (๊ธ€์ž์ˆ˜ ์ œํ•œ ํ•ด๊ฒฐ & ๋งํฌ ํฌํ•จ ๋ฒ„์ „)
function sendDiscordReport(date, stats, aiInsights) {
  // ... (์ƒ๋žต)
  // ๊ธด AI ํ”ผ๋“œ๋ฐฑ์„ ๋ณธ๋ฌธ(Description)์— ๋ฐฐ์น˜ํ•˜์—ฌ ์งค๋ฆผ ๋ฐฉ์ง€
  const payload = {
    "username": "๋ฐ์ผ๋ฆฌ ๋ฆฌํฌํŠธ ๋ด‡",
    "embeds": [{
      "title": `๐Ÿ“… ${date} ๋ฐ์ผ๋ฆฌ ๋กœ๊ทธ ๋ฆฌํฌํŠธ`,
      "url": reportUrl, 
      "description": `[๐Ÿ‘‰ ์›น์—์„œ ์ƒ์„ธ ๋ฆฌํฌํŠธ ํ™•์ธํ•˜๊ธฐ](${reportUrl})\n\n**๐Ÿค– AI ์ฝ”์น˜์˜ ํ”ผ๋“œ๋ฐฑ**\n${aiInsights}`,
      // ... (์ƒ๋žต)
    }]
  };
  // ... (์ƒ๋žต)
}
  • ๋””์Šค์ฝ”๋“œ๋กœ ๋ฐ›์€ ๋ฐ์ผ๋ฆฌ ๋ฆฌํฌํŠธ

    ํœด๋Œ€ํฐ์— ์žˆ๋Š” ํ•œ๊ตญ์–ด ์•ฑ ์Šคํฌ๋ฆฐ์ƒท

2. Activepieces: AI ์ œ์•ˆ์„ ๊ตฌ๊ธ€ ํ•  ์ผ(Tasks)๋กœ ์ž๋™ ๋“ฑ๋ก

  • ๊ตฌ๊ธ€ ์‹œํŠธ์— ์ €์žฅ๋œ AI์˜ ๊ธด ์กฐ์–ธ ์ค‘ "์˜ค๋Š˜์˜ ์‹ค์ฒœ ์ œ์•ˆ" 3๊ฐ€์ง€๋งŒ ์™ ๋ฝ‘์•„์„œ ์บ˜๋ฆฐ๋”์— ๋„ฃ๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. Activepieces์˜ Code Piece๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

โ‘  ์ดˆ๊ธฐ ๋ฌธ์ œ: ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ ์˜ค๋ฅ˜

์ฒ˜์Œ์—” AI๊ฐ€ "#### 1. ์ˆ˜๋ฉด..." ์ฒ˜๋Ÿผ ๋งˆํฌ๋‹ค์šด ํ—ค๋”๋ฅผ ๋ถ™์—ฌ์„œ ์จ์ฃผ๋Š” ๋ฐ”๋žŒ์— ์ฝ”๋“œ๊ฐ€ ๋ชฉ๋ก์„ ์ธ์‹ํ•˜์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

โ‘ก Gemini์—๊ฒŒ ์š”์ฒญํ•œ ํ”„๋กฌํ”„ํŠธ:

"Activepieces์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋กœ ํŒŒ์‹ฑํ•˜๋ ค๊ณ  ํ•˜๋Š”๋ฐ, Input ๋ฐ์ดํ„ฐ๋Š” ๋“ค์–ด์™”์ง€๋งŒ Output์ด ๋นˆ ๋ฆฌ์ŠคํŠธ๋กœ ๋‚˜์™€. AI๊ฐ€ ์•ž์— ์ƒต(#)์ด๋‚˜ ํŠน์ˆ˜๋ฌธ์ž๋ฅผ ๋ถ™์—ฌ์„œ ๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™์€๋ฐ, ์ด๊ฑธ ํ•ด๊ฒฐํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๋งŒ๋Šฅ ์ •๊ทœํ‘œํ˜„์‹ ์ฝ”๋“œ๋ฅผ ์งœ์ค˜."

โ‘ข ํ•ด๊ฒฐ๋œ Javascript ์ฝ”๋“œ:

Gemini๊ฐ€ ์งœ์ค€ ์•„๋ž˜ ์ฝ”๋“œ๋กœ ํ—ค๋”(###), ๋ณผ๋“œ์ฒด(**), ๋ฒˆํ˜ธ ์„œ์‹ ๋“ฑ์„ ๋ชจ๋‘ ๋ฌด์‹œํ•˜๊ณ  ๊น”๋”ํ•˜๊ฒŒ ๋‚ด์šฉ๋งŒ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

JavaScript

export const code = async (inputs) => {
  const text = inputs.content;
  // 1. '์‹ค์ฒœ ์ œ์•ˆ' ์„น์…˜ ์ฐพ๊ธฐ (๋„์–ด์“ฐ๊ธฐ, ์ด๋ชจ์ง€ ์œ ๋ฌด ์ƒ๊ด€์—†์ด)
  const splitRegex = /###\s*.*?(์˜ค๋Š˜์˜)?\s*์‹ค์ฒœ\s*์ œ์•ˆ/i;
  const parts = text.split(splitRegex);
  
  if (parts.length < 2) return [];

  // 2. ์ˆซ์ž ๋ชฉ๋ก ์ถ”์ถœ (์•ž์— #, *, ๊ณต๋ฐฑ์ด ์žˆ์–ด๋„ ์ธ์‹ํ•˜๋„๋ก ์ •๊ทœ์‹ ๊ฐœ์„ )
  const targetSection = parts[parts.length - 1];
  const tasks = [];
  const lines = targetSection.split('\n');

  for (const line of lines) {
    const trimmed = line.trim();
    // ํ•ต์‹ฌ ์ •๊ทœ์‹: /^\s*(#+|[*]+)?\s*\d+(\.|-|\))/ 
    if (/^\s*(#+|[*]+)?\s*\d+(\.|-|\))/.test(trimmed)) {
      const cleanTask = trimmed.replace(/^[\s#*]*\d+[\.\-\)]\s*/, '');
      if (cleanTask.length > 0) tasks.push(cleanTask); 
    }
  }
  return tasks;
};

  • ์ž๋™ Task ๋“ฑ๋ก Activepieces flow

  • ๊ตฌ๊ธ€ ์บ˜๋ฆฐ๋”์— ์ž๋™์œผ๋กœ ๋“ฑ๋ก๋œ AI ์ œ์•ˆ

[์ถ”๊ฐ€ ์ˆ˜์ •]
activity logging system2 ํ”Œ๋กœ์šฐ์—์„œ Utility AI_Classify Text ์‚ฌ์šฉ์‹œ AI ํฌ๋ฆฌ๋”ง ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ Hero ์Šคํ„ฐ๋””์žฅ๋‹˜์ด ์•Œ๋ ค์ฃผ์‹  AI API key ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” Generate Content๋กœ ์ˆ˜์ •

๊ตฌ๊ธ€์• ๋„๋ฆฌํ‹ฑ์Šค ๋Œ€์‹œ๋ณด๋“œ ์Šคํฌ๋ฆฐ์ƒท

๐ŸŒˆ ๊ฒฐ๊ณผ์™€ ๋ฐฐ์šด ์ 

๐ŸŽ‰ ๊ฒฐ๊ณผ

  1. ๋งํฌ ์ •์ƒ ์ž‘๋™: ์ด์ œ PC์™€ ๋ชจ๋ฐ”์ผ ์–ด๋””์„œ๋“  ๋ฆฌํฌํŠธ ์›น์•ฑ์ด ๋ฐ”๋กœ ์—ด๋ฆฝ๋‹ˆ๋‹ค.

  2. ๋””์Šค์ฝ”๋“œ ์•Œ๋ฆผ: ๋งค์ผ ์•„์นจ ๋””์Šค์ฝ”๋“œ ์•Œ๋žŒ์„ ํ†ตํ•ด ์ง๊ด€์ ์œผ๋กœ ๋ฆฌํฌํŠธ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. (๋””์Šค์ฝ”๋“œ ์ˆ˜์‹  ํ™”๋ฉด ์บก์ฒ˜ ์ถ”์ฒœ)

  3. ์‹ค์ฒœ๋ ฅ ํ–ฅ์ƒ: ์‹œํŠธ๋ฅผ ์ผœ์ง€ ์•Š์•„๋„, ๊ตฌ๊ธ€ ์บ˜๋ฆฐ๋”(Tasks)์— "์˜ค๋Š˜ ํ•ด์•ผ ํ•  ์ผ 3๊ฐ€์ง€"๊ฐ€ ์ž๋™์œผ๋กœ ๊ฝ‚ํ˜€์žˆ์–ด ๋ฐ”๋กœ ์‹คํ–‰์— ์˜ฎ๊ธธ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. (๊ตฌ๊ธ€ ์บ˜๋ฆฐ๋” Tasks ๋“ฑ๋ก ํ™”๋ฉด ์บก์ฒ˜ ์ถ”์ฒœ)

๐Ÿ’ก ๋ฐฐ์šด ์  & ๊ฟ€ํŒ

  • ๋ฐฐํฌ์—์„œ ๊ถŒํ•œ์˜ ์ค‘์š”์„ฑ: ๋‹ค๋ฅธ ์•ฑ์—์„œ Apps Script์˜ ๋งํฌ๋ฅผ ์—ด๋ ค๋ฉด ๊ถŒํ•œ์„ ๊ตฌ๊ธ€ ๊ณ„์ •์ด ์žˆ๋Š” ๋ชจ๋“  ์‚ฌ์šฉ์ž๋กœ ๋ฐ”๊ฟ”์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  • ์ •๊ทœํ‘œํ˜„์‹์˜ ํž˜: ๋ฐ์ดํ„ฐ ํ˜•์‹์ด ์ผ์ •ํ•˜์ง€ ์•Š์€ AI์˜ ๋‹ต๋ณ€์„ ์ฒ˜๋ฆฌํ•  ๋•Œ๋Š” Activepieces์˜ ๊ธฐ๋ณธ ๊ธฐ๋Šฅ๋ณด๋‹ค Javascript + ์ •๊ทœํ‘œํ˜„์‹์ด ํ›จ์”ฌ ๊ฐ•๋ ฅํ•ฉ๋‹ˆ๋‹ค. Gemini์—๊ฒŒ "ํŒŒ์‹ฑํ•ด์ค˜"๋ผ๊ณ  ํ•˜๋ฉด ์™„๋ฒฝํ•œ ์ฝ”๋“œ๋ฅผ ์งœ์ค๋‹ˆ๋‹ค.

  • ์ž๋™ํ™”์˜ ์—ฐ๊ฒฐ: Apps Script(์ƒ์„ฑ) -> Discord(์•Œ๋ฆผ) -> Activepieces(์‹ค์ฒœ)๋กœ ์ด์–ด์ง€๋Š” ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•˜๋‹ˆ ์ƒ์‚ฐ์„ฑ ์‹œ์Šคํ…œ์ด ์™„์„ฑ๋œ ๋А๋‚Œ์ž…๋‹ˆ๋‹ค.

๐Ÿš€ ์•ž์œผ๋กœ์˜ ๊ณ„ํš

  • ํ˜„์žฌ๋Š” ์•„์ง๊นŒ์ง€ ์ €๋งŒ์˜ ์•„์ด๋””์–ด๊ฐ€ ๋“ค์–ด๊ฐ„ ํšŒ๊ณ  ๋ฆฌํฌํŠธ๊ฐ€ ์•„๋‹ˆ์ง€๋งŒ ์ข€ ๋” ๊ณ ๋ฏผํ•ด ๋ณด๊ณ  ์ข€ ๋” ๊ฐœ์ธํ™”ํ•˜์—ฌ ์—…๊ทธ๋ ˆ์ด๋“œํ•ด๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.


๋„์›€ ๋ฐ›์€ ๊ธ€

  • ์ง€ํ”ผํ„ฐ์Šค19๊ธฐ ํšŒ๊ณ ๋ฆฌํฌํŠธ ์Šคํ„ฐ๋””, Gemini์™€์˜ ๋Œ€ํ™”


1
2๊ฐœ์˜ ๋‹ต๊ธ€

๋‰ด์Šค๋ ˆํ„ฐ ๋ฌด๋ฃŒ ๊ตฌ๋…

๐Ÿ‘‰ ์ด ๊ฒŒ์‹œ๊ธ€๋„ ์ฝ์–ด๋ณด์„ธ์š”