고객사 PoC · 단계별 안내

CrewMeal 설치 · 구성 · 테스트 가이드

CrewMeal을 처음 접하는 담당자가 위에서부터 순서대로 따라 하기만 하면 설치 · 구성 · 테스트를 끝낼 수 있도록 만든 문서입니다. 모든 명령은 Windows PowerShell 기준이며, 코드 상자의 복사 버튼을 눌러 그대로 붙여 넣으면 됩니다.

이 파일 하나만 있으면 인터넷 없이도 볼 수 있습니다. 체크한 진행 상황은 이 브라우저에 저장됩니다.


0

먼저 트랙을 고르세요

CrewMeal 테스트는 세 단계로 나뉩니다. A → B → C 순서를 권장합니다. 트랙 A는 혼자서 바로 할 수 있고, 트랙 C는 트랙 B의 배포 주소가 있어야 진행할 수 있습니다.

트랙 A

내 PC에서 30분 체험

문서를 넣으면 검색용 콘텐츠가 실제로 만들어지는지 눈으로 확인합니다.

필요
PC 1대 + Python
시간
약 30분
비용
0원
트랙 A 시작 →
트랙 B

고객사 Azure에 배포

그림·차트를 해석하는 고품질 AI 비전 분석을 켜고 서버로 운영합니다.

필요
Azure 구독(소유자)
시간
반나절
비용
사용량 과금
트랙 B 시작 →
트랙 C

SharePoint · Copilot 연동

라이브러리에서 버튼 한 번 → Copilot이 그 내용을 근거로 답하는 전 과정.

필요
M365 테넌트 관리자
시간
1일
비용
사용량 과금
트랙 C 시작 →
✅ 우선 결과물만 빨리 보고 싶다면 → 트랙 A만 하세요. Azure 구독도, Microsoft 365 계정도, 관리자 승인도 필요 없습니다.
⚠️ PoC 공통 주의 이 구성은 개념검증(PoC)용으로 공개 엔드포인트를 사용합니다. 실제 기밀 문서를 넣지 마세요. 테스트에는 비민감 문서만 사용합니다.

제품 개요와 아키텍처는 GitHub 저장소소개 사이트를 참고하세요.


1

사전 준비 사항

시작하기 전에 미리 준비해 두어야 할 것을 한곳에 모았습니다. 고른 트랙에 해당하는 것만 준비하면 됩니다. 표에서 는 필요 없다는 뜻입니다.

✅ 트랙 A만 해 본다면 준비물은 이게 전부입니다 PC 1대 · Python · Git · 테스트용 문서 몇 개. Azure 구독도, Microsoft 365 계정도, 결제 수단도, 관리자 승인도 필요 없습니다. 바로 트랙 A로 넘어가세요 →

1-1. 한눈에 보는 준비물

준비물ABC비고
작업용 Windows PC (PowerShell)1대
Python 3.11 이상3.12 권장
Git소스 내려받기
비민감 테스트 문서5~10개
Azure 구독 (소유자)결제 수단 등록됨
Azure CLI · Azure Developer CLI배포 도구
Entra 앱 등록 + 관리자 동의 권한앱 1개
eastus2 모델 쿼터 1,150K TPM부족하면 배포 실패
Microsoft 365 테넌트테스트 사이트 생성 가능
SharePoint 앱 카탈로그없으면 먼저 생성
Node.js 22.14 이상 23 미만SPFx 빌드용
Microsoft 365 Copilot 라이선스마지막 검증 1건에만
💡 Docker와 LibreOffice는 설치하지 않아도 됩니다 컨테이너 이미지는 Azure에서 원격 빌드(remoteBuild)되므로 로컬 Docker가 필요 없고, PPTX 변환용 LibreOffice와 한글 문서용 rhwp는 서버 이미지에 이미 포함되어 있습니다. 트랙 A는 AI를 쓰지 않는 저품질(텍스트+OCR) 티어로 도는 덕분에 둘 다 필요 없습니다.

1-2. 누가 참여해야 하나요

한 사람이 모든 권한을 갖고 있다면 혼자서도 가능합니다. 보통은 아래 세 역할이 필요합니다.

트랙 A

테스트 실무 담당자

문서를 준비하고 결과 품질을 평가하는 주 담당자입니다.

권한
본인 PC에 프로그램 설치
할 일
설치 · 실행 · 결과 확인
시간
약 30분
트랙 B

Azure 담당자

고객사 구독에 리소스를 만들고 배포를 실행합니다.

권한
구독 소유자(Owner)
할 일
쿼터 확인 · azd up
시간
반나절
트랙 C

Microsoft 365 관리자

앱 동의와 SharePoint 설정을 처리합니다.

권한
테넌트 관리자 · 사이트 소유자
할 일
동의 · 앱 설치 · API 승인
시간
1일

1-3. 설치할 소프트웨어

프로그램필요 버전필요한 트랙확인 명령
Python3.11 이상 (3.12 권장)A · B · Cpython --version
Git최신A · B · Cgit --version
Azure CLI2.60 이상B · Caz version
Azure Developer CLI1.28.0 이상B · Cazd version
Node.js22.14 이상 23 미만Cnode --version
Microsoft.Graph.Authentication최신CPowerShell 모듈

설치는 winget으로 한 번에 할 수 있습니다. 필요한 줄만 실행하세요.

# 모든 트랙 공통
winget install Python.Python.3.12
winget install Git.Git

