twitter 북마크 요약본을 Notion에 매일 정리하기(feat.노코드를 가장한 코드)


요약

  1. twitter 북마크 요약본을 Notion에 매일 정리하는 기능을 노코드를 빙자한 로우 코드로 만들어보았습니다.

  2. zapier, air-table, twitter api, nest js(정말 간단)을 사용했습니다.

  3. 제작 방법을 공유드려요.

  • 혹시 생산성을 위해서 노코드로 제작하고 싶으신 거 있으시면, 공유부탁드려요. 한번 제작해보겠습니다.


서론: 만들게 된 계기

chat gpters에 만들게 된 계기:

안녕하세요. chatgpters 카톡방과 chatgpters 그룹에서 여러 게시글들을 보고 chat gpt를 통한 가능성을 엿보고 있었던 대학생입니다. /

여러 글들을 통해서 Chat gpt와 zapier 여러 툴들의 조합으로 무한한 영역에서 자동화가 가능하다는 것을 알았습니다. 이 때문에 저에게 꼭 필요한 자동화를 시도해보았고, 여러분들께 공유드리고자 합니다.

트위터 북마크 요약본을 notion에 정리하는 기능을 만들게 된 계기:

트위터에는 세계 최고의 똑똑이들이 많이 있습니다.

일론 머스크를 시작으로, open ai의 ceo, 노션의 CEO 등등 위대한 사람들이 많은데요.

생성 ai 시장에 관심을 가지는 만큼 트위터에서 많은 사람들의 이야기들을 보면서 인사이트를 얻고 있습니다.

(생성 ai 인사이트를 위해 jerry liu, jason 등등 추천드립니다. 추천해주실 인물들있으면 말씀해주세요.)

트위터의 북마크를 정리해주는 서비스들을 애용하고 있습니다. Sonic(전: x base).

트위터의 북마크는 굉장히 불편한데요. 시간순으로만 정리가 되어있고, 카테고리별로 등등 정리가 되어있지 않습니다. sonic 등을 쓰면, 카테코리 별로도 정리가 가능하고, 이미지별, 태그 별로 검색이 가능합니다.

(강추)

하지만, 저에게 필요한 것은 제가 한 북마크들을 notion으로 정리해주는 기능이었습니다.

저는 유용한 내용의 트윗을 북마크를 해놓고, 잘 확인하지 않습니다. 북마크는 많이 하지만, 그 내용들을 비서처럼 요약해주고, 제가 쓰는 서비스(Notion)으로 정리해주면 좋겠다는 생각이 들었어요.

저는 북마크하기만 하면, notion에 차곡차곡 정리되서 나중에 한번에 볼 수 있게 말입니다.

chatgpters에서 여러 게시글들을 보니, 노코드 툴을 사용해서 굉장히 많이 만들고 계시더라고요.

그래서 이번 기회에 한번 제작해보았습니다. 코드가 일부 들어가는 부분에 대해서는 git repository에 모든 코드를 공유해드렸으니, 참고 바랍니다.




본론: zapier 세팅을 해보자.

우선 zapier에 가입합니다. zapier는 이번에 써보니 정말 미친 툴이라는 것을 알게 되었습니다. 거의 모든 것을 자동화 할 수 있습니다.




zapier에 가입하고, 새로운 zap을 생성했습니다.



처음에 아래와 같은 화면이 뜨는데요. 간단하게 설명하면, Trigger(트리거)는 특정 동작이 언제 실행될 수 있는지를 결정하는 이벤트를 묻는 것이고, action(액션)은 trigger 후에 일어날 동작들을 이야기합니다.


제가 지금 만들고자하는 자동화의 영역에서 trigger는 twitter 북마크가 추가되는 순간 혹은 특정 시간대가 될 수 있겠습니다.(예: 매일 오전 9시마다)


그런데 왠걸 zapier에 트위터가 없습니다. zapier는 트위터를 지원하지 않았습니다. ㅠㅜㅠㅜ

(설마해서 최근에 업데이트된 X로도 쳐봤는데, 없네요)


그렇다고 여기서 포기할 순 없습니다. GPT에게 물어보니 Webhook이 있다고 하군요.



zapier 프리미엄 버전에는 webhook을 지원합니다.

