개발자를 위한 노션 자동화 — API와 AI로 워크플로우 혁신하기

Notion자동화API생산성워크플로우AI

노션을 단순 메모장으로만 쓰고 있다면 50%만 활용하는 것입니다. 개발자라면 노션 API와 자동화를 통해 진정한 두 번째 뇌를 만들 수 있습니다.


노션 API 시작하기

Integration 생성

  1. 노션 개발자 페이지 접속
  2. "New integration" 클릭
  3. 이름 설정 및 권한 선택
  4. API 키 복사
# 환경 변수 설정
export NOTION_API_KEY="secret_..."
export NOTION_DATABASE_ID="..."

기본 연결 테스트

import { Client } from '@notionhq/client';

const notion = new Client({ auth: process.env.NOTION_API_KEY });

// 데이터베이스 조회
const response = await notion.databases.query({
  database_id: process.env.NOTION_DATABASE_ID,
});

console.log(response.results);

실전 자동화 1: GitHub 이슈 동기화

GitHub 이슈가 생성되면 자동으로 노션 태스크로 추가합니다.

아키텍처

구현

// github-notion-sync.ts
import { Octokit } from '@octokit/rest';
import { Client } from '@notionhq/client';

const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
const notion = new Client({ auth: process.env.NOTION_API_KEY });

async function syncIssueToNotion(issue: GitHubIssue) {
  // 이미 존재하는지 확인
  const existing = await notion.databases.query({
    database_id: TASK_DB_ID,
    filter: {
      property: 'GitHub Issue',
      url: { equals: issue.html_url },
    },
  });

  if (existing.results.length > 0) {
    // 업데이트
    await notion.pages.update({
      page_id: existing.results[0].id,
      properties: {
        'Status': { select: { name: mapStatus(issue.state) } },
        'Title': { title: [{ text: { content: issue.title } }] },
      },
    });
  } else {
    // 새로 생성
    await notion.pages.create({
      parent: { database_id: TASK_DB_ID },
      properties: {
        'Title': { title: [{ text: { content: issue.title } }] },
        'GitHub Issue': { url: issue.html_url },
        'Status': { select: { name: 'To Do' } },
        'Labels': {
          multi_select: issue.labels.map(l => ({ name: l.name })),
        },
        'Assignee': {
          people: issue.assignees.map(a => ({ id: getUserId(a.login) })),
        },
      },
    });
  }
}

// Webhook 핸들러 (Express)
app.post('/webhook/github', async (req, res) => {
  const { action, issue } = req.body;

  if (['opened', 'edited', 'closed'].includes(action)) {
    await syncIssueToNotion(issue);
  }

  res.status(200).send('OK');
});

실전 자동화 2: 일일 리포트 생성

매일 아침 전날 작업 내용을 자동으로 정리합니다.

// daily-report.ts
import { Client } from '@notionhq/client';
import OpenAI from 'openai';

const notion = new Client({ auth: process.env.NOTION_API_KEY });
const openai = new OpenAI();

async function generateDailyReport() {
  const yesterday = new Date();
  yesterday.setDate(yesterday.getDate() - 1);

  // 어제 완료된 태스크 조회
  const tasks = await notion.databases.query({
    database_id: TASK_DB_ID,
    filter: {
      and: [
        { property: 'Status', select: { equals: 'Done' } },
        { property: 'Completed', date: { equals: yesterday.toISOString().split('T')[0] } },
      ],
    },
  });

  // AI로 요약 생성
  const taskList = tasks.results.map(t => getTitle(t)).join('\n');

  const summary = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      {
        role: 'system',
        content: '당신은 일일 업무 리포트를 작성하는 어시스턴트입니다.',
      },
      {
        role: 'user',
        content: `다음 완료된 작업들을 바탕으로 간결한 일일 리포트를 작성해주세요:\n${taskList}`,
      },
    ],
  });

  // 노션에 리포트 페이지 생성
  await notion.pages.create({
    parent: { database_id: REPORTS_DB_ID },
    properties: {
      'Title': {
        title: [{ text: { content: `일일 리포트 - ${yesterday.toLocaleDateString('ko')}` } }],
      },
      'Date': { date: { start: yesterday.toISOString() } },
    },
    children: [
      {
        type: 'heading_2',
        heading_2: { rich_text: [{ text: { content: '완료 작업' } }] },
      },
      {
        type: 'bulleted_list_item',
        bulleted_list_item: {
          rich_text: tasks.results.map(t => ({
            text: { content: getTitle(t) + '\n' },
          })),
        },
      },
      {
        type: 'heading_2',
        heading_2: { rich_text: [{ text: { content: 'AI 요약' } }] },
      },
      {
        type: 'paragraph',
        paragraph: {
          rich_text: [{ text: { content: summary.choices[0].message.content } }],
        },
      },
    ],
  });
}