# 트랙 B 이상
winget install Microsoft.AzureCLI
winget install Microsoft.Azd
⚠️ 두 가지만 주의하세요 Python 설치 화면에서 “Add python.exe to PATH” 체크를 꼭 켜세요. 그리고 SPFx 빌드는 Node.js 22.x만 허용하므로, 최신 LTS가 23 이상이면 빌드가 거부됩니다. nodejs.org에서 22.x를 직접 받거나 nvm-windows로 버전을 전환해 사용하세요.

설치가 끝났으면 아래로 한 번에 확인합니다. 필요한 줄에서 버전이 나오면 준비 완료입니다.

python --version
git --version
az version --output tsv 2>$null
azd version
node --version

1-4. Azure 쪽 준비 트랙 B · C

항목준비 내용
구독 권한소유자(Owner) 또는 리소스 생성 + Microsoft.Authorization/roleAssignments/write
결제결제 수단이 등록된 유료 구독 (무료 평가판은 쿼터가 부족합니다)
리전eastus2 — 템플릿에 고정. PostgreSQL만 centralus에 생성됩니다
모델 쿼터eastus2 GlobalStandard 기준 1,150K TPM 여유 (부족하면 용량을 낮춰 배포)
Azure Policy고객사 정책이 특정 리전·SKU·공용 엔드포인트를 막고 있지 않은지 미리 확인
Entra 앱앱 등록 1개와 관리자 동의를 부여할 수 있는 권한
💡 쿼터는 미리 확인해 두는 편이 좋습니다 쿼터가 모자라면 배포가 중간에 실패합니다. 확인 명령과 대처법은 트랙 B의 B-1 단계에 있습니다. 승인에 며칠 걸릴 수 있으니 부족하면 미리 증설을 신청하세요.

1-5. Microsoft 365 쪽 준비 트랙 C

항목준비 내용
테넌트 관리자Entra 앱에 관리자 동의를 부여할 수 있는 계정
테스트 사이트SharePoint 팀 사이트 1개 (예: crewmeal-test)와 문서 라이브러리
사이트 소유자열 추가·앱 설치를 할 수 있는 권한 (앱 권한 부여 스크립트도 이 계정으로 실행)
앱 카탈로그테넌트 앱 카탈로그가 있어야 SPFx 패키지를 올릴 수 있습니다. 없으면 먼저 생성하세요
API 액세스 승인SharePoint 관리 센터 → 고급 → API 액세스에서 승인할 수 있는 권한
Copilot 라이선스마지막 검증(범위 지정 Copilot 질의)에 필요합니다. 없으면 검색 반영까지만 확인
💡 커넥터 방식을 쓸 때만 추가 게시 방식으로 Copilot 커넥터를 고르면 Microsoft 365 관리 센터의 검색 및 인텔리전스 설정 권한이 추가로 필요합니다. 처음 테스트라면 권한이 단순한 SharePoint 컬럼 방식을 권장합니다.

1-6. 테스트용 문서 준비

아래 종류를 섞어서 5~10개 준비하면 뒤의 테스트 시나리오를 그대로 수행할 수 있습니다.

문서 종류확인하는 것필요한 트랙
텍스트 위주 PPTX원문 문장이 보존되는지A
표가 들어간 PPTX행·열 값이 누락 없이 재현되는지A
막대·선 차트 PPTX그래프의 의미를 문장으로 설명하는지B
간트차트 · 일정표 PPTX작업명·기간·순서를 설명하는지B
스캔이 아닌 PDF페이지별 내용이 추출되는지B
HWP · HWPX 한글 문서본문·표·머리말이 추출되는지B
50장 이상 대용량 덱실패 없이 완료되는지, 소요 시간B
⚠️ 실제 기밀 문서는 넣지 마세요 이 구성은 개념검증(PoC)용으로 공개 엔드포인트를 사용합니다. 사내 공개 자료, 이미 배포된 제안서, 샘플로 만든 문서처럼 유출되어도 문제가 없는 문서만 사용하세요.

1-7. 네트워크 · 방화벽

사내망에서 아래 주소가 막혀 있으면 설치나 배포가 중간에 멈춥니다. 폐쇄망이라면 미리 방화벽 예외를 신청해 두세요.

접속 대상용도트랙
github.com소스 코드 내려받기A · B · C
pypi.org, files.pythonhosted.org파이썬 패키지 설치A · B · C
127.0.0.1:8000트랙 A 로컬 웹 서버 (외부 통신 아님)A
login.microsoftonline.comAzure · Microsoft 365 로그인B · C
management.azure.com, portal.azure.comAzure 배포와 관리B · C
graph.microsoft.comSharePoint 정보 조회 · 게시B · C
*.azurecontainerapps.io배포된 웹 앱과 상태 페이지B · C
*.sharepoint.com테스트 사이트와 앱 카탈로그C
registry.npmjs.orgSPFx 패키지 빌드C

1-8. 시작 전 최종 점검

체크가 모두 켜지면 준비 완료입니다. 체크 상태는 이 브라우저에 저장됩니다.

점검 항목트랙
어느 트랙까지 진행할지 정했다 (A / B / C)공통
Python과 Git이 설치되어 버전이 확인된다공통
비민감 테스트 문서를 5~10개 모았다공통
Azure 구독 소유자 권한과 eastus2 쿼터를 확인했다B · C
M365 테넌트 관리자와 테스트 사이트가 준비됐다C
Node.js 22.x와 앱 카탈로그를 확인했다C

2

트랙 A — 내 PC에서 30분 체험

약 30분 · 비용 0원

Azure도 Microsoft 365도 없이 PC 한 대에서 문서를 넣고 결과를 확인합니다. AI 비전 모델을 쓰지 않는 저품질(텍스트+OCR) 티어로 동작하므로 비용이 전혀 들지 않고 LibreOffice 설치도 필요 없습니다.