자체적인 코드를 작성하고, 이 웹훅을 통해서 특정 동작이 발생했을 때, zapier의 트리거가 발생하도록 해야겠습니다.





webhook은 zapier premium 버전부터 가능하기 때문에 결제를 했습니다.


이제 api를 만들어 보겠습니다.


본론: 트위터 api 사용하기


웹훅을 통해서 특정 시간대에 북마크를 가져오고, airtable의 db와 비교해서 다른 것이 있으면, zaiper의 webhook으로 보내는 전략을 취하려고 합니다.


우선 그럼 북마크를 가져올 수 있도록 트위터 api에 접근해봅시다.

이것도 결제가 필요합니다. 결제를 해서 app을 만들고, client_id와 client_secret를 준비합니다.

client_id와 client_secret을 통해서 특정 유저(제 아이디)의 access_token을 받습니다.

(간단하게 이야기하면, app은 북마크나, user에 접근할 수 있게 해주는 기능이고, 이 기능을 사용하여 특정 유저의 데이터에 접근할 수 있도록 할 수 있도록 app과 연결시켜서 access_token을 얻습니다.)



트위터는 본인들의 api를 잘 사용할 수 있도록 post맨을 제공해주더라고요.


이전에 발급받은 access_token과 twitter 저의 닉네임을 이용해서 user id를 가져왔습니다.



user id가 있어야지 book마크에 접근할 수 있는데요. 아래와 같이 저의 북마크에 접근해봅니다.

제가 북마크한 내용들이 나오고 있어요. 이렇게 한 것들을 백앤드 코드로 만들고, 에어 테이블에 저장해봐야겠습니다.



본론: 백앤드 코드 만들기



아래와 같이 만들었습니다.(역시 gpt 짱)

이 코드를 이제 조금 변경해서 북마크를 주기적으로 불러올 때, airtable에 있는 북마크와 비교해서 북마크가 있으면, 그냥 그대로 두고, 북마크가 새로운 것이면, zapier webhook api로 통신을 보내는 코드를 작성했습니다.


import { Injectable, Logger } from '@nestjs/common';
import { Cron, Interval } from '@nestjs/schedule';
import axios from 'axios';

@Injectable()
export class AppService {
  private readonly logger = new Logger(AppService.name);

  @Cron('0 0 * * *') // 매시간 정각에 실행
  async handleCron() {
    this.logger.debug('Cron job started');

    try {
      const airTableBookMarks = await this.fetchExistingBookmarksFromAirtable();
      const twitterBookMarks = await this.fetchBookmarks();

      const newBookmarks = this.findNewBookmarks(
        twitterBookMarks,
        airTableBookMarks,
      );
      if (newBookmarks.length > 0) {
        await this.createNewBookmarks(newBookmarks);
        await this.sendToZapier(newBookmarks);
      }
    } catch (error) {
      this.logger.error('API 요청 중 오류 발생:', error);
    }
  }

  private async fetchBookmarks(): Promise<any[]> {
    const header = {
      Authorization: `Bearer ${process.env.TWITTER_BEARER_TOKEN}`,
    };
    // 트위터에서 북마크를 가져오는 코드
    const bookmarks = await axios.get(
      `https://api.twitter.com/2/users/${process.env.TWITTER_USER_ID}/bookmarks`,
      {
        headers: header,
      },
    );

    return bookmarks.data.data.map((bookmark) => {
      return {
        id: bookmark.id,
        text: bookmark.text,
      };
    });
  }

  private async fetchExistingBookmarksFromAirtable(): Promise<any[]> {
    // Airtable에서 기존 북마크를 불러오는 코드
    const bookmarks = await axios.get(`${process.env.AIRTABLE_URL}`, {
      headers: { Authorization: `Bearer ${process.env.AIRTABLE_TOKEN}` },
    });

    return bookmarks.data.records.map((bookmark) => {
      return {
        id: bookmark.fields.twit_id,
        text: bookmark.fields.text,
      };
    });
  }

  private findNewBookmarks(bookmarks: any[], existingBookmarks: any[]): any[] {
    // 에어테이블과 트위터 북마크를 비교하여 새로운 북마크를 찾는 코드
    console.log(bookmarks, 'bookmarks');
    console.log(existingBookmarks, 'existingBookmarks');
    const result = bookmarks.filter(
      (bookmark) =>
        !existingBookmarks.map((item) => item.id).includes(bookmark.id),
    );
    console.log(result, 'result');
    return result;
  }