// 매일 아침 9시 실행 (cron)
// 0 9 * * * node daily-report.js

실전 자동화 3: 콘텐츠 아이디어 수집

웹에서 발견한 아이디어를 자동으로 노션에 저장합니다.

Chrome Extension

// background.js
chrome.contextMenus.create({
  id: 'save-to-notion',
  title: 'Save to Notion',
  contexts: ['selection', 'link'],
});

chrome.contextMenus.onClicked.addListener(async (info, tab) => {
  const content = info.selectionText || info.linkUrl;

  await fetch('https://your-api.com/notion/quick-save', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      content,
      url: tab.url,
      title: tab.title,
    }),
  });
});

서버 API

// quick-save.ts
app.post('/notion/quick-save', async (req, res) => {
  const { content, url, title } = req.body;

  // AI로 카테고리 분류
  const category = await classifyContent(content);

  await notion.pages.create({
    parent: { database_id: IDEAS_DB_ID },
    properties: {
      'Title': { title: [{ text: { content: title || content.slice(0, 50) } }] },
      'Source URL': { url },
      'Category': { select: { name: category } },
      'Status': { select: { name: 'Inbox' } },
    },
    children: [
      {
        type: 'quote',
        quote: { rich_text: [{ text: { content } }] },
      },
    ],
  });

  res.json({ success: true });
});

실전 자동화 4: 슬랙 알림 연동

노션 데이터베이스 변경 시 슬랙으로 알림을 보냅니다.

// notion-slack-notify.ts
import { WebClient } from '@slack/web-api';

const slack = new WebClient(process.env.SLACK_TOKEN);

async function checkAndNotify() {
  // 최근 10분 내 변경된 항목
  const recentChanges = await notion.databases.query({
    database_id: TASK_DB_ID,
    filter: {
      property: 'Last edited time',
      date: {
        after: new Date(Date.now() - 10 * 60 * 1000).toISOString(),
      },
    },
  });

  for (const page of recentChanges.results) {
    const status = getStatus(page);
    const title = getTitle(page);
    const assignee = getAssignee(page);

    if (status === 'Done') {
      await slack.chat.postMessage({
        channel: '#dev-updates',
        text: `✅ *${title}* 완료됨 (@${assignee})`,
        unfurl_links: false,
      });
    }

    if (status === 'Blocked') {
      await slack.chat.postMessage({
        channel: '#dev-alerts',
        text: `🚨 *${title}* 블로커 발생! (@${assignee})`,
        unfurl_links: false,
      });
    }
  }
}

// 10분마다 실행
setInterval(checkAndNotify, 10 * 60 * 1000);

노코드 대안: Make (Integromat)

코드 없이 자동화하려면 Make를 활용할 수 있습니다.

가능한 자동화

  • Gmail → Notion: 중요 이메일 자동 저장
  • Calendar → Notion: 미팅 일정 동기화
  • Notion → Slack: 상태 변경 알림
  • RSS → Notion: 블로그 구독 자동 저장

설정 예시

  1. Make 계정 생성
  2. Notion 모듈 추가 → Integration 연결
  3. 트리거 설정 (스케줄 또는 웹훅)
  4. 액션 정의

보안 고려사항

// API 키 보호
// .env 파일 사용, 절대 커밋하지 않음
NOTION_API_KEY=secret_...

// 접근 권한 최소화
// Integration에 필요한 페이지만 공유

// 웹훅 검증
function verifyWebhook(req: Request): boolean {
  const signature = req.headers['x-signature'];
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(JSON.stringify(req.body))
    .digest('hex');
  return signature === expected;
}

마치며

노션 자동화를 통해 얻을 수 있는 것:

  • 시간 절약: 반복 작업 자동화
  • 정보 중앙화: 여러 소스의 정보를 한 곳에
  • 팀 협업 강화: 실시간 동기화 및 알림
  • 데이터 기반 의사결정: 자동 리포트 생성

시작은 작게, 하나의 자동화부터 구축해보세요. 점점 확장하다 보면 어느새 노션이 당신의 두 번째 뇌가 되어 있을 것입니다.

궁금한 점이 있으신가요?

협업·의뢰는 아래로, 가벼운 소통은 인스타그램 @bluefox._.hi도 환영이에요.