A1

준비물 확인

항목필요 버전확인 명령
Python3.11 이상 (3.12 권장)python --version
Git아무 최신 버전git --version

없다면 python.orggit-scm.com에서 설치하세요. Python 설치 시 “Add python.exe to PATH” 체크를 꼭 켜세요.

A2

소스 코드 받기

cd $HOME
git clone https://github.com/microsoft/CrewMeal.git
cd CrewMeal
✅ 확인 dir 을 쳤을 때 README.md, src, scripts 폴더가 보이면 성공.
A3

파이썬 환경 만들기 2~5분

python -m venv .venv
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"

마지막 줄에 Successfully installed ... crewmeal-0.1.0 ... 이 나오면 성공입니다.

✅ 확인 아래 명령이 366 passed 같은 결과로 끝나면 설치가 정상입니다.
.\.venv\Scripts\python.exe -m pytest -q
A4

웹 서버 실행 터미널 1번

PowerShell 창을 하나 열고 아래를 통째로 붙여 넣습니다.

cd $HOME\CrewMeal
$env:CREWMEAL_ADMIN_KEY          = "local-admin-key"
$env:CREWMEAL_WEB_SESSION_SECRET  = "local-session-secret"
$env:CREWMEAL_INGEST_REQUIRE_AUTH = "false"
$env:CREWMEAL_STATUS_REQUIRE_AUTH = "false"
.\.venv\Scripts\python.exe -m uvicorn crewmeal.search_enhancement.web:create_app_from_env `
  --factory --host 127.0.0.1 --port 8000

Uvicorn running on http://127.0.0.1:8000 이 보이면 실행 중입니다. 이 창은 끄지 말고 그대로 두세요.

✅ 확인 브라우저에서 http://127.0.0.1:8000/healthz 를 열면 {"status":"ok"} 가 보입니다.
A5

문서 올리기

  1. 브라우저에서 http://127.0.0.1:8000/admin 접속
  2. 관리자 키에 local-admin-key 입력 후 로그인
  3. 상단 메뉴에서 시연 업로드(/admin/tryout) 클릭
  4. 테스트용 .pptx 파일을 선택하고 업로드 (.pdf·.hwp·.hwpx·.docx·.xlsx 등 활성화된 형식이면 무엇이든 됩니다 — 페이지에 허용 확장자가 표시됩니다)

업로드하면 자동으로 상태 페이지(/s/...)로 이동합니다. 이때 상태는 대기(Queued) 입니다 — 아직 처리할 워커를 켜지 않았기 때문입니다.

💡 팁 손에 든 PPT가 없다면 PowerPoint에서 슬라이드 2~3장짜리 아무 파일이나 만들어 쓰세요. 표·차트가 있으면 결과가 더 잘 보입니다.
A6

워커 실행해서 처리하기 터미널 2번

새 PowerShell 창을 하나 더 열고 아래를 통째로 붙여 넣습니다. 아래 M365 값은 의미 없는 더미 값입니다. 게시 대상이 아직 선택되지 않은 상태(unset)이므로 워커는 SharePoint에 접속하지 않습니다.

cd $HOME\CrewMeal
$env:CREWMEAL_M365_TENANT_ID     = "00000000-0000-0000-0000-000000000000"
$env:CREWMEAL_M365_CLIENT_ID     = "00000000-0000-0000-0000-000000000000"
$env:CREWMEAL_M365_CLIENT_SECRET = "local-dummy"
$env:CREWMEAL_M365_SITE_ID       = "local-dummy-site"
$env:CREWMEAL_M365_DRIVE_ID      = "local-dummy-drive"
$env:CREWMEAL_M365_LIST_ID       = "local-dummy-list"
$env:CREWMEAL_M365_SITE_URL      = "https://localhost/sites/local"

# 비용 0원 · AI 호출 없음 (저품질 텍스트 티어)
$env:PPTX_ANALYSIS_TIER = "text_ocr"
$env:PPTX_OCR_ENABLED   = "false"

.\.venv\Scripts\python.exe -m crewmeal.search_enhancement.cli once --verbose
✅ 확인 마지막에 Processed 0 command(s) and 1 job(s). 가 보이면 문서 1건을 처리한 것입니다.
A7

결과 확인

A-5에서 열렸던 상태 페이지로 돌아갑니다. 이 페이지는 3초마다 스스로 갱신되므로 그냥 두고 보면 됩니다(수동 새로고침도 가능).

보이는 것의미
완료 배지처리 성공
「진행 상황」 타임라인 8단계작업 시작 → 원본 다운로드 → 파일 검증 → 문서 변환·추출 → 페이지 렌더링 → 콘텐츠 분석 → HTML 생성 → 완료
「추출된 HTML 미리보기」실제로 만들어진 검색용 콘텐츠 (새 창에서 열기 ↗ 로 크게 보기)
✅ 합격 기준 추출된 HTML 안에 원본 슬라이드의 제목 · 문장 · 표 내용이 그대로 들어 있으면 정상입니다.
A8

트랙 A 정리

  • 터미널 1(웹)에서 Ctrl + C 를 눌러 서버를 끕니다.
  • 로컬 데이터는 .crewmeal\search-enhancement.db 파일 하나에만 저장됩니다. 지우고 싶으면 폴더째 삭제하세요.
Remove-Item -Recurse -Force .crewmeal
📌 트랙 A의 한계 저품질 티어는 AI 비전 모델을 쓰지 않으므로 그림 · 차트 · 다이어그램의 의미 설명은 생성되지 않습니다. 간트차트 해석, 도표 요약 등 CrewMeal의 핵심 가치를 보려면 트랙 B로 넘어가세요.

3

트랙 B — 고객사 Azure 구독에 배포

반나절

여기서부터 고품질(AI 비전) 분석이 켜집니다. 웹 앱과 워커가 Azure Container Apps에서 24시간 돌아갑니다.

B1

준비물 · 쿼터 확인

항목요구 사항
Azure 구독소유자(Owner) 또는 리소스 생성 + Microsoft.Authorization/roleAssignments/write 권한
Azure CLI2.60 이상 — az version
Azure Developer CLI1.28.0 이상azd version
리전eastus2 (템플릿에 고정, 아래 참고)
모델 쿼터eastus2 GlobalStandard 기준 1,150K TPM 여유

설치 명령:

winget install Microsoft.AzureCLI
winget install Microsoft.Azd
⚠️ 리전 고정 infra/main.biceplocation 파라미터는 현재 @allowed(['eastus2']) 로 제한되어 있습니다. 다른 리전에 배포하려면 이 목록에 원하는 리전을 추가해야 하고, 해당 리전에 GPT-5.6 Luna 모델이 제공되는지 먼저 확인해야 합니다. PostgreSQL은 별도로 centralus 에 만들어집니다(postgresLocation 파라미터로 변경 가능).

쿼터 확인 — 부족하면 azd up 이 실패합니다.

az login
az account set --subscription "<고객사 구독 ID>"
az cognitiveservices usage list --location eastus2 `
  --query "[?contains(name.value,'GlobalStandard')].{name:name.value,used:currentValue,limit:limit}" -o table

