이미지 로딩 중...
AI Generated
2025. 11. 5. · 9 Views
Notion 실무 활용 완벽 가이드
실무에서 Notion을 더욱 효율적으로 활용하는 방법을 알아봅니다. 데이터베이스 활용, 자동화, 팀 협업 등 중급 개발자를 위한 실전 노하우를 담았습니다.
목차
- Notion API를 활용한 데이터 자동화
- 데이터베이스 Relations으로 정보 연결하기
- Formula로 동적 계산 자동화하기
- Template 버튼으로 작업 템플릿 자동 생성
- Synced Blocks로 콘텐츠 동기화하기
- 고급 필터로 동적 뷰 만들기
- Webhook과 통합하여 실시간 알림 구현
- 데이터베이스 Rollup으로 집계 데이터 자동 계산
1. Notion API를 활용한 데이터 자동화
시작하며
여러분이 매일 프로젝트 진행 상황을 Notion에 수동으로 업데이트하느라 시간을 낭비한 적 있나요? 매번 GitHub 이슈를 확인하고, JIRA 티켓을 보고, 그 내용을 Notion 테이블에 일일이 입력하는 작업은 정말 지루하고 실수하기 쉽습니다.
이런 반복 작업은 개발자의 생산성을 크게 떨어뜨립니다. 특히 여러 도구를 사용하는 팀에서는 데이터 동기화가 항상 문제가 되죠.
한 곳에서 업데이트한 내용이 다른 곳에 반영되지 않아 혼란이 생기기도 합니다. 바로 이럴 때 필요한 것이 Notion API를 활용한 데이터 자동화입니다.
한 번만 설정해두면 외부 시스템의 데이터가 자동으로 Notion에 동기화되어 여러분의 소중한 시간을 아껴줍니다.
개요
간단히 말해서, Notion API는 외부 애플리케이션에서 Notion의 페이지와 데이터베이스를 프로그래밍 방식으로 접근하고 조작할 수 있게 해주는 RESTful API입니다. 이 API를 사용하면 GitHub 커밋 로그를 자동으로 Notion 데이터베이스에 기록하거나, 슬랙 메시지를 Notion 페이지로 저장하거나, CI/CD 빌드 결과를 자동으로 업데이트할 수 있습니다.
예를 들어, 새로운 버그 리포트가 제출되면 자동으로 Notion의 버그 트래킹 데이터베이스에 항목을 생성하는 것이 가능합니다. 기존에는 모든 정보를 수동으로 복사-붙여넣기 했다면, 이제는 스크립트나 웹훅을 통해 완전히 자동화할 수 있습니다.
Notion API의 핵심 특징은 첫째, RESTful 구조로 직관적이며, 둘째, 페이지와 데이터베이스 모두 조작 가능하고, 셋째, 실시간 업데이트를 지원한다는 점입니다. 이러한 특징들이 팀의 워크플로우를 크게 개선하고 데이터 일관성을 유지하는 데 중요한 역할을 합니다.
코드 예제
const { Client } = require('@notionhq/client');
// Notion 클라이언트 초기화
const notion = new Client({ auth: process.env.NOTION_API_KEY });
async function addTaskToDatabase(databaseId, taskName, status) {
// 데이터베이스에 새로운 페이지(항목) 생성
const response = await notion.pages.create({
parent: { database_id: databaseId },
properties: {
// 제목 속성 설정
Name: { title: [{ text: { content: taskName } }] },
// 상태 속성 설정
Status: { select: { name: status } },
// 생성 날짜 자동 기록
Created: { date: { start: new Date().toISOString() } }
}
});
return response;
}
설명
이것이 하는 일: 이 코드는 Notion 데이터베이스에 프로그래밍 방식으로 새로운 작업 항목을 추가하는 완전한 워크플로우를 보여줍니다. 첫 번째로, @notionhq/client 패키지를 사용하여 Notion API 클라이언트를 초기화합니다.
여기서 환경 변수로 API 키를 전달하는데, 이렇게 하는 이유는 보안을 위해 민감한 정보를 코드에 직접 하드코딩하지 않기 위함입니다. API 키는 Notion의 Integrations 페이지에서 생성할 수 있으며, 이 키를 통해 여러분의 워크스페이스에 접근 권한을 얻게 됩니다.
그 다음으로, addTaskToDatabase 함수가 실행되면서 실제로 데이터베이스에 항목을 생성합니다. notion.pages.create() 메서드를 호출할 때 두 가지 중요한 정보를 전달합니다.
parent 객체는 어느 데이터베이스에 항목을 추가할지 지정하고, properties 객체는 각 컬럼에 어떤 값을 넣을지 정의합니다. Notion의 데이터 타입(title, select, date 등)에 맞게 데이터를 구조화하는 것이 핵심입니다.
마지막으로, API 호출이 완료되면 생성된 페이지의 전체 정보가 담긴 응답 객체를 반환합니다. 이 응답에는 페이지 ID, URL, 생성 시간 등 유용한 메타데이터가 포함되어 있어 후속 작업에 활용할 수 있습니다.
여러분이 이 코드를 사용하면 GitHub Actions, AWS Lambda, 또는 어떤 자동화 스크립트에서든 Notion을 업데이트할 수 있습니다. 예를 들어 CI/CD 파이프라인에서 배포가 완료되면 자동으로 Notion의 릴리즈 노트에 항목을 추가하거나, 크론 잡으로 매일 아침 일일 리포트를 생성하는 등의 활용이 가능합니다.
또한 에러 처리를 추가하면 API 호출 실패 시 재시도 로직을 구현할 수 있고, 배치 작업을 통해 한 번에 여러 항목을 효율적으로 업데이트할 수도 있습니다.
실전 팁
💡 API 키는 반드시 환경 변수나 시크릿 매니저에 저장하세요. 코드에 직접 포함하면 GitHub에 푸시했을 때 보안 위험이 발생합니다.
💡 Notion API는 rate limit이 있습니다(초당 3개 요청). 대량의 데이터를 처리할 때는 요청 사이에 적절한 딜레이를 추가하거나 배치 처리를 고려하세요.
💡 데이터베이스의 속성(properties) 구조를 먼저 확인하세요. API로 데이터를 추가할 때 존재하지 않는 속성명을 사용하면 에러가 발생합니다.
💡 Integration을 생성한 후에는 반드시 해당 데이터베이스나 페이지를 Integration과 공유해야 접근할 수 있습니다. 'Share' 버튼에서 Integration을 추가하는 것을 잊지 마세요.
💡 에러 응답을 항상 처리하세요. try-catch 블록으로 감싸고, API 에러 코드를 확인하여 적절한 대응(재시도, 로깅, 알림 등)을 구현하면 안정적인 자동화를 만들 수 있습니다.
2. 데이터베이스 Relations으로 정보 연결하기
시작하며
여러분이 Notion에서 프로젝트 관리를 할 때, 작업(Task)과 담당자(Person)를 따로 관리하면서 둘 사이의 관계를 명확하게 표현하지 못해 답답했던 경험이 있나요? 각 작업에 담당자 이름을 텍스트로 입력하면 나중에 특정 개발자가 맡은 모든 작업을 한눈에 보기가 어렵습니다.
이런 문제는 데이터 정규화가 되지 않아 발생합니다. 같은 정보를 여러 곳에 중복 입력하면 일관성이 깨지고, 한 곳을 수정할 때 다른 곳도 모두 찾아서 고쳐야 하는 불편함이 생깁니다.
또한 데이터 간의 관계를 활용한 고급 분석이나 자동화가 불가능해집니다. 바로 이럴 때 필요한 것이 Notion의 Relation 속성입니다.
데이터베이스 간의 관계를 명확히 정의하여 정보를 체계적으로 관리하고, 양방향 참조를 통해 데이터의 일관성을 유지할 수 있습니다.
개요
간단히 말해서, Relation은 하나의 데이터베이스에 있는 항목을 다른 데이터베이스의 항목과 연결하는 속성 타입으로, 관계형 데이터베이스의 외래 키(Foreign Key)와 유사한 개념입니다. 이 기능을 사용하면 작업 데이터베이스를 프로젝트 데이터베이스와 연결하거나, 회의록을 참석자 데이터베이스와 연결할 수 있습니다.
예를 들어, 버그 리포트 데이터베이스를 기능 데이터베이스와 연결하면 특정 기능과 관련된 모든 버그를 즉시 확인할 수 있어 매우 유용합니다. 기존에는 관련 정보를 텍스트나 링크로 일일이 입력했다면, 이제는 Relation으로 한 번 연결하면 자동으로 양방향 참조가 생성되고 Rollup을 통해 관련 데이터를 집계할 수 있습니다.
Relation의 핵심 특징은 첫째, 양방향 참조가 자동으로 생성되어 데이터 일관성이 보장되고, 둘째, Rollup과 결합하여 관련 데이터를 집계·계산할 수 있으며, 셋째, 복잡한 데이터 구조를 직관적으로 시각화할 수 있다는 점입니다. 이러한 특징들이 대규모 프로젝트에서 정보를 체계적으로 관리하고 인사이트를 도출하는 데 필수적입니다.
코드 예제
const { Client } = require('@notionhq/client');
const notion = new Client({ auth: process.env.NOTION_API_KEY });
async function linkTaskToProject(taskPageId, projectPageId) {
// 작업 페이지를 프로젝트와 연결
const response = await notion.pages.update({
page_id: taskPageId,
properties: {
// Relation 속성을 통해 프로젝트 연결
Project: {
relation: [{ id: projectPageId }]
}
}
});
// 연결 후 Rollup으로 프로젝트의 총 작업 수 계산 가능
// Rollup 속성은 UI에서 설정: Project relation -> Count all
return response;
}
설명
이것이 하는 일: 이 코드는 작업(Task) 페이지를 프로젝트(Project) 페이지와 프로그래밍 방식으로 연결하여 두 데이터베이스 간의 관계를 설정합니다. 첫 번째로, notion.pages.update() 메서드를 사용하여 기존 작업 페이지의 속성을 업데이트합니다.
여기서 중요한 점은 page_id를 통해 특정 페이지를 지정하고, properties 객체에서 Relation 타입의 속성을 수정한다는 것입니다. Relation은 배열 형태로 여러 항목을 연결할 수 있기 때문에 [{ id: projectPageId }]처럼 배열로 감싸서 전달합니다.
그 다음으로, 이 API 호출이 실행되면 Notion의 데이터베이스 구조상 양방향 참조가 자동으로 업데이트됩니다. 즉, 작업 페이지에서 프로젝트를 볼 수 있을 뿐만 아니라, 프로젝트 페이지에서도 이 작업이 자동으로 나타나게 됩니다.
이는 수동으로 양쪽을 다 업데이트할 필요가 없다는 뜻이며, 데이터 불일치 문제를 원천적으로 방지합니다. 마지막으로, Relation이 설정되면 Rollup 속성을 통해 강력한 데이터 집계가 가능해집니다.
주석에서 언급했듯이 프로젝트 데이터베이스에서 "연결된 작업의 개수", "완료된 작업의 비율", "작업들의 예상 시간 합계" 같은 계산을 자동으로 수행할 수 있습니다. Rollup은 Notion UI에서 설정하는 것이 더 직관적이지만, API를 통해서도 접근 가능합니다.
여러분이 이 코드를 사용하면 프로젝트 관리 자동화 시스템을 구축할 수 있습니다. 예를 들어 JIRA에서 이슈가 생성되면 자동으로 Notion 작업을 만들고 해당 프로젝트에 연결하거나, GitHub PR이 머지되면 관련 작업의 상태를 자동으로 업데이트하는 워크플로우를 만들 수 있습니다.
또한 여러 프로젝트에 걸쳐 있는 작업을 한 번에 관리하거나, 특정 팀원이 여러 프로젝트에서 맡은 모든 작업을 대시보드로 시각화하는 것도 가능합니다.
실전 팁
💡 Relation을 생성할 때 "Show on [대상 데이터베이스]" 옵션을 활성화하면 양방향 참조가 자동으로 설정됩니다. API로 작업할 때도 이 설정이 되어 있는지 확인하세요.
💡 한 작업을 여러 프로젝트에 연결하려면 relation 배열에 여러 개의 id 객체를 추가하면 됩니다: [{ id: project1 }, { id: project2 }]
💡 Rollup을 활용하면 관련된 항목들의 합계, 평균, 최대값, 최소값 등을 자동 계산할 수 있습니다. 프로젝트의 총 예상 시간이나 완료율을 실시간으로 추적할 때 유용합니다.
💡 Relation을 제거하려면 빈 배열을 전달하세요: { relation: [] }. 이렇게 하면 모든 연결이 해제됩니다.
💡 복잡한 데이터 구조를 설계할 때는 먼저 종이에 ERD(Entity-Relationship Diagram)를 그려보세요. 어떤 데이터베이스끼리 어떤 관계를 가져야 하는지 미리 계획하면 나중에 구조를 변경하는 수고를 줄일 수 있습니다.
3. Formula로 동적 계산 자동화하기
시작하며
여러분이 프로젝트의 진행률을 계산하거나 마감일까지 남은 일수를 표시하려고 할 때, 매번 수동으로 계산해서 입력하는 것이 얼마나 번거로운지 아시나요? 완료된 작업이 추가될 때마다 진행률을 다시 계산해서 업데이트해야 하고, 날짜가 바뀔 때마다 남은 일수를 고쳐야 합니다.
이런 수동 계산은 실수가 발생하기 쉽고, 데이터가 실시간으로 변경될 때 즉시 반영되지 않아 정보의 정확성이 떨어집니다. 특히 여러 사람이 동시에 작업하는 데이터베이스에서는 누군가 업데이트를 깜빡하면 잘못된 정보를 기반으로 의사결정을 하게 될 위험이 있습니다.
바로 이럴 때 필요한 것이 Notion의 Formula 속성입니다. 한 번 수식을 설정해두면 다른 속성들이 변경될 때마다 자동으로 재계산되어 항상 최신의 정확한 값을 보여줍니다.
개요
간단히 말해서, Formula는 다른 속성들의 값을 기반으로 자동으로 계산되는 동적 속성으로, 엑셀의 수식과 유사하지만 Notion 데이터베이스의 각 행마다 독립적으로 작동합니다. 이 기능을 사용하면 마감일까지 남은 일수를 자동 계산하거나, 시작일과 종료일로부터 작업 기간을 산출하거나, 여러 조건에 따라 우선순위를 자동으로 부여할 수 있습니다.
예를 들어, 예산 데이터베이스에서 계획 대비 실제 지출 비율을 자동으로 표시하거나, 작업 상태가 "완료"이고 마감일을 넘긴 경우 자동으로 플래그를 표시하는 것이 가능합니다. 기존에는 계산된 값을 수동으로 입력하고 변경 사항이 있을 때마다 일일이 업데이트했다면, 이제는 Formula를 한 번 설정하면 영구적으로 자동 계산되어 유지보수 부담이 사라집니다.
Formula의 핵심 특징은 첫째, 실시간으로 자동 업데이트되어 항상 정확한 값을 보장하고, 둘째, 조건문, 날짜 연산, 문자열 조작 등 다양한 함수를 지원하며, 셋째, 다른 Formula를 참조하여 복잡한 계산을 단계적으로 구현할 수 있다는 점입니다. 이러한 특징들이 데이터 중심 의사결정을 지원하고 워크플로우를 자동화하는 데 핵심적인 역할을 합니다.
코드 예제
// Notion Formula는 UI에서 설정하지만,
// API로 읽거나 설정할 수 있습니다
// 예시 1: 마감일까지 남은 일수 계산
// dateBetween(prop("DueDate"), now(), "days")
// 예시 2: 진행률 계산 (완료된 작업/전체 작업)
// prop("CompletedTasks") / prop("TotalTasks") * 100
// 예시 3: 우선순위 자동 부여
// if(dateBetween(prop("DueDate"), now(), "days") < 3, "🔴 긴급",
// if(dateBetween(prop("DueDate"), now(), "days") < 7, "🟡 중요", "🟢 보통"))
// API로 Formula 속성 읽기
const page = await notion.pages.retrieve({ page_id: pageId });
const daysLeft = page.properties.DaysLeft.formula.number;
console.log(`남은 일수: ${daysLeft}일`);
설명
이것이 하는 일: 이 코드는 Notion Formula의 다양한 활용 예시와 API를 통해 계산된 값을 읽어오는 방법을 보여줍니다. 첫 번째로, 세 가지 실용적인 Formula 예시를 소개합니다.
dateBetween() 함수는 두 날짜 사이의 차이를 계산하는데, 마감일(prop("DueDate"))과 현재 시점(now()) 사이의 일수를 계산하여 얼마나 시간이 남았는지 자동으로 표시합니다. 진행률 계산은 간단한 나눗셈과 곱셈으로 백분율을 산출하며, 이 값은 완료된 작업이나 전체 작업 수가 변경될 때마다 즉시 업데이트됩니다.
그 다음으로, 조건문을 활용한 우선순위 자동 부여 예시를 볼 수 있습니다. if() 함수를 중첩하여 마감일이 3일 미만으로 남았으면 "🔴 긴급", 7일 미만이면 "🟡 중요", 그 외에는 "🟢 보통"으로 자동 분류합니다.
이렇게 하면 수동으로 우선순위를 지정하지 않아도 마감일에 따라 시각적으로 긴급한 작업을 즉시 파악할 수 있습니다. 마지막으로, API를 통해 Formula로 계산된 값을 읽어오는 방법을 보여줍니다.
notion.pages.retrieve()로 페이지 정보를 가져온 후, properties.DaysLeft.formula.number처럼 접근하면 계산된 숫자 값을 얻을 수 있습니다. Formula의 반환 타입에 따라 .number, .string, .boolean, .date 등 적절한 속성을 사용해야 합니다.
여러분이 이 코드를 사용하면 대시보드에서 실시간 메트릭을 자동으로 업데이트하거나, 특정 조건을 만족하는 항목을 자동으로 필터링할 수 있습니다. 예를 들어 마감일이 임박한 작업들을 자동으로 슬랙에 알림 보내는 스크립트를 만들거나, 월간 리포트를 생성할 때 Formula로 계산된 KPI를 추출하여 차트로 시각화하는 것이 가능합니다.
또한 복잡한 비즈니스 로직(예: 가중 점수 계산, 할인율 적용, SLA 준수 여부 판단)을 Formula로 구현하면 코드 없이도 강력한 자동화를 구축할 수 있습니다.
실전 팁
💡 Formula에서 빈 값을 참조하면 에러가 발생할 수 있으니 if(empty(prop("Field")), 0, 계산식) 같은 방식으로 빈 값을 처리하세요.
💡 날짜 계산 시 now()는 매번 현재 시각을 반환하므로, 고정된 시점을 기준으로 계산하려면 별도의 날짜 속성을 생성하는 것이 좋습니다.
💡 복잡한 Formula는 여러 단계로 나누어 중간 계산 결과를 별도 Formula 속성으로 만들면 디버깅이 쉬워지고 재사용성도 높아집니다.
💡 format() 함수로 숫자를 문자열로 변환하여 단위를 붙일 수 있습니다: format(prop("Price")) + "원" 이렇게 하면 가독성이 좋아집니다.
💡 Rollup과 Formula를 결합하면 더욱 강력합니다. 예를 들어 Rollup으로 관련 작업들의 예상 시간을 합산한 후, Formula로 그 값이 40시간을 초과하면 경고를 표시하는 식으로 활용할 수 있습니다.
4. Template 버튼으로 작업 템플릿 자동 생성
시작하며
여러분이 새로운 프로젝트를 시작할 때마다 같은 구조의 페이지를 반복해서 만들고, 체크리스트를 일일이 작성하고, 관련 데이터베이스 항목들을 수동으로 연결하느라 시간을 낭비한 적 있나요? 매번 "이번에는 뭘 빠뜨리지 않았나?" 걱정하면서 이전 프로젝트를 참고해 복사-붙여넣기 하는 것은 정말 비효율적입니다.
이런 반복 작업은 표준화된 프로세스를 따르기 어렵게 만들고, 사람마다 다른 방식으로 페이지를 만들어 일관성이 떨어집니다. 또한 필수 단계를 빠뜨리거나 잘못된 구조로 시작하면 나중에 수정하기가 더 번거로워집니다.
바로 이럴 때 필요한 것이 Notion의 Template 버튼입니다. 미리 정의된 구조의 페이지나 데이터베이스 항목을 버튼 클릭 한 번으로 생성하여, 팀 전체가 일관된 형식을 유지하면서도 시간을 크게 절약할 수 있습니다.
개요
간단히 말해서, Template 버튼은 사전에 정의한 페이지 구조, 속성 값, 하위 블록들을 자동으로 생성하는 버튼으로, 반복적인 작업 흐름을 원클릭으로 표준화할 수 있게 해줍니다. 이 기능을 사용하면 "새 스프린트 시작" 버튼을 만들어 회고 페이지, 스프린트 목표, 작업 항목 템플릿을 한 번에 생성하거나, "버그 리포트" 템플릿으로 재현 단계, 환경 정보, 스크린샷 섹션이 포함된 표준화된 리포트를 즉시 만들 수 있습니다.
예를 들어, 새로운 팀원이 입사했을 때 "온보딩 체크리스트" 버튼 하나로 첫 주/첫 달 동안 해야 할 모든 작업과 읽어야 할 문서 링크를 자동으로 생성하는 것이 가능합니다. 기존에는 예전 페이지를 복제하고 내용을 일일이 지우고 수정했다면, 이제는 Template 버튼으로 깨끗한 템플릿을 매번 새로 생성할 수 있습니다.
Template 버튼의 핵심 특징은 첫째, 데이터베이스 템플릿과 일반 페이지 템플릿을 모두 지원하고, 둘째, 생성된 페이지에 자동으로 속성 값(태그, 날짜, 담당자 등)을 설정할 수 있으며, 셋째, 하위 블록과 체크리스트까지 포함한 복잡한 구조를 한 번에 생성할 수 있다는 점입니다. 이러한 특징들이 팀의 작업 프로세스를 표준화하고 온보딩을 간소화하는 데 매우 효과적입니다.
코드 예제
// Notion UI에서 Template 버튼을 만들고,
// API로 템플릿 기반 페이지를 생성할 수 있습니다
const { Client } = require('@notionhq/client');
const notion = new Client({ auth: process.env.NOTION_API_KEY });
async function createFromTemplate(databaseId, templateContent) {
// 템플릿 구조를 기반으로 새 페이지 생성
const response = await notion.pages.create({
parent: { database_id: databaseId },
properties: {
Name: { title: [{ text: { content: '새 프로젝트' } }] },
Status: { select: { name: 'Planning' } },
StartDate: { date: { start: new Date().toISOString() } }
},
// 페이지 내용(블록) 추가
children: [
{ heading_2: { rich_text: [{ text: { content: '📋 프로젝트 개요' } }] } },
{ paragraph: { rich_text: [{ text: { content: '프로젝트 목표와 범위를 작성하세요.' } }] } },
{ heading_2: { rich_text: [{ text: { content: '✅ 체크리스트' } }] } },
{ to_do: { rich_text: [{ text: { content: '요구사항 분석' } }], checked: false } },
{ to_do: { rich_text: [{ text: { content: '기술 스택 결정' } }], checked: false } }
]
});
return response;
}
설명
이것이 하는 일: 이 코드는 프로그래밍 방식으로 템플릿 기반의 페이지를 생성하며, Notion UI의 Template 버튼과 유사한 기능을 API로 구현합니다. 첫 번째로, createFromTemplate 함수는 데이터베이스 ID와 템플릿 내용을 받아 새로운 페이지를 생성합니다.
properties 객체에서 페이지의 메타데이터(제목, 상태, 시작일 등)를 설정하는데, 여기서 중요한 점은 이러한 기본값들이 템플릿의 일부로 자동 설정된다는 것입니다. 예를 들어 모든 새 프로젝트는 항상 'Planning' 상태로 시작하고, 생성 시점의 날짜가 자동으로 기록됩니다.
그 다음으로, children 배열을 통해 페이지의 실제 콘텐츠 블록을 추가합니다. 여기서는 두 개의 헤딩(heading_2)과 설명 문단(paragraph), 그리고 두 개의 체크리스트 항목(to_do)을 생성합니다.
각 블록은 Notion의 블록 타입에 맞는 구조를 따라야 하며, rich_text 배열을 통해 텍스트 내용을 정의합니다. 체크리스트 항목의 checked: false는 초기에는 체크되지 않은 상태임을 의미합니다.
마지막으로, 이 API 호출이 완료되면 완전히 구성된 페이지가 데이터베이스에 추가됩니다. 반환되는 응답 객체에는 생성된 페이지의 ID와 URL이 포함되어 있어, 사용자에게 바로 링크를 제공하거나 후속 API 호출에서 이 페이지를 업데이트하는 데 사용할 수 있습니다.
여러분이 이 코드를 사용하면 자동화 워크플로우에 템플릿 생성을 통합할 수 있습니다. 예를 들어 GitHub에서 새 이슈가 생성되면 자동으로 Notion에 해당하는 버그 리포트 페이지를 템플릿으로 생성하거나, Slack의 /명령어를 통해 회의록 템플릿을 즉시 생성하는 봇을 만들 수 있습니다.
또한 프로젝트 유형(신규 개발, 유지보수, 리서치 등)에 따라 다른 템플릿을 선택하는 조건부 로직을 추가하여 더욱 유연한 자동화를 구현할 수도 있습니다. 템플릿에 변수를 삽입하여 생성 시점의 정보(생성자, 현재 스프린트, 프로젝트 코드 등)를 자동으로 채워넣는 것도 가능합니다.
실전 팁
💡 Template 버튼을 데이터베이스 뷰 상단에 배치하면 모든 팀원이 쉽게 접근할 수 있습니다. 여러 개의 템플릿 버튼을 만들어 다양한 용도로 활용하세요.
💡 템플릿 내에서 @today, @me 같은 동적 변수를 사용하면 생성 시점의 날짜와 생성자를 자동으로 입력할 수 있습니다.
💡 복잡한 템플릿은 먼저 수동으로 완벽한 예시 페이지를 만들어보고, 그것을 기반으로 템플릿을 구성하면 실수를 줄일 수 있습니다.
💡 API로 템플릿을 생성할 때 children에 너무 많은 블록을 한 번에 추가하면 타임아웃이 발생할 수 있습니다. 100개 이상의 블록이 필요하면 페이지 생성 후 notion.blocks.children.append()로 추가 블록을 나누어 삽입하세요.
💡 팀의 워크플로우가 변경되면 템플릿도 즉시 업데이트하세요. 오래된 템플릿을 사용하면 오히려 혼란이 생길 수 있으니, 템플릿 관리 책임자를 지정하는 것이 좋습니다.
5. Synced Blocks로 콘텐츠 동기화하기
시작하며
여러분이 여러 페이지에서 동일한 정보(예: 팀 연락처, 배포 가이드, 코딩 컨벤션)를 유지해야 할 때, 한 곳을 수정하면 다른 모든 곳도 일일이 찾아서 업데이트해야 하는 번거로움을 겪은 적 있나요? 10개의 프로젝트 문서에 같은 배포 절차가 복사되어 있다면, 절차가 바뀔 때마다 10곳을 모두 수정해야 합니다.
이런 중복 콘텐츠는 정보 불일치를 초래하기 쉽습니다. 어느 한 곳을 업데이트하는 것을 깜빡하면 팀원들이 오래된 정보를 보고 잘못된 작업을 수행할 위험이 있습니다.
또한 어떤 버전이 최신인지 혼란스러워 신뢰도가 떨어집니다. 바로 이럴 때 필요한 것이 Notion의 Synced Blocks입니다.
원본 블록을 한 번만 수정하면 그것을 참조하는 모든 위치에 변경사항이 즉시 반영되어, 정보의 일관성을 완벽하게 유지할 수 있습니다.
개요
간단히 말해서, Synced Block은 한 곳에 작성된 콘텐츠를 여러 페이지에 동기화된 형태로 삽입할 수 있는 기능으로, 원본이 변경되면 모든 참조 위치가 자동으로 업데이트됩니다. 이 기능을 사용하면 자주 변경되는 공지사항을 여러 프로젝트 문서에 동기화하거나, 공통 FAQ를 모든 팀 위키에 일관되게 표시하거나, 표준 코드 스니펫을 여러 가이드에서 동일하게 유지할 수 있습니다.
예를 들어, API 인증 방법을 설명하는 블록을 원본으로 만들어두면, 모든 API 문서에서 같은 설명을 볼 수 있고, 인증 방식이 변경되면 원본 한 곳만 수정하면 됩니다. 기존에는 각 페이지를 일일이 찾아다니며 수동으로 업데이트했다면, 이제는 원본 한 곳만 관리하면 모든 참조가 자동으로 동기화됩니다.
Synced Block의 핵심 특징은 첫째, 실시간 동기화로 즉시 모든 위치에 변경사항이 반영되고, 둘째, 원본과 참조를 명확히 구분하여 실수로 참조를 수정하는 것을 방지하며, 셋째, 복잡한 블록 구조(헤딩, 리스트, 코드 블록 등)도 모두 동기화할 수 있다는 점입니다. 이러한 특징들이 대규모 문서 시스템에서 정보 일관성을 유지하고 유지보수 부담을 크게 줄이는 데 필수적입니다.
코드 예제
const { Client } = require('@notionhq/client');
const notion = new Client({ auth: process.env.NOTION_API_KEY });
async function createSyncedBlock(pageId, originalBlockId) {
// 페이지에 Synced Block 추가
const response = await notion.blocks.children.append({
block_id: pageId,
children: [
{
// Synced Block 참조 생성
synced_block: {
synced_from: {
block_id: originalBlockId // 원본 블록 ID 참조
}
}
}
]
});
return response;
}
// 새로운 원본 Synced Block 생성 (원본은 synced_from: null)
async function createOriginalSyncedBlock(pageId, content) {
const response = await notion.blocks.children.append({
block_id: pageId,
children: [
{
synced_block: {
synced_from: null, // null이면 원본 블록
children: [
{ paragraph: { rich_text: [{ text: { content } }] } }
]
}
}
]
});
return response.results[0].id; // 원본 블록 ID 반환
}
설명
이것이 하는 일: 이 코드는 Synced Block의 원본을 생성하고, 그것을 다른 페이지에서 참조하는 완전한 워크플로우를 API로 구현합니다. 첫 번째로, createSyncedBlock 함수는 기존의 원본 블록을 참조하는 Synced Block을 새로운 페이지에 추가합니다.
synced_block 객체의 synced_from 속성에 원본 블록의 ID를 지정하면 Notion이 자동으로 해당 블록의 콘텐츠를 가져와 동기화합니다. 이렇게 생성된 참조 블록은 읽기 전용이며, 원본이 변경되면 자동으로 업데이트됩니다.
여러 페이지에서 같은 원본을 참조할 수 있어 한 번의 수정으로 모든 곳을 업데이트할 수 있습니다. 그 다음으로, createOriginalSyncedBlock 함수는 새로운 원본 Synced Block을 생성하는 방법을 보여줍니다.
여기서 핵심은 synced_from: null로 설정하는 것인데, 이것이 바로 "이 블록은 원본이다"라는 의미입니다. children 배열에 실제 콘텐츠(여기서는 문단)를 정의하며, 이 콘텐츠가 다른 모든 참조 위치에 동기화될 내용입니다.
함수는 생성된 원본 블록의 ID를 반환하는데, 이 ID를 다른 페이지에서 참조할 때 사용합니다. 마지막으로, 실제 활용 시나리오를 생각해보면 먼저 중요한 공통 정보를 담은 원본 Synced Block을 생성하고, 그 블록 ID를 저장해둡니다.
그런 다음 필요한 모든 페이지에서 이 ID를 사용하여 참조 블록을 추가합니다. 원본 블록을 업데이트하려면 일반적인 블록 업데이트 API를 사용하면 되며, 변경사항은 자동으로 모든 참조에 전파됩니다.
여러분이 이 코드를 사용하면 조직의 중요한 정보를 중앙 집중식으로 관리할 수 있습니다. 예를 들어 보안 정책, 긴급 연락처, 자주 사용하는 코드 스니펫 같은 것들을 원본 블록으로 만들어두고, 관련된 모든 문서에 참조를 삽입하면 됩니다.
정책이 변경되면 원본 한 곳만 수정하면 모든 프로젝트 문서에 즉시 반영됩니다. 또한 온보딩 문서, 회고 템플릿, 릴리즈 체크리스트 같은 반복적으로 사용되는 구조를 Synced Block으로 만들어 일관성을 유지할 수 있습니다.
실전 팁
💡 원본 Synced Block은 별도의 "마스터 문서" 페이지에 모아두면 관리가 쉽습니다. 어디에 원본이 있는지 찾기 쉽고, 한눈에 어떤 콘텐츠들이 동기화되고 있는지 파악할 수 있습니다.
💡 Synced Block 내부에는 거의 모든 블록 타입(텍스트, 이미지, 코드, 리스트 등)을 포함할 수 있지만, 다른 Synced Block을 중첩할 수는 없습니다.
💡 참조 블록은 기본적으로 읽기 전용이지만, Notion UI에서 "원본으로 이동" 링크를 통해 쉽게 원본을 찾아 수정할 수 있습니다. API에서는 원본 블록 ID를 알고 있어야 수정 가능합니다.
💡 많은 페이지에서 같은 블록을 참조하고 있다면, 원본을 수정하기 전에 영향 범위를 파악하세요. 의도치 않게 중요한 문서의 내용이 바뀔 수 있습니다.
💡 버전 관리가 중요한 콘텐츠는 Synced Block보다 별도 페이지로 분리하고 링크로 참조하는 것이 더 안전할 수 있습니다. Synced Block은 즉시 동기화되므로 롤백이 어렵습니다.
6. 고급 필터로 동적 뷰 만들기
시작하며
여러분이 Notion 데이터베이스에서 원하는 정보를 찾으려고 할 때, 매번 수동으로 스크롤하면서 찾거나 단순한 필터로는 복잡한 조건을 표현하지 못해 답답했던 경험이 있나요? "이번 주에 마감인데 아직 시작하지 않은 내 작업"이나 "우선순위가 높으면서 담당자가 지정되지 않은 버그" 같은 복합적인 조건을 찾기가 어렵습니다.
이런 제한적인 필터링은 대량의 데이터에서 정확히 필요한 정보만 추출하기 어렵게 만들고, 중요한 항목을 놓치는 실수로 이어질 수 있습니다. 특히 프로젝트가 커질수록 데이터베이스에 수백 개의 항목이 쌓이면서 관리가 점점 어려워집니다.
바로 이럴 때 필요한 것이 Notion의 고급 필터 기능입니다. AND/OR 조건을 조합하고, 날짜 범위를 지정하고, 비어있는 값을 체크하는 등 복잡한 쿼리를 만들어 원하는 데이터만 정확하게 추출할 수 있습니다.
개요
간단히 말해서, 고급 필터는 여러 조건을 논리 연산자(AND, OR)로 결합하여 데이터베이스를 정교하게 쿼리할 수 있는 기능으로, SQL의 WHERE 절과 유사한 역할을 합니다. 이 기능을 사용하면 "완료되지 않았고 마감일이 오늘부터 3일 이내인 작업"이나 "특정 태그를 가지면서 최근 7일 내에 생성된 페이지"처럼 구체적인 조건을 설정할 수 있습니다.
예를 들어, 스프린트 보드에서 "현재 스프린트이면서 (상태가 In Progress이거나 블로커가 있는) 작업"만 필터링하여 매일 스탠드업 미팅에서 논의할 항목을 자동으로 표시하는 것이 가능합니다. 기존에는 단순한 단일 조건 필터만 사용하거나 수동으로 항목을 찾았다면, 이제는 복잡한 비즈니스 로직을 필터로 표현하여 동적인 뷰를 만들 수 있습니다.
고급 필터의 핵심 특징은 첫째, AND/OR를 중첩하여 복잡한 조건 트리를 구성할 수 있고, 둘째, 날짜 상대 비교(과거 X일, 다음 X주 등)를 지원하여 시간에 따라 자동으로 변하는 뷰를 만들 수 있으며, 셋째, 빈 값 체크, 포함/미포함 등 다양한 연산자를 제공한다는 점입니다. 이러한 특징들이 데이터 중심 워크플로우를 구축하고 의사결정에 필요한 정보를 즉시 파악하는 데 핵심적입니다.
코드 예제
const { Client } = require('@notionhq/client');
const notion = new Client({ auth: process.env.NOTION_API_KEY });
async function queryWithAdvancedFilter(databaseId) {
// 복잡한 조건으로 데이터베이스 쿼리
const response = await notion.databases.query({
database_id: databaseId,
filter: {
and: [ // AND 조건: 모든 조건을 만족해야 함
{
property: 'Status',
select: { does_not_equal: 'Done' } // 완료되지 않음
},
{
or: [ // OR 조건: 둘 중 하나라도 만족
{
property: 'DueDate',
date: { next_week: {} } // 다음 주 마감
},
{
property: 'Priority',
select: { equals: '🔴 긴급' } // 긴급 우선순위
}
]
},
{
property: 'Assignee',
people: { is_not_empty: true } // 담당자가 지정됨
}
]
},
sorts: [
{ property: 'DueDate', direction: 'ascending' } // 마감일 오름차순
]
});
return response.results;
}
설명
이것이 하는 일: 이 코드는 Notion 데이터베이스에서 복잡한 비즈니스 로직을 표현하는 고급 필터를 사용하여 특정 조건을 만족하는 항목들만 추출합니다. 첫 번째로, filter 객체의 최상위에 and 배열을 사용하여 여러 조건을 모두 만족해야 한다는 것을 정의합니다.
첫 번째 조건은 Status가 'Done'이 아닌 항목들을 찾습니다. does_not_equal 연산자는 특정 값을 제외할 때 유용하며, 완료된 작업을 필터에서 제거하는 일반적인 패턴입니다.
그 다음으로, or 조건을 중첩하여 "다음 주에 마감이거나 긴급 우선순위인" 항목을 찾습니다. 이렇게 AND 안에 OR을 넣는 방식으로 "(A AND (B OR C))" 같은 복잡한 논리를 표현할 수 있습니다.
date: { next_week: {} }는 상대적 날짜 필터로, 현재 시점을 기준으로 자동으로 계산되므로 매일 실행해도 항상 "다음 주" 마감인 항목을 정확히 찾아줍니다. 이런 상대 날짜 필터는 past_week, next_month, on_or_after: { start: '2024-01-01' } 등 다양하게 활용할 수 있습니다.
마지막으로, people: { is_not_empty: true } 조건으로 담당자가 지정된 항목만 필터링하고, sorts 배열로 결과를 마감일 순으로 정렬합니다. 이렇게 조합하면 "아직 완료되지 않았고, (다음 주 마감이거나 긴급하고), 담당자가 있는 작업들을 마감일 순으로" 가져오는 정교한 쿼리가 완성됩니다.
여러분이 이 코드를 사용하면 맞춤형 대시보드나 자동 리포트를 구축할 수 있습니다. 예를 들어 매일 아침 이 쿼리를 실행하여 "오늘 집중해야 할 작업" 목록을 슬랙에 자동으로 보내거나, 매주 금요일에 "다음 주에 마감인 항목들" 리스트를 이메일로 발송하는 자동화를 만들 수 있습니다.
또한 팀 리더 대시보드에서 "담당자가 지정되지 않은 긴급 이슈", "마감일이 지났지만 완료되지 않은 작업", "특정 라벨이 붙은 모든 항목" 같은 여러 개의 동적 섹션을 만들어 실시간으로 팀 상태를 모니터링할 수 있습니다.
실전 팁
💡 복잡한 필터를 작성할 때는 먼저 Notion UI에서 테스트해보고, 브라우저 개발자 도구의 네트워크 탭에서 실제 API 요청을 확인하면 정확한 구조를 알 수 있습니다.
💡 상대 날짜 필터(past_week, next_month 등)는 매일 자동으로 업데이트되므로 "이번 주 작업" 같은 동적 뷰를 만들 때 매우 유용합니다.
💡 is_empty와 is_not_empty는 모든 속성 타입에 사용할 수 있어 "아직 검토되지 않은 항목(Reviewer가 비어있음)" 같은 체크에 활용할 수 있습니다.
💡 필터가 너무 복잡해지면 쿼리 성능이 저하될 수 있습니다. 가능하면 먼저 가장 제한적인 조건(결과를 크게 줄이는 조건)을 앞에 배치하세요.
💡 API 응답은 페이지네이션이 적용됩니다(기본 100개). 모든 결과를 가져오려면 has_more를 확인하고 start_cursor를 사용해 다음 페이지를 반복 요청하는 로직을 추가하세요.
7. Webhook과 통합하여 실시간 알림 구현
시작하며
여러분이 중요한 Notion 페이지가 업데이트될 때마다 팀에 즉시 알려야 하는데, 계속 페이지를 새로고침하면서 변경사항을 확인하거나 수동으로 슬랙 메시지를 보내는 것이 번거로웠던 경험이 있나요? 누군가 긴급 버그를 추가했는데 한참 후에야 알아차리면 대응이 늦어집니다.
이런 수동 모니터링은 실시간성이 떨어지고, 중요한 변경사항을 놓칠 위험이 있으며, 팀원들이 계속 확인하느라 시간을 낭비하게 만듭니다. 특히 빠른 대응이 필요한 이슈나 승인이 필요한 작업의 경우 지연이 프로젝트 전체에 영향을 줄 수 있습니다.
바로 이럴 때 필요한 것이 Webhook을 활용한 실시간 알림 시스템입니다. Notion에서 특정 이벤트(페이지 생성, 속성 변경 등)가 발생하면 즉시 외부 시스템으로 데이터를 전송하여 자동으로 알림을 보내거나 후속 작업을 트리거할 수 있습니다.
개요
간단히 말해서, Webhook 통합은 Notion의 변경사항을 실시간으로 감지하여 외부 서비스(Slack, Discord, 이메일, 커스텀 서버 등)에 자동으로 알림을 보내는 이벤트 기반 자동화 메커니즘입니다. 이 기능을 사용하면 새로운 버그 리포트가 생성되면 자동으로 개발 채널에 슬랙 메시지를 보내거나, 작업 상태가 "완료"로 변경되면 프로젝트 매니저에게 이메일을 발송하거나, 긴급 우선순위가 지정되면 즉시 담당자에게 SMS를 보낼 수 있습니다.
예를 들어, 고객이 Notion 폼을 통해 지원 요청을 제출하면 자동으로 티케팅 시스템에 이슈를 생성하고 담당팀 채널에 알림을 보내는 완전 자동화된 워크플로우를 구축할 수 있습니다. 기존에는 주기적으로 폴링하여 변경사항을 확인하거나 수동으로 알림을 보냈다면, 이제는 이벤트가 발생하는 즉시 자동으로 처리됩니다.
Webhook 통합의 핵심 특징은 첫째, 이벤트 발생 즉시 데이터가 전송되어 실시간 대응이 가능하고, 둘째, 서버리스 함수(AWS Lambda, Vercel Functions 등)와 결합하여 확장 가능한 자동화를 구축할 수 있으며, 셋째, 여러 서비스를 체인으로 연결하여 복잡한 워크플로우를 만들 수 있다는 점입니다. 이러한 특징들이 팀의 커뮤니케이션을 개선하고 중요한 이벤트에 대한 대응 속도를 크게 향상시킵니다.
코드 예제
// Notion은 직접적인 webhook을 제공하지 않으므로,
// 폴링 방식으로 변경사항을 감지하고 webhook으로 전송
const { Client } = require('@notionhq/client');
const axios = require('axios');
const notion = new Client({ auth: process.env.NOTION_API_KEY });
async function monitorAndNotify(databaseId, webhookUrl, lastChecked) {
// 마지막 체크 이후 변경된 항목 쿼리
const response = await notion.databases.query({
database_id: databaseId,
filter: {
property: 'LastEdited',
date: { after: lastChecked }
}
});
// 변경된 항목마다 webhook 전송
for (const page of response.results) {
const title = page.properties.Name.title[0]?.text.content || 'Untitled';
const status = page.properties.Status.select?.name || 'None';
// Slack webhook 형식으로 알림 전송
await axios.post(webhookUrl, {
text: `📢 Notion 업데이트: "${title}"`,
blocks: [
{
type: 'section',
text: { type: 'mrkdwn', text: `*${title}*\n상태: ${status}` }
},
{
type: 'actions',
elements: [
{
type: 'button',
text: { type: 'plain_text', text: '페이지 열기' },
url: page.url
}
]
}
]
});
}
return response.results.length;
}
// 주기적으로 실행 (예: 1분마다)
setInterval(() => monitorAndNotify(DB_ID, WEBHOOK_URL, lastCheck), 60000);
설명
이것이 하는 일: 이 코드는 Notion 데이터베이스의 변경사항을 주기적으로 확인하고, 새로운 업데이트가 있으면 Slack webhook을 통해 팀 채널에 자동으로 알림을 보냅니다. 첫 번째로, monitorAndNotify 함수는 마지막 확인 시점(lastChecked) 이후에 수정된 항목들을 쿼리합니다.
LastEdited 속성에 after 필터를 사용하여 특정 시점 이후의 변경사항만 가져오므로, 이미 처리한 항목을 중복으로 알림 보내는 것을 방지합니다. Notion의 Last edited time 속성은 자동으로 관리되므로 별도로 수동 업데이트할 필요가 없습니다.
그 다음으로, 쿼리 결과를 반복하면서 각 페이지의 정보를 추출합니다. 제목(Name)과 상태(Status)를 가져와 Slack 메시지 형식으로 구성하는데, 여기서 중요한 점은 Slack의 Block Kit 형식을 사용하여 시각적으로 풍부한 메시지를 만든다는 것입니다.
section 블록으로 주요 정보를 표시하고, actions 블록으로 "페이지 열기" 버튼을 추가하여 클릭 한 번으로 해당 Notion 페이지로 바로 이동할 수 있게 합니다. 마지막으로, setInterval을 사용하여 이 함수를 주기적으로(60초마다) 실행합니다.
실제 프로덕션 환경에서는 cron job이나 AWS Lambda의 CloudWatch Events를 사용하는 것이 더 안정적입니다. 각 실행 후에는 현재 시각을 lastCheck 변수에 저장하여 다음 실행 때 사용합니다.
여러분이 이 코드를 사용하면 팀의 중요한 업데이트를 놓치지 않고 즉시 대응할 수 있습니다. 예를 들어 고객 지원 티켓이 추가되면 5분 내에 담당자에게 알림이 가도록 설정하거나, 코드 리뷰 요청이 생성되면 즉시 리뷰어에게 멘션을 보내는 등의 활용이 가능합니다.
또한 여러 조건(긴급 우선순위, 특정 태그, 담당자 미지정 등)에 따라 다른 채널이나 사람에게 알림을 보내는 스마트 라우팅을 구현할 수도 있습니다. 더 나아가 Notion의 변경사항을 다른 시스템(JIRA, Trello, Linear 등)에 동기화하는 양방향 통합도 가능합니다.
실전 팁
💡 Slack webhook URL은 민감 정보이므로 반드시 환경 변수로 관리하세요. GitHub에 노출되면 스팸이나 악용의 위험이 있습니다.
💡 폴링 간격은 너무 짧으면 API rate limit에 걸리고, 너무 길면 실시간성이 떨어집니다. 1-5분 간격이 적절하며, 중요도에 따라 조정하세요.
💡 대량의 변경사항이 한 번에 발생하면 너무 많은 알림이 쏟아질 수 있습니다. 한 번에 최대 N개까지만 알림을 보내거나, 여러 변경사항을 하나의 요약 메시지로 묶는 로직을 추가하세요.
💡 Slack 외에도 Discord, MS Teams, 이메일(SendGrid, AWS SES) 등 다양한 webhook을 지원하는 서비스와 통합할 수 있습니다. 각 서비스의 메시지 형식에 맞게 payload를 조정하세요.
💡 에러 처리를 반드시 추가하세요. API 호출 실패, webhook 전송 실패 등의 예외 상황을 로깅하고, 필요하면 재시도 로직을 구현하여 안정성을 높이세요.
8. 데이터베이스 Rollup으로 집계 데이터 자동 계산
시작하며
여러분이 프로젝트에 속한 모든 작업들의 예상 시간을 합산하거나, 특정 스프린트에서 완료된 작업 개수를 세거나, 팀원별 평균 작업 시간을 계산해야 할 때, 수동으로 계산기를 두드리거나 엑셀로 내보내서 집계하는 것이 얼마나 번거로운지 아시나요? 이런 수동 집계는 데이터가 변경될 때마다 다시 계산해야 하고, 실수가 발생하기 쉬우며, 실시간 인사이트를 얻기 어렵게 만듭니다.
특히 여러 데이터베이스에 걸쳐 있는 정보를 종합할 때는 데이터를 일일이 찾아다니며 계산해야 하는 고통이 따릅니다. 바로 이럴 때 필요한 것이 Notion의 Rollup 속성입니다.
Relation으로 연결된 항목들의 값을 자동으로 집계(합계, 평균, 개수, 최대/최소값 등)하여 프로젝트 수준의 메트릭을 실시간으로 보여줍니다.
개요
간단히 말해서, Rollup은 Relation 속성을 통해 연결된 다른 데이터베이스의 항목들로부터 특정 속성을 가져와 집계 함수를 적용하는 계산 속성으로, SQL의 GROUP BY 집계와 유사한 개념입니다. 이 기능을 사용하면 프로젝트 데이터베이스에서 연결된 모든 작업들의 예상 시간 합계를 자동 계산하거나, 완료된 작업 개수를 세어 진행률을 표시하거나, 가장 오래된 미완료 작업의 생성일을 찾아낼 수 있습니다.
예를 들어, 팀 데이터베이스에서 각 팀원에게 할당된 작업들의 평균 우선순위를 계산하여 누구의 워크로드가 가장 높은지 한눈에 파악하는 것이 가능합니다. 기존에는 Formula로 단일 페이지 내의 값만 계산하거나 수동으로 집계했다면, 이제는 Rollup으로 관계된 여러 항목들의 값을 자동으로 집계하여 상위 수준의 인사이트를 얻을 수 있습니다.
Rollup의 핵심 특징은 첫째, 다양한 집계 함수(Sum, Average, Count, Min, Max, Median 등)를 지원하고, 둘째, Relation이 변경되면 자동으로 재계산되어 항상 최신 값을 보장하며, 셋째, 집계된 값을 다시 Formula에서 참조하여 더 복잡한 계산을 수행할 수 있다는 점입니다. 이러한 특징들이 데이터 기반 의사결정과 프로젝트 메트릭 대시보드 구축에 필수적입니다.
코드 예제
// Rollup은 주로 Notion UI에서 설정하지만,
// API로 Rollup 값을 읽을 수 있습니다
const { Client } = require('@notionhq/client');
const notion = new Client({ auth: process.env.NOTION_API_KEY });
async function getProjectMetrics(projectPageId) {
// 프로젝트 페이지 정보 가져오기
const page = await notion.pages.retrieve({ page_id: projectPageId });
// Rollup으로 계산된 메트릭 추출
const metrics = {
// 총 작업 개수 (Count all)
totalTasks: page.properties.TotalTasks.rollup.number,
// 완료된 작업 개수 (Count values where Status = Done)
completedTasks: page.properties.CompletedTasks.rollup.number,
// 총 예상 시간 (Sum of EstimatedHours)
totalHours: page.properties.TotalHours.rollup.number,
// 평균 작업 시간 (Average of ActualHours)
avgHours: page.properties.AvgHours.rollup.number,
// 가장 긴급한 작업의 마감일 (Earliest of DueDate)
nextDeadline: page.properties.NextDeadline.rollup.date?.start
};
// 진행률 계산
metrics.progress = (metrics.completedTasks / metrics.totalTasks * 100).toFixed(1);
return metrics;
}
설명
이것이 하는 일: 이 코드는 Notion의 Rollup 속성으로 미리 계산된 프로젝트 메트릭들을 API로 읽어와 대시보드나 리포트에 활용할 수 있도록 구조화된 데이터로 반환합니다. 첫 번째로, notion.pages.retrieve()를 통해 프로젝트 페이지의 전체 정보를 가져옵니다.
이 페이지는 작업(Task) 데이터베이스와 Relation으로 연결되어 있으며, 여러 개의 Rollup 속성을 통해 연결된 작업들의 다양한 메트릭을 자동으로 계산하고 있습니다. Rollup은 Notion UI에서 설정하는데, 예를 들어 "TotalTasks" Rollup은 Tasks Relation을 참조하여 "Count all"을 계산하고, "CompletedTasks"는 "Count values"에 Status = Done 필터를 적용한 것입니다.
그 다음으로, 각 Rollup 속성에서 계산된 값을 추출합니다. Rollup의 결과 타입은 사용한 집계 함수에 따라 다릅니다.
number 타입(Sum, Average, Count 등), date 타입(Earliest, Latest), array 타입(Show original 등)이 있으며, 적절한 속성으로 접근해야 합니다. 예를 들어 TotalHours.rollup.number는 연결된 모든 작업들의 예상 시간을 합산한 숫자 값이고, NextDeadline.rollup.date?.start는 가장 빠른 마감일을 나타내는 날짜 문자열입니다.
마지막으로, 추출한 메트릭들을 사용하여 추가적인 계산을 수행합니다. 여기서는 완료된 작업 개수를 전체 작업 개수로 나누어 진행률을 백분율로 계산합니다.
이렇게 API로 가져온 데이터는 커스텀 대시보드, 차트 생성, 주간 리포트 자동 생성 등 다양한 용도로 활용할 수 있습니다. 여러분이 이 코드를 사용하면 경영진 대시보드를 구축하거나 자동화된 리포트 시스템을 만들 수 있습니다.
예를 들어 매주 금요일에 모든 활성 프로젝트의 메트릭을 수집하여 "주간 프로젝트 현황" 이메일을 자동 발송하거나, Grafana 같은 모니터링 도구에 데이터를 전송하여 시계열 차트로 프로젝트 진행 추이를 시각화할 수 있습니다. 또한 특정 임계값을 초과하면 알림을 보내는 스마트 모니터링도 가능합니다(예: 프로젝트 예상 시간이 200시간을 초과하면 경고).
실전 팁
💡 Rollup 속성을 만들 때는 먼저 Relation이 제대로 설정되어 있어야 합니다. Relation → Rollup 순서로 생성하세요.
💡 "Count values"를 사용하면 특정 조건을 만족하는 항목만 셀 수 있습니다. "Count all"과 "Count values (Status = Done)"을 각각 만들면 진행률 계산이 가능합니다.
💡 Rollup에서 "Show original"을 선택하면 집계하지 않고 모든 값을 배열로 보여줍니다. 이것을 다시 Formula에서 참조하여 복잡한 조건부 계산을 할 수 있습니다.
💡 Rollup이 비어있을 때(연결된 항목이 없을 때)는 null이 반환됩니다. 코드에서 metrics.totalHours || 0 같은 방식으로 기본값을 제공하세요.
💡 중첩된 Rollup(Rollup의 Rollup)은 직접 지원되지 않지만, 중간 단계에 Formula를 사용하면 비슷한 효과를 낼 수 있습니다. 예: Task → Project → Portfolio 구조에서 Portfolio의 총 시간을 계산하려면 Project에서 먼저 Rollup하고, Portfolio에서 그 값을 다시 Rollup하세요.