feat: AI 업무 추천에 프로젝트 문서 내용 반영(DB 캐싱)

업무 작성 화면의 AI 추천이 프로젝트 제목·설명과 업무 제목·내용에 더해
프로젝트 첨부 문서의 내용까지 파악하도록 확장한다.

매 호출마다 문서를 재파싱하지 않도록, 업로드 시점에 1회 텍스트를
추출해 project_attachments.extracted_text 에 캐싱하고 AI 추천에서
꺼내 읽는 구조로 구현한다.

- ProjectAttachment.extractedText 컬럼 추가(text, nullable, select:false)
- extract-text.ts: txt/csv(직접)·pdf(pdf-parse)·docx(mammoth) 추출
  (문서당 8천 자 상한, 추출 불가/실패 시 null)
- addFile: 업로드 시 텍스트 추출·캐싱
- getAttachmentsTextForAi: 문서별 추출 본문을 합쳐 반환(총 1.6만 자 상한)
- suggestChecklist: [프로젝트 문서] 섹션을 프롬프트에 추가 + 시스템 규칙 보강
- 운영용 마이그레이션 추가(dev 는 synchronize 로 자동 반영)
- 추출 텍스트는 AI 내부용 — 프론트 응답 DTO 에는 노출하지 않음

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-23 14:54:29 +09:00
parent 87c9019446
commit 739a5a70f3
7 changed files with 555 additions and 100 deletions
@@ -0,0 +1,20 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
// 프로젝트 첨부 문서의 추출 본문 캐시 컬럼 추가.
// 업로드 시 1회 추출해 보관하고, AI 업무 추천에서 꺼내 읽는다.
// 운영(migrationsRun)에서만 실행되며, dev 는 synchronize 로 자동 반영된다.
export class AddProjectAttachmentExtractedText1782600000000 implements MigrationInterface {
name = 'AddProjectAttachmentExtractedText1782600000000';
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project_attachments" ADD "extracted_text" text`,
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
`ALTER TABLE "project_attachments" DROP COLUMN "extracted_text"`,
);
}
}