배포되는 모델 4종과 기본 용량:

배포 이름모델용량(TPM)용도
gpt-5-6-luna-testgpt-5.6-luna500K운영 기본 슬라이드 분석
gpt-5-2gpt-5.2500K폴백
gpt-5-minigpt-5-mini100K비교용
text-embedding-3-large임베딩50K예비

쿼터가 모자라면 infra/modules/foundry.bicepgptCapacity, lunaCapacity, embeddingCapacity 값을 낮추세요 (예: 각각 100, 100, 10).

B2

Microsoft 365 앱 등록 만들기

Azure 배포에는 M365 앱의 테넌트 ID / 클라이언트 ID / 시크릿이 필요합니다. SharePoint 연동을 아직 안 하더라도 값 자체는 있어야 합니다.

  1. Entra 관리 센터앱 등록새 등록
  2. 이름: crewmeal-poc, 지원되는 계정 유형: 이 조직 디렉터리의 계정만
  3. 만들고 나서 개요 화면에서 다음 두 값을 메모합니다.
    • 애플리케이션(클라이언트) ID → CREWMEAL_M365_CLIENT_ID
    • 디렉터리(테넌트) ID → CREWMEAL_M365_TENANT_ID
  4. 인증서 및 암호새 클라이언트 암호 → 값 복사 → CREWMEAL_M365_CLIENT_SECRET
    이 화면을 벗어나면 다시 볼 수 없습니다.
  5. API 권한권한 추가Microsoft Graph애플리케이션 권한에서 다음을 추가합니다.
권한필수 여부
Sites.Selected✅ 필수
ExternalConnection.ReadWrite.OwnedByCopilot 커넥터 방식일 때만
ExternalItem.ReadWrite.OwnedByCopilot 커넥터 방식일 때만
  1. 같은 화면에서 SharePoint애플리케이션 권한Sites.Selected 도 추가
  2. 관리자 동의 부여 버튼을 눌러 동의 처리 (상태가 모두 초록색 체크가 되어야 함)
🔐 최소 권한 Sites.Selected는 “관리자가 지정한 사이트에만” 접근하는 최소 권한입니다. 테넌트 전체 문서에 접근하지 않습니다.
B3

배포 값 설정

SharePoint 사이트를 아직 안 만들었다면 site / drive / list 값은 임시로 pending 을 넣고, 트랙 C에서 실제 값으로 바꾸면 됩니다.

cd $HOME\CrewMeal
azd auth login
azd env new poc
azd env set AZURE_SUBSCRIPTION_ID "<고객사 구독 ID>"
azd env set AZURE_LOCATION        "eastus2"

# 새로 만들 비밀 값 — 직접 정하세요
#   ※ POSTGRES_ADMIN_PASSWORD 는 DB 접속 문자열에 들어가므로
#     @ : / ? # 같은 문자를 쓰지 말고 영문·숫자·하이픈만 사용하세요.
azd env set POSTGRES_ADMIN_PASSWORD     "Crewmeal-Poc-2026-Strong"
azd env set CREWMEAL_ADMIN_KEY          "<관리자 포털 접속 키>"
azd env set CREWMEAL_WEB_SESSION_SECRET "<임의의 긴 문자열>"

# B-2에서 만든 앱 값
azd env set CREWMEAL_M365_TENANT_ID     "<테넌트 ID>"
azd env set CREWMEAL_M365_CLIENT_ID     "<클라이언트 ID>"
azd env set CREWMEAL_M365_CLIENT_SECRET "<클라이언트 시크릿>"

# SharePoint 값 (트랙 C에서 확정 — 지금은 자리표시자)
azd env set CREWMEAL_M365_SITE_ID       "pending"
azd env set CREWMEAL_M365_DRIVE_ID      "pending"
azd env set CREWMEAL_M365_LIST_ID       "pending"
azd env set CREWMEAL_M365_SITE_URL      "pending"
azd env set CREWMEAL_M365_CONNECTION_ID "crewmealpoc"

