02-types-base

Dec 7, 2025

Base Types

📁 관련 코드: lib/types/base.ts

모든 그래프 노드의 기반이 되는 타입들을 정의합니다.

왜 Base Types를 먼저 만드는가?

Graph Database의 핵심 원칙: 모든 노드는 공통된 속성을 가져야 합니다.

           BaseNode (공통)
               
   ┌───────────┼───────────┬───────────┬───────────┐
   
Memory      Person      Thread      Entity       Task

BaseNode를 먼저 정의하면:

  • 모든 노드가 일관된 구조를 가짐

  • 그래프 쿼리 시 공통 필드로 필터링 가능

  • TypeScript의 타입 안전성 확보

ImportanceTier

enum ImportanceTier {
  CRITICAL = 1.0,  // 금전, 계약, 긴급 의사결정
  HIGH = 0.8,      // 프로젝트 마일스톤, 다자간 합의
  MEDIUM = 0.6,    // 일반 업무 정보, 미팅 노트
  LOW = 0.4,       // 광고, 뉴스레터, 일반 알림
}

왜 숫자(0~1)로 정의했는가?

고려한 대안들:

대안

장점

단점

문자열 ("high", "low")

읽기 쉬움

정렬/비교 불가, 가중치 계산 불가

정수 (1, 2, 3, 4)

단순함

수학적 의미 없음 (3이 1보다 "3배 중요"한가?)

0~1 실수

확률/가중치로 해석 가능

약간 복잡

선택 이유:

  • 벡터 검색 시 가중치로 사용 가능

  • 여러 요소를 곱하거나 평균 낼 수 있음

  • 다른 점수들(confidence 등)과 일관된 스케일

실제 사용 예시

// 검색 결과 정렬
const sortedMemories = memories.sort(
  (a, b) => b.importance - a.importance
);

// 가중 평균 계산
const weightedScore = memory.importance * memory.confidence;

// 임계값 필터링
const importantOnly = memories.filter(
  m => m.importance >= ImportanceTier.HIGH
);

각 티어의 기준

티어

점수

예시

CRITICAL

1.0

"계약금 500만원 입금 완료", "내일까지 결정 필요"

HIGH

0.8

"다음 주 화요일 런칭", "팀 전체 미팅 결과"

MEDIUM

0.6

"회의록", "일반 업무 논의"

LOW

0.4

"뉴스레터", "프로모션 안내"

SourceType

enum SourceType {
  USER_INPUT = 'user_input',      // 우선순위 1 (최고)
  BOOTSTRAPPED = 'bootstrapped',  // 우선순위 2
  TOOL_OUTPUT = 'tool_output',    // 우선순위 3
  REALTIME = 'realtime',          // 우선순위 4 (최저)
}

왜 필요한가?

문제 상황: 같은 정보가 여러 소스에서 다르게 들어옴

예시 - "김철수"의 소속 회사:

  • 이메일 A (2024-01-10): "김철수, ABC회사"

  • 이메일 B (2024-01-15): "김철수, XYZ회사"

  • 사용자 입력 (2024-01-12): "김철수는 ABC회사야"

어떤 정보를 믿어야 할까?

우선순위 결정 로직

USER_INPUT > BOOTSTRAPPED > TOOL_OUTPUT > REALTIME
  1. USER_INPUT: 사용자가 직접 입력 → 가장 신뢰

  2. BOOTSTRAPPED: 초기 데이터 수집 시 검증된 정보

  3. TOOL_OUTPUT: MCP 도구가 생성한 정보

  4. REALTIME: 실시간 수집 (검증 시간 부족)

충돌 해결 예시

// 같은 사람에 대한 두 정보가 충돌할 때
if (existing.sourceType !== incoming.sourceType) {
  // 우선순위 비교
  const priority = {
    [SourceType.USER_INPUT]: 4,
    [SourceType.BOOTSTRAPPED]: 3,
    [SourceType.TOOL_OUTPUT]: 2,
    [SourceType.REALTIME]: 1,
  };

  if (priority[incoming.sourceType] > priority[existing.sourceType]) {
    // 새 정보로 덮어쓰기
    return incoming;
  }
}

NodeType

enum NodeType {
  MEMORY = 'memory',
  PERSON = 'person',
  THREAD = 'thread',
  ENTITY = 'entity',
  TASK = 'task',
}

각 노드 타입의 역할

타입

설명

예시

MEMORY

추출된 기억 단위

"1월 15일 미팅에서 Q1 목표 확정"

PERSON

사람 정보

"김철수 (ABC회사 PM)"

THREAD

이메일 스레드

"Re: Re: 프로젝트 일정 논의"

ENTITY

회사/제품/프로젝트

"ABC회사", "신규 앱 프로젝트"

TASK

할일/요청

"보고서 제출 (마감: 1/20)"

노드 간 관계 예시

[Thread: 프로젝트 논의]
        
        ├── contains ──→ [Memory: Q1 목표 확정]
        
        ├── involves ──→ [Person: 김철수]
        └── mentions ──→ [Entity: ABC회사]
        
        └── contains ──→ [Memory: 보고서 요청]
                                
                                └── creates ──→ [Task: 보고서 제출]

BaseNode

interface BaseNode {
  id: string;
  nodeType: NodeType;
  createdAt: Date;
  updatedAt: Date;
  sourceType: SourceType;
  sourceId?: string;
  confidence: number;
}

각 필드 상세 설명

id: string

  • 형식: UUID v4

  • 용도: 노드 고유 식별

  • 예시: "550e8400-e29b-41d4-a716-446655440000"

nodeType: NodeType

  • 용도: 노드 종류 구분

  • 왜 필요한가: 그래프 쿼리 시 타입별 필터링

// FalkorDB 쿼리 예시
MATCH (n:Node {nodeType: 'memory'}) RETURN n

createdAt: Date / updatedAt: Date

  • 용도: 시간 기반 정렬 및 필터링

  • 충돌 해결 시: 같은 우선순위면 최신 정보 우선

sourceType: SourceType

  • 용도: 정보 출처 추적, 충돌 해결

  • 위의 SourceType 섹션 참조

sourceId?: string

  • 용도: 원본 데이터 참조

  • 예시: Gmail의 messageId, threadId

  • 왜 optional인가: USER_INPUT은 원본 ID가 없음

confidence: number

  • 범위: 0.0 ~ 1.0

  • 용도: LLM 추출 신뢰도

confidence vs importance

이 두 개념은 자주 혼동되므로 명확히 구분합니다:


confidence

importance

질문

"이 정보가 맞나?"

"이 정보가 중요한가?"

결정 주체

LLM 추출 신뢰도

내용 기반 판단

예시

"이름 추출 90% 확신"

"계약금 정보라 매우 중요"

위치

BaseNode (모든 노드)

MemoryNode (메모리만)

// 둘 다 높아야 신뢰할 수 있는 중요 정보
const reliableImportant = memories.filter(
  m => m.confidence >= 0.8 && m.importance >= ImportanceTier.HIGH
);

다음 문서

  • → MemoryNode: 핵심 기억 단위의 스키마