  private async createNewBookmarks(newBookMarks: any): Promise<any[]> {
    const records = newBookMarks.map((bookmark) => {
      return {
        fields: {
          twit_id: bookmark.id,
          text: bookmark.text,
        },
      };
    });
   //bookmarks를 생성하는 코드
    const bookmarks = await axios.post(
      `${process.env.AIRTABLE_URL}`,
      {
        records: records,
      },
      {
        headers: { Authorization: `Bearer ${process.env.AIRTABLE_TOKEN}` },
      },
    );

    return bookmarks.data;
  }

  private async sendToZapier(newBookmarks: any[]): Promise<void> {
    // Zapier Webhook API로 통신을 보내는 코드 
    let text = newBookmarks.flatMap((bookmark) => bookmark.text).join('');

    text = text.replace(/\+|\\n/g, '');

    await axios.post(`${process.env.ZAPIER_WEBHOOK_URL}`, {
      data: {
        text: text,
      },
    });
  }

  getHello(): string {
    return 'Hello World!';
  }
}

코드는 아래의 깃허브에 모두 공유했습니다.


챗 gpt가 설명해준대로 코드를 메인 AppService 내에서 다 표현을 했습니다.

여기에는 트위터 북마크를 가져오는 코드, airtable에 저장되어있는 북마크를 가져오는 코드, 둘을 비교하여 airtable에 저장해주는 코드, zapier 웹 훅 url에 보내는 코드가 모두 작성되어있습니다. 그렇다면, 이를 기반으로 다시 zapier를 설정해보죠.



본론: 제피어로 연결시키기



제피어 구조는 위와 같습니다.

아까 코드에서 작성했던 것과 같이 webhook을 걸고, webhook이 발생하는 상황에 트리거를 발생시켜서

chatgpt로 받은 데이터를 요약합니다. 그리고, 요약한 데이터를 notion에 보내여 설정합니다.



chat gpt 같은 경우에 제피어로 연결시키려면 open api key가 필요하고,

notion같은 경우에는 oauth를 통해 notion에 로그인한 후 특정 페이지를 선택해주면 됩니다.


notion같은 경우에는 oauth를 통해 notion에 로그인한 후 특정 페이지를 선택해주면 됩니다.


미리 설정해놓은 데이터 베이스를 연결 시켜주면, 끝!!

그렇다면 실제 결과를 볼까요?

(실제 결과를 자동화해놓을려면, 서버같은 경우에는 자동으로 돌아갈 수 있도록 배포를 해야하지만, 현재는 테스트이기 때문에 그냥 진행했습니다.)









마무리


zapier는 굉장한 툴이었지만, zapier premium 버전을 직접 결제해서 사용해야 한다는 점이 불편했습니다.

twitter api도 결제하는 것은 마찬가지고요.

또한 일부 low 코드도 들어가서 개발자가 아니신 분들에게는 더 혼란스러우실 수 있을 것 같습니다.



제가 만들어놓은 이런 기능을 다른 사람들도 쉽게 사용할 수 있게 만들고 공유할 수는 없을까요?

만들어놓은 zap을 공유하기는 했지만, 제피어에는 없는 twitter oauth나 코드들이 들어가서 zap을 공유하는 것만으로는 힘들 것 같습니다.

제가 만들어놓은 플로우를 여러분들도 사용하시면 좋을 것 같은데, 사용하시려면 이 과정을 다시 구축하는 수 밖에 없습니다.



기회가 되면, 다음번 게시글에서는 제가 만든 기능을 여러분들도 쉽게 사용할 수 있는 페이지를 제작해보고, 여러분들께 공유드리겠습니다. 모두 사용하실 수 있는 웹 페이지의 형태가 될 것 같아요. 많은 기대 부탁드립니다! 감사합니다.


(ps. 지식 큐레이팅과 업무 생산성 부분에 있어서 노코드로 제작하고 싶으신 거 있으시면, 댓글 부탁드려요!

제작해보고, 공유드리겠습니다. )





9
2개의 답글

👉 이 게시글도 읽어보세요