# 초기 PoC는 Ingest 인증 없이 시작 (트랙 C에서 켭니다)
azd env set CREWMEAL_INGEST_REQUIRE_AUTH "false"
azd env set CREWMEAL_INGEST_AUDIENCE     "api://crewmeal-ingest"
B4

배포 실행 15~25분

azd up
  • 인프라 생성 → 컨테이너 이미지 빌드 → 웹/워커 배포까지 자동으로 진행됩니다.
  • 이미지는 Azure Container Registry에서 원격 빌드(remoteBuild: true)되므로 PC에 Docker를 설치할 필요가 없습니다.

만들어지는 주요 리소스:

리소스용도
Microsoft Foundry (AIServices S0)슬라이드 분석 모델 4종
Container Apps 환경 + 웹/워커 앱서비스 실행
Container Registry (Standard)컨테이너 이미지
PostgreSQL Flexible Server 16상태 · 큐 · 산출물 저장
Storage / Key Vault(정책 허용 시 사용)
Log Analytics로그
사용자 할당 관리 ID키 없는 인증
✅ 확인 완료 메시지의 SERVICE_WEB_URI 를 복사해 둡니다.
azd env get-values | Select-String "SERVICE_WEB_URI"
B5

배포 직후 1회 수동 작업 필수

⚠️ 건너뛰면 로그인이 안 됩니다 상태 페이지 로그인(Entra SSO)이 동작하려면 앱 등록에 리디렉션 URI를 추가해야 합니다. 하지 않으면 로그인 시 AADSTS50011 오류가 납니다.
  1. Entra 관리 센터 → 앱 등록crewmeal-poc인증
  2. 플랫폼 추가
  3. 리디렉션 URI에 아래를 입력 (B-4에서 복사한 주소 사용)
    https://<SERVICE_WEB_URI 호스트>/auth/callback
  4. 암시적 허용 및 하이브리드 흐름 에서 ID 토큰 체크 → 저장
B6

배포 검증

$web = (azd env get-values | Select-String "SERVICE_WEB_URI").ToString().Split('=')[1].Trim('"')
Invoke-WebRequest "$web/healthz" -UseBasicParsing | Select-Object -ExpandProperty Content
Invoke-WebRequest "$web/readyz"  -UseBasicParsing | Select-Object -ExpandProperty Content

둘 다 {"status":"ok"} / {"status":"ready"} 가 나와야 합니다. (readyz 는 데이터베이스 연결까지 확인합니다.)

고품질 분석 실제 확인

  1. 브라우저에서 {SERVICE_WEB_URI}/admin 접속 → CREWMEAL_ADMIN_KEY 로 로그인
  2. 설정 화면에서 「이미지 분석 모델」 카드가 gpt-5.6-luna / gpt-5-6-luna-test 로 표시되는지 확인
  3. 시연 업로드에서 그림 · 차트가 있는 PPT를 업로드
  4. 상태 페이지에서 완료 까지 진행되는지 확인
  5. 추출된 HTML에 그림/차트에 대한 설명 문장이 들어 있으면 성공
✅ 트랙 B 합격 기준 차트가 들어간 슬라이드에서 “무엇을 나타내는 그래프인지” 문장으로 설명이 생성됨.

4

트랙 C — SharePoint · Copilot 연동

1일

사용자가 SharePoint 문서 라이브러리에서 파일을 선택하고 버튼 한 번으로 검색강화를 요청하고, 결과가 Microsoft Search / Copilot에 반영되는 전체 흐름입니다.

C1

테스트 사이트와 라이브러리 준비

  1. SharePoint에서 팀 사이트를 새로 만듭니다 (예: crewmeal-test).
  2. 기본 문서(Documents) 라이브러리를 사용합니다.
  3. 비민감 테스트 문서(PPTX/PDF) 5~10개를 업로드합니다.
  4. 라이브러리에 하이퍼링크 열을 하나 수동으로 추가합니다.
    • 열 추가 → 종류 하이퍼링크 → 이름 CrewmealSearchStatusLink
⚠️ 자동 생성되지 않는 열 CrewmealSearchStatusLink 는 스크립트가 만들어 주지 않습니다. SPFx 명령이 상태 페이지 링크를 여기에 기록하므로 반드시 수동으로 추가하세요.
C2

사이트 / 드라이브 / 목록 ID 조회

Install-Module Microsoft.Graph.Authentication -Scope CurrentUser   # 최초 1회
Import-Module Microsoft.Graph.Authentication
Connect-MgGraph -Scopes "Sites.Read.All" -UseDeviceCode -NoWelcome

$hostName = "contoso.sharepoint.com"     # 고객사 도메인으로 변경
$sitePath = "crewmeal-test"              # 사이트 경로로 변경

$site = Invoke-MgGraphRequest -Method GET `
  -Uri "https://graph.microsoft.com/v1.0/sites/${hostName}:/sites/${sitePath}"
$drives = Invoke-MgGraphRequest -Method GET `
  -Uri "https://graph.microsoft.com/v1.0/sites/$($site.id)/drives"
$drive = $drives.value | Where-Object { $_.name -in @("Documents", "문서") } | Select-Object -First 1
$list = Invoke-MgGraphRequest -Method GET `
  -Uri "https://graph.microsoft.com/v1.0/sites/$($site.id)/drives/$($drive.id)/list"

[pscustomobject]@{
  SITE_ID  = $site.id
  DRIVE_ID = $drive.id
  LIST_ID  = $list.id
  SITE_URL = $site.webUrl
} | Format-List

출력된 4개 값을 메모합니다.

C3

사용자 환경 변수 설정 스크립트용

⚠️ 여기서 가장 많이 막힙니다 scripts\*.ps1사용자(User) 범위 환경 변수를 읽습니다. $env: 로만 설정하면 스크립트가 값을 찾지 못합니다.
$vars = @{
  CREWMEAL_M365_TENANT_ID     = "<테넌트 ID>"
  CREWMEAL_M365_CLIENT_ID     = "<클라이언트 ID>"
  CREWMEAL_M365_CLIENT_SECRET = "<클라이언트 시크릿>"
  CREWMEAL_M365_SITE_ID       = "<C-2의 SITE_ID>"
  CREWMEAL_M365_DRIVE_ID      = "<C-2의 DRIVE_ID>"
  CREWMEAL_M365_LIST_ID       = "<C-2의 LIST_ID>"
  CREWMEAL_M365_SITE_URL      = "<C-2의 SITE_URL>"
  CREWMEAL_M365_CONNECTION_ID = "crewmealpoc"
}
foreach ($k in $vars.Keys) {
  [Environment]::SetEnvironmentVariable($k, $vars[$k], "User")
  Set-Item -Path "Env:$k" -Value $vars[$k]
}

설정 후 PowerShell 창을 새로 열어야 값이 반영됩니다.

C4

앱에 대상 사이트 권한 부여 사이트 관리자 1회

cd $HOME\CrewMeal
.\scripts\grant_test_site_permission.ps1

장치 코드 로그인이 뜨면 사이트 관리자 계정으로 로그인합니다.

✅ 확인 출력에 roles: write 가 나오면 성공입니다.
C5

게시 방식 선택

관리자 포털 {SERVICE_WEB_URI}/admin/settings?tab=publication검색 콘텐츠 게시 방식 카드에서 하나를 고릅니다. 새 설치는 선택 전까지 아무 곳에도 게시하지 않습니다.

방식장점단점추천
SharePoint 컬럼원본 문서의 권한(ACL)을 그대로 사용, 설정 단순컬럼당 63,999자 제한⭐ 처음 테스트에 권장
Copilot 커넥터길이 여유(HTML 3MB), 별도 색인커넥터 권한 · 관리센터 설정 필요대규모 검토 시

C-5-a. SharePoint 컬럼 방식

cd $HOME\CrewMeal
.\scripts\provision_test_library_admin.ps1

이 스크립트는 라이브러리에 상태 열들을 만들고, 작업 중에만 앱 권한을 fullcontrol 로 올렸다가 끝나면 반드시 write 로 되돌립니다.

검색 콘텐츠 컬럼(CrewmealSearchContent) 연결과 상태 열 서식은 SharePoint가 앱 전용 토큰을 허용하지 않아 사이트 소유자 세션이 필요합니다. 위임 토큰이 있다면 아래처럼 적용합니다.

$env:CREWMEAL_M365_SHAREPOINT_ACCESS_TOKEN = "<위임 SharePoint 액세스 토큰>"
.\.venv\Scripts\python.exe .\scripts\configure_test_library.py `
  --apply-content-column --apply-formatting

C-5-b. Copilot 커넥터 방식

cd $HOME\CrewMeal
.\.venv\Scripts\python.exe .\scripts\configure_copilot_connection.py

그리고 Microsoft 365 관리 센터 → 검색 및 인텔리전스 → 사용자 지정 → 세로 항목 → All → 커넥터 결과 관리 에서 해당 커넥터의 인라인 결과를 활성화해야 Copilot이 항목을 참조합니다.

C6

문서 형식 켜기

/admin/settings?tab=formats문서 형식 지원 카드에서 테스트할 형식을 체크합니다. 카드에는 형식마다 어떤 방식으로 읽는지(처리 방식)도 함께 표시됩니다.

형식상태추가 준비물
PPTX서버 이미지에 LibreOffice 포함
PDF없음
HWP / HWPX서버 이미지에 rhwp 0.7.19 포함
DOCX / DOCM서버 이미지에 LibreOffice 포함
XLSX / XLSM서버 이미지에 LibreOffice 포함
C7

SharePoint 명령(SPFx) 배포

1. 설정 값 치환 — 아래 파일의 자리표시자를 실제 값으로 바꿉니다.

파일바꿀 값
sharepoint\search-enhancement-command\src\extensions\searchEnhancement\SearchEnhancementCommandSet.manifest.jsonapiBaseUrl, apiResource
sharepoint\search-enhancement-command\sharepoint\assets\elements.xmlapiBaseUrl, apiResource
sharepoint\search-enhancement-command\config\package-solution.jsonwebApiPermissionRequests.resource
  • apiBaseUrl = 트랙 B의 SERVICE_WEB_URI
  • apiResource = Ingest용 앱 등록의 App ID URI (예: api://crewmeal-ingest)

2. 패키지 빌드 (Node.js 22.14 이상 23 미만 필요)

cd $HOME\CrewMeal\sharepoint\search-enhancement-command
npm install
npm run build
npm run test:unit

결과물: sharepoint\solution\search-enhancement-command.sppkg

3. App Catalog 업로드 → 앱을 테스트 사이트에만 설치 (테넌트 전체 배포는 사용하지 않습니다.)

4. SharePoint 관리 센터 → 고급 → API 액세스 에서 SPFx가 요청한 권한을 승인합니다.

5. CORS / 인증 설정 — SPFx는 SharePoint 페이지에서 API를 호출하므로 허용 오리진이 필요합니다.

cd $HOME\CrewMeal
azd env set CREWMEAL_INGEST_ALLOWED_ORIGINS "https://contoso.sharepoint.com"
azd env set CREWMEAL_INGEST_REQUIRE_AUTH    "true"
azd env set CREWMEAL_INGEST_AUDIENCE        "api://crewmeal-ingest"
azd env set CREWMEAL_INGEST_ALLOWED_APP_IDS "<SPFx가 사용하는 앱 ID>"
azd env set CREWMEAL_M365_SITE_ID   "<C-2의 SITE_ID>"
azd env set CREWMEAL_M365_DRIVE_ID  "<C-2의 DRIVE_ID>"
azd env set CREWMEAL_M365_LIST_ID   "<C-2의 LIST_ID>"
azd env set CREWMEAL_M365_SITE_URL  "<C-2의 SITE_URL>"
azd up
C8

실사용 테스트

  1. SharePoint 문서 라이브러리에서 PPT 파일 1개를 선택합니다.
  2. 명령 모음에 「코파일럿을 위해 검색강화」 버튼이 나타납니다.
문서 상태보이는 버튼
미등록코파일럿을 위해 검색강화
실패 / 원본 갱신됨검색강화 다시 시도
대기 · 처리 · 완료검색강화 삭제
  1. 버튼을 누르면 상태 열이 QueuedProcessingReady 로 바뀝니다.
  2. CrewmealSearchStatusLink 열의 링크를 눌러 진행 상황을 실시간 확인합니다.
💡 버튼이 안 보인다면 버튼은 편집 권한이 있는 사용자가 지원 문서 1개만 선택했을 때 나타납니다. 여러 개를 선택하면 보이지 않습니다.
C9

검색 · Copilot 반영 확인

컬럼 방식은 SharePoint 검색 인덱스에 반영되어야 Copilot이 참조합니다.

  1. 라이브러리 설정 → 고급 설정 → 문서 라이브러리 다시 인덱싱 실행
  2. 인덱싱은 수 분~수 시간 걸립니다 (테넌트 상황에 따라 다름).
  3. 생성된 검색 콘텐츠에만 존재하는 고유 문자열(canary) 로 Microsoft Search를 검색해 원본 문서가 결과에 나오는지 확인합니다.
  4. /admin/settings?tab=publication컬럼 검색 준비 카드에 canary와 원본 URL을 기록합니다.
  5. 같은 문서(또는 라이브러리)로 범위를 지정한 Copilot에게 질문해서 canary 내용을 근거로 답하는지 확인합니다.
✅ 트랙 C 합격 기준 SharePoint 버튼 → 상태 Ready → 검색에서 canary 발견 → 범위 지정 Copilot이 강화된 내용을 근거로 답변.

5

테스트 시나리오와 합격 기준

고객사 검증 회의에서 그대로 쓸 수 있는 체크리스트입니다. 체크 상태는 자동 저장됩니다.

#시나리오조작합격 기준트랙
1기본 텍스트 추출텍스트 위주 PPT 업로드원문 문장이 결과 HTML에 보존됨A
2표 추출표가 있는 PPT표의 행/열 값이 누락 없이 재현A
3차트 해석막대/선 차트 슬라이드그래프가 무엇을 뜻하는지 문장으로 설명B
4간트차트일정표 슬라이드작업명·기간·순서가 문장으로 설명B
5PDF 처리스캔 아닌 PDF페이지별 내용이 추출됨B
6HWP/HWPX한글 문서본문·표·머리말/꼬리말 추출B
7대용량50장 이상 덱실패 없이 완료, 소요 시간 기록B
8재작업상태 페이지 → 다시 실행새 결과로 갱신B
9피드백 반영상태 페이지 → 코멘트 후 재작업코멘트가 반영된 결과B
10원본 무결성처리 후 원본 다운로드원본 파일이 변경되지 않음C
11권한권한 없는 사용자로 접근상태 페이지 접근 차단C
12삭제검색강화 삭제색인/컬럼에서 제거, 상태 NotEnabledC
13검색 반영canary 검색원본 문서가 결과에 노출C
14Copilot 답변범위 지정 질의강화 내용을 근거로 답변C
15비용 확인관리자 대시보드문서별 토큰·추정 비용 표시B

6

환경 변수 총정리

필수

변수설명예시
CREWMEAL_M365_TENANT_IDEntra 테넌트 IDGUID
CREWMEAL_M365_CLIENT_ID앱 클라이언트 IDGUID
CREWMEAL_M365_CLIENT_SECRET앱 시크릿(비밀)
CREWMEAL_M365_SITE_IDSharePoint 사이트 IDhost,guid,guid
CREWMEAL_M365_DRIVE_ID문서 라이브러리 드라이브 ID
CREWMEAL_M365_LIST_ID목록 IDGUID
CREWMEAL_M365_SITE_URL사이트 URLhttps://.../sites/...
CREWMEAL_ADMIN_KEY관리자 포털 키(비밀)
CREWMEAL_WEB_SESSION_SECRET세션 서명 키(비밀)

선택 / 튜닝

변수기본값설명
PPTX_ANALYSIS_TIERvisionvision(고품질) / text_ocr(무비용)
PPTX_OCR_ENABLEDtrue저품질 티어에서 이미지 OCR 사용
SLIDE_IMAGE_MODELgpt-5.6-lunagpt-5.2, gpt-5-mini 선택 가능
SLIDE_IMAGE_DEPLOYMENTgpt-5-6-luna-testFoundry 배포 이름
SLIDE_IMAGE_RENDER_DPI144페이지 렌더 해상도
SLIDE_IMAGE_MAX_WORKERS2동시 분석 슬라이드 수
CREWMEAL_INGEST_REQUIRE_AUTHtrueIngest API 토큰 검증
CREWMEAL_STATUS_REQUIRE_AUTH위 값과 동일상태 페이지 Entra 로그인
CREWMEAL_INGEST_ALLOWED_ORIGINS(없음)CORS 허용 오리진(CSV)
CREWMEAL_ARTIFACT_BACKEND자동database / blob / 로컬 파일
SOFFICE_PATH자동 탐색로컬 LibreOffice 경로
RHWP_PATH자동 탐색로컬 rhwp 경로
CREWMEAL_MIP_SDK_CLI(없음)MIP 복호화 CLI (README 참고)

7

문제 해결

증상원인해결
ConfigurationError: Missing Microsoft 365 settings워커 실행 창에 M365 변수 없음같은 창에서 변수 설정 후 재실행 (트랙 A는 더미 값 사용)
웹 시작 시 CREWMEAL_WEB_SESSION_SECRET must be set인증 켠 상태에서 세션 키 없음세션 시크릿 설정 또는 CREWMEAL_INGEST_REQUIRE_AUTH=false
로그인 시 AADSTS50011리디렉션 URI 미등록B-5 수행 ({웹주소}/auth/callback 추가 + ID 토큰 허용)
웹 앱이 기동 실패 (ConfigurationError)CREWMEAL_STATUS_REQUIRE_AUTH=true 인데 SSO 자격증명 없음M365 변수 3종 설정 또는 해당 값을 false
SPFx 버튼에서 Failed to fetchCORS 미설정CREWMEAL_INGEST_ALLOWED_ORIGINS 에 SharePoint 오리진 추가 후 재배포
Graph 403 오류사이트 권한 미부여scripts\grant_test_site_permission.ps1 실행
스크립트가 “Missing user environment variable”$env: 로만 설정C-3처럼 User 범위로 설정 후 새 창에서 실행
azd up 이 쿼터 오류로 실패모델 TPM 부족infra/modules/foundry.bicep 의 capacity 값 축소
리전 오류locationeastus2 로 고정infra/main.bicep@allowed 목록 수정
상태가 계속 Queued워커 미실행로컬은 cli once, Azure는 워커 앱 상태 확인
결과에 그림 설명이 없음저품질 티어/admin/settings?tab=analysis 에서 분석 티어를 고품질로 변경 후 재작업
한글 OCR이 깨짐기본 OCR 모델은 한국어 미지원로컬은 PPTX_OCR_REC_MODEL/PPTX_OCR_REC_KEYS 지정, 컨테이너는 --build-arg ENABLE_LOW_TIER_OCR=1 로 한국어 모델 포함해 빌드
MIP 문서 처리 실패복호화 미구성README 「MIP 복호화」 참고, 관리 포털의 준비 마법사로 점검
검색에 반영되지 않음재인덱싱 안 함라이브러리 설정에서 수동 재인덱싱 후 대기

로그 확인

# 웹 앱 로그
az containerapp logs show -g <리소스그룹> -n <웹앱이름> --tail 100
# 워커 로그
az containerapp logs show -g <리소스그룹> -n <워커앱이름> --tail 100

8

비용 관리와 정리

  • 문서별 추정 비용은 관리자 대시보드와 상태 페이지에 표시됩니다.
  • 비용을 아예 쓰지 않으려면 분석 티어를 저품질(text_ocr) 로 두세요.
  • PoC 구성은 야간 비용 절감을 위해 PostgreSQL이 자동 정지되고, 매일 아침 (한국시간 기준, 기본 07시) Logic App이 자동 재시작합니다. 워커는 DB 연결이 끊긴 동안 재시도하며 스스로 복구합니다.
⚠️ 테스트 종료 후 전체 삭제 — 되돌릴 수 없습니다 아래 명령은 이 환경에서 만든 Azure 리소스를 모두 지웁니다.
cd $HOME\CrewMeal
azd down --purge --force

추가 정리:

  • SharePoint 테스트 사이트에서 앱 제거, App Catalog에서 패키지 삭제
  • Entra 앱 등록 삭제
  • 커넥터 방식이었다면 Copilot 커넥터 연결 삭제

9

보안 · 데이터 취급

고객사 보안 검토에서 자주 나오는 질문에 대한 답입니다.

  • 원본 문서는 임시 폴더에만 내려받고 처리 후 삭제합니다.
  • 원본 파일 바이너리는 수정하지 않습니다.
  • 원본 문서 · PDF · PNG · HTML 본문과 비밀 값은 로컬 상태 DB에 저장하지 않습니다.
  • Azure OpenAI · Blob 접근은 API 키 없이 관리 ID(DefaultAzureCredential)로 인증합니다.
  • SharePoint 접근 권한은 Sites.Selected지정한 사이트에만 부여됩니다.
  • 컬럼 방식은 원본 문서의 권한을 그대로 따르므로 권한 복제가 없습니다.
  • PoC는 공개 엔드포인트를 사용하므로 기밀 문서를 넣지 마세요.

10

도움 요청 시 함께 보내주세요

문제가 해결되지 않으면 아래 정보를 정리해 전달해 주세요. 훨씬 빨리 원인을 찾을 수 있습니다.

  1. 어느 트랙(A/B/C)의 몇 번 단계인지
  2. 실행한 명령과 화면에 나온 오류 메시지 전문
  3. azd env get-values 결과 (비밀 값은 반드시 가리고)
  4. 상태 페이지의 실패 단계 이름과 메시지
  5. 컨테이너 앱 로그 마지막 100줄
CrewMeal — Copilot 검색 콘텐츠 강화 · MIT License 문서 최종 수정: 2026-07-25