이 가이드는 Strapi v5 신규 설치 기준입니다. v4 컨테이너는 중지만 해두고, v5를 완전히 새로 셋업한 뒤 WordPress 역동기화 워크플로우로 기존 글을 가져옵니다.
Strapi v5란 — v4와 핵심 차이점
| 항목 | Strapi v4 | Strapi v5 |
|---|---|---|
| 엔트리 식별자 | id (숫자, 예: 42) | documentId (문자열, 예: “a1b2c3def456”) |
| API 응답 구조 | { data: { id, attributes: { title, ... } } } | { data: { documentId, title, ... } } (flat) |
| coverImage URL | data.attributes.coverImage.data.attributes.url | data.coverImage.url |
| PUT 경로 | /api/blog-posts/{id} (숫자) | /api/blog-posts/{documentId} (문자열) |
| Meilisearch 패키지 | @strapi/plugin-meilisearch | strapi-plugin-meilisearch (@ 없음) |
| Node.js 최소 버전 | v18 | v20 |
| Content-Type Builder | production 모드에서도 사용 가능 | development 모드에서만 사용 가능 |
n8n에서 가장 많이 바뀌는 부분
// ── v4 방식 ────────────────────────────────── const entry = $json.body.entry; const blogPostId = entry.id; // 숫자 42 const coverUrl = $json.data.attributes .coverImage.data.attributes.url; // 중첩 attributes // PUT URL: /api/blog-posts/42 // ── v5 방식 ────────────────────────────────── const entry = $json.body.entry; const blogPostDocId = entry.documentId; // 문자열 "a1b2c3def456" const coverUrl = $json.data.coverImage.url; // flat — 중첩 없음 // PUT URL: /api/blog-posts/a1b2c3def456
REST API 경로(/api/blog-posts), Bearer 인증, Webhook 시크릿, n8n HTTP Request 노드 방식, WordPress REST API 연동, ComfyUI 이미지 생성 — 이 모든 것은 v4와 동일하게 동작합니다. 바뀌는 건 식별자(id→documentId)와 응답 파싱 경로(attributes 제거) 두 가지뿐입니다.
기존 v4 중지 & v5 신규 설치
① v4 컨테이너 중지 (데이터 보존)
docker stop strapi
docker ps | grep strapi
# 아무것도 안 나오면 중지 완료② v5 프로젝트 디렉토리 생성
# strapi-v5: 애플리케이션 코드 (git으로 관리) mkdir -p /mnt/data/02_automation/strapi-v5 # strapi-postgres: DB 데이터만 별도 분리 (매우 중요) mkdir -p /mnt/data/02_automation/strapi-postgres/data cd /mnt/data/02_automation/strapi-v5
기존 가이드의 - /mnt/data/02_automation/strapi-v5:/opt/app 마운트는 컨테이너 재기동 시 호스트의 strapi-v5 디렉토리가 /opt/app 전체를 덮어씌워 node_modules, 빌드 결과물, 설정이 모두 초기화됩니다. 올바른 방법은 아래와 같이 uploads 폴더만 마운트합니다.
③ Strapi v5 프로젝트 스캐폴딩 (최초 1회)
docker run --rm -it \
-v /mnt/data/02_automation/strapi-v5:/app \
-w /app \
node:20-bookworm-slim \
bash -c "
apt-get update -qq && apt-get install -y python3 make g++ &&
npx create-strapi-app@5 . \
--no-run \
--skip-cloud \
--ts \
--dbclient=postgres \
--dbhost=strapi-pg-db \
--dbport=5432 \
--dbname=strapi_db \
--dbusername=strapi \
--dbpassword=strapi1234 (REWRwerwer\!0101 - 느낌표 넣고싶을 땐 \로 구분)
"
# 완료 후 파일 확인 — package.json, src/, config/ 가 생성되어야 함
ls /mnt/data/02_automation/strapi-v5/④ Dockerfile 작성
FROM node:20-bookworm-slim AS build WORKDIR /opt/app RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM node:20-bookworm-slim WORKDIR /opt/app RUN apt-get update && apt-get install -y python3 make g++ && rm -rf /var/lib/apt/lists/* COPY --from=build /opt/app ./ EXPOSE 1337 CMD ["npm", "run", "start"]
⑤ docker-compose.yml — 올바른 볼륨 설정
strapi-pg-db:
image: postgres:16-alpine
container_name: strapi-pg-db
restart: unless-stopped
environment:
POSTGRES_USER: strapi
POSTGRES_PASSWORD: ${STRAPI_DB_PASSWORD}
POSTGRES_DB: strapi_db # DB 이름 strapi_db 로 통일
volumes:
# DB 데이터는 별도 디렉토리에 분리 보관
- /mnt/data/02_automation/strapi-postgres/data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U strapi -d strapi_db"]
interval: 10s
timeout: 5s
retries: 5
networks:
- ai-common-net
strapi:
build:
context: /mnt/data/02_automation/strapi-v5
dockerfile: Dockerfile
container_name: strapi
restart: unless-stopped
ports:
- "1337:1337"
environment:
NODE_ENV: production # 스키마 확정 후 production 사용
HOST: 0.0.0.0
PORT: 1337
APP_KEYS: ${STRAPI_APP_KEYS}
JWT_SECRET: ${STRAPI_JWT_SECRET}
ADMIN_JWT_SECRET: ${STRAPI_ADMIN_JWT_SECRET}
API_TOKEN_SALT: ${STRAPI_API_TOKEN_SALT}
DATABASE_CLIENT: postgres
DATABASE_HOST: strapi-pg-db
DATABASE_PORT: 5432
DATABASE_NAME: strapi_db # POSTGRES_DB 값과 반드시 동일
DATABASE_USERNAME: strapi
DATABASE_PASSWORD: ${STRAPI_DB_PASSWORD}
DATABASE_SSL: "false"
volumes:
# ✅ uploads 폴더만 마운트 — 전체 /opt/app 마운트 금지
- /mnt/data/02_automation/strapi-v5/public/uploads:/opt/app/public/uploads
depends_on:
strapi-pg-db:
condition: service_healthy
networks:
- ai-common-net/mnt/data/02_automation/strapi-v5:/opt/app처럼 소스 디렉토리 전체를 마운트하면, 컨테이너 기동 시 호스트 디렉토리가 컨테이너 내부 /opt/app을 덮어씌웁니다. Dockerfile에서 빌드된 node_modules와 dist 폴더가 모두 날아가 애플리케이션이 동작하지 않습니다. 유저 업로드 파일(uploads)만 호스트에 영구 보관하고, 나머지는 이미지 빌드 결과물을 그대로 사용합니다.
⑥ .env 시크릿 키 생성 및 추가
# 아래 명령어 실행 후 각 값을 .env에 직접 붙여넣기 (변수 치환 오류 방지)
echo "STRAPI_DB_PASSWORD=$(openssl rand -base64 24)"
echo "STRAPI_APP_KEYS=$(openssl rand -base64 32),$(openssl rand -base64 32)"
echo "STRAPI_API_TOKEN_SALT=$(openssl rand -base64 24)"
echo "STRAPI_ADMIN_JWT_SECRET=$(openssl rand -base64 24)"
echo "STRAPI_JWT_SECRET=$(openssl rand -base64 24)"⑦ 빌드 & 실행
docker compose build strapidocker compose up -d strapi-pg-db strapidocker logs -f strapi → Project is running at http://localhost:1337 메시지가 나오면 성공http://192.168.1.253:1337/admin 접속초기 설정 — Admin 계정 & 기본 구성
→ Enable sign-ups 토글 OFF → Save
NODE_ENV=development 일 때만 사용 가능합니다.docker-compose.yml에서
NODE_ENV: development로 변경 후 재시작합니다.스키마 설계 시: NODE_ENV=development → Content-Type Builder 사용 → 스키마 저장
운영 복귀 시: NODE_ENV=production으로 변경 → docker compose build strapi → docker compose up -d strapi
스키마를 수정한 뒤에는 반드시 이미지를 다시 빌드해야 변경사항이 production에 반영됩니다.
Content-Type Builder — Blog Post 스키마 설계
Content-Type Builder 화면에서 보이는 이름과 schema.json의 실제 타입명이 다릅니다.
| Admin UI에서 선택하는 이름 | 세부 선택 | schema.json 타입 | 용도 |
|---|---|---|---|
| Text | Short text 선택 | string | 제목, 짧은 단일 행 텍스트 |
| Text | Long text 선택 | text | 요약문, 여러 줄 텍스트 |
| Rich Text | Blocks 선택 | blocks | 본문 (블록 에디터) |
| UID | Attached field 선택 | uid | 슬러그 (자동 생성+중복 방지) |
| Number | Integer 선택 | integer | 숫자 값 |
| Media | Single media 선택 | media | 이미지 1장 |
| Enumeration | 값 목록 입력 | enumeration | 정해진 값 중 하나 선택 |
| Component | 컴포넌트 선택 | component | 재사용 가능한 필드 묶음 |
필드를 추가할 때 두 가지 이름을 설정합니다.
Name(이름): 반드시 영문 소문자+카멜케이스로 입력. 이것이 API 필드명이 됩니다. (예: wordpressPostId)
Label(표시 이름): Admin UI에서 보이는 이름으로, 한글도 가능합니다. (예: WordPress 포스트 ID)
영문 Name으로 생성 후 Advanced settings에서 Label만 한글로 변경하면 됩니다.
Blog Post 컬렉션 기본 정보
진입: Admin 패널 좌측 사이드바 → Content-Type Builder → + Create new collection type
| 항목 | 값 |
|---|---|
| Display name | Blog Post |
| API ID (단수형) | blog-post |
| API ID (복수형) | blog-posts |
| Draft/Publish | ✅ 활성화 (반드시 체크) |
필드 전체 목록 — 실제 UI 기준
| 필드 Name (영문, API명) | UI 타입 선택 | 세부 옵션 | 설명 |
|---|---|---|---|
title | Text | Short text · Required 체크 | 글 제목 |
slug | UID | Attached to: title · Required 자동 · Unique 자동 | WP 퍼머링크. Finish 후 Save 클릭 |
content | Rich Text | Blocks 선택 · Required 체크 | 본문 블록 에디터 |
excerpt | Text | Long text 선택 | 요약문 (여러 줄 가능) |
category | Enumeration | 값 목록 입력 · Required 체크 | 아래 Enum 값 참고 |
subCategory | Enumeration | 값 목록 입력 · Required 체크 | 아래 Enum 값 참고 |
coverImage | Media | Single media · 이미지 타입만 허용 | 대표 이미지 (ComfyUI 자동 생성) |
wordpressPostId | Number | Integer 선택 | WP 역기록용 포스트 ID |
imageMeta | Component | imageMeta 컴포넌트 | 이미지 메타 (아래 컴포넌트 참고) |
seoMeta | Component | seoMeta 컴포넌트 | SEO / Rank Math 데이터 |
socialMeta | Component | socialMeta 컴포넌트 | SNS 발행용 텍스트 |
Enumeration 값 — 영문 소문자만 허용
Enumeration의 값(Value)은 반드시 영문 소문자로 입력해야 합니다. 한글을 입력하면 Strapi가 내부적으로 처리할 수 없어 ValidationError 400이 발생합니다. Label(표시 이름)만 한글로 설정하세요.
ai-lab finance home-lab
local-ai workflow music-gen image-media-gen prompt daily-stock-reports investment-automation stock-etf nas devops security server-network
컴포넌트 구성
| 컴포넌트 | 필드 Name | UI 타입 | 설명 |
|---|---|---|---|
| imageMeta | fileName | Text (Short) | 영문 파일명 |
altText | Text (Short) | 이미지 대체 텍스트 | |
imageTitle | Text (Short) | 이미지 title 속성 | |
caption | Text (Long) | 이미지 캡션 | |
description | Text (Long) | 이미지 설명 | |
| seoMeta | seoTitle | Text (Short) | Rank Math SEO 제목 |
focusKeyword | Text (Short) | 포커스 키워드 | |
secondaryKeywords | Text (Long) | 보조 키워드 목록 | |
metaDescription | Text (Long) | 메타 설명 (160자 이내) | |
categoryPath | Text (Short) | WP 카테고리 슬러그 경로 | |
| socialMeta | snsTags | Text (Long) | SNS 해시태그 |
snsSummary | Text (Long) | SNS 게시글 본문 | |
snsComment | Text (Long) | SNS 댓글 (링크용) | |
tistorySummary | Text (Long) | 티스토리 요약 |
Content-Type Builder → Blog Post → + Add another field → Component → Create a new component
컴포넌트 이름: imageMeta / 카테고리: shared → Finish → 위 필드들을 추가 → Save
seoMeta, socialMeta도 동일한 방법으로 생성합니다.
API 토큰 발급 & Webhook 설정
① API 토큰 발급 — n8n 연동용
n8n-pipeline· Token type: Full access
· Token duration: Unlimited
→ Header Auth 선택 → Name:
Strapi v5 Bearer→ Name 필드:
Authorization, Value 필드: Bearer 복사한토큰값② Webhook 설정 — 시크릿 전체 과정
Strapi가 Webhook을 보낼 때 HTTP 헤더에 시크릿 값을 포함합니다. n8n이 이 헤더를 검증해 Strapi에서 보낸 정상 요청인지 확인합니다. 이 과정이 없으면 누구나 n8n Webhook URL로 가짜 요청을 보낼 수 있습니다.
openssl rand -hex 16
# 예: a3f8d2c1b9e4f7a0c5d2e8f1b6a3c9d4· Name:
n8n-publish· URL:
http://n8n:5678/webhook/strapi-publish· Headers → Add a header
— Header Name:
X-Webhook-Secret— Header Value: 위에서 생성한 시크릿 값 붙여넣기
· Events → Entry → Publish ✅ 체크
· Save
· Left Value:
{{ $headers['x-webhook-secret'] }}· Operator: equals
· Right Value: 위 시크릿 문자열 직접 입력
③ Blog Post API 공개 권한 설정
WordPress 역동기화 워크플로우가 인증 없이 조회할 수 있도록 설정합니다.
WordPress 카테고리 & Rank Math 설정
Strapi Enum ↔ WordPress 카테고리 슬러그 매핑
| Strapi category | Strapi subCategory | WP 카테고리 슬러그 | WP 표시명 |
|---|---|---|---|
| ai-lab | local-ai | local-ai | 로컬 AI |
| ai-lab | workflow | workflow | 워크플로우 |
| ai-lab | music-gen | music-gen | AI 음악 |
| ai-lab | image-media-gen | image-media-gen | AI 이미지 |
| ai-lab | prompt | prompt | 프롬프트 |
| finance | daily-stock-reports | daily-stock-reports | 일일 시황 |
| finance | investment-automation | investment-automation | 투자 자동화 |
| finance | stock-etf | stock-etf | 주식·ETF |
| home-lab | nas | nas | NAS |
| home-lab | devops | devops | DevOps |
| home-lab | security | security | 보안 |
| home-lab | server-network | server-network | 서버·네트워크 |
WordPress functions.php — Rank Math REST API 확장
// Rank Math 메타 필드를 REST API에서 읽기/쓰기 가능하도록 등록
add_action('rest_api_init', function() {
$meta_fields = [
'rank_math_title',
'rank_math_description',
'rank_math_focus_keyword',
'rank_math_secondary_keyword',
'rank_math_primary_category',
];
foreach ($meta_fields as $field) {
register_post_meta('post', $field, [
'show_in_rest' => true,
'single' => true,
'type' => ($field === 'rank_math_primary_category') ? 'integer' : 'string',
]);
}
});n8n 워크플로우 Import & Credential 설정
n8n → 좌측 사이드바 → Workflows → 우측 상단 + New Workflow → Import from File로 가져옵니다. 아래 표에 따라 Credential과 주요 설정값만 채우면 바로 동작합니다.
| 노드 번호 | 설정 항목 | 입력값 |
|---|---|---|
| 1. Webhook | Webhook URL 확인 | /webhook/strapi-publish |
| 3. IF: 시크릿 검증 | Left Value | {{ $headers['x-webhook-secret'] }} |
| 3. IF: 시크릿 검증 | Right Value | STEP 05 ② 에서 설정한 시크릿 문자열 |
| 5. ComfyUI | URL | http://comfyui:8188/prompt |
| 5. ComfyUI | ckpt_name 값 | 실제 설치된 모델 파일명으로 교체 필수 |
| 10. Strapi Media 업로드 | Credential | Strapi v5 Bearer |
| 11. Strapi coverImage | Credential | Strapi v5 Bearer |
| 12, 14, 15, 16, 20, 22 | Credential | WordPress Basic Auth |
| 17. Strapi 역기록 | Credential | Strapi v5 Bearer |
5번 노드의 ckpt_name 기본값이 설정되어 있습니다. R730 ComfyUI에 실제로 설치된 모델 파일명과 정확히 일치해야 합니다.
설치된 모델 목록 확인: http://192.168.1.253:8188/object_info → CheckpointLoaderSimple → ckpt_name
v4 vs v5 n8n 코드 변경 상세
기존 v4 워크플로우에서 v5로 업그레이드할 때 반드시 수정해야 하는 부분입니다.
노드 4 — 식별자 추출 (핵심 변경)
// ❌ v4 방식 — 숫자 id const blogPostId = entry.id; // ✅ v5 방식 — 문자열 documentId const blogPostDocId = entry.documentId;
노드 11 — coverImage 연결 및 URL 파싱
// ❌ v4 — PUT URL http://strapi:1337/api/blog-posts/{{ $('4_extract').item.json.blogPostId }}?populate=coverImage // ✅ v5 — PUT URL (documentId 사용) http://strapi:1337/api/blog-posts/{{ $('4_extract').item.json.blogPostDocId }}?populate=coverImage // ❌ v4 — coverImage URL 추출 (중첩 attributes) http://strapi:1337{{ $('11_cover').item.json.data.attributes.coverImage.data.attributes.url }} // ✅ v5 — coverImage URL 추출 (flat) http://strapi:1337{{ $('11_cover').item.json.data.coverImage.url }}
노드 17 — Strapi 역기록 URL
// ❌ v4 http://strapi:1337/api/blog-posts/{{ $('4_extract').item.json.blogPostId }} // ✅ v5 http://strapi:1337/api/blog-posts/{{ $('4_extract').item.json.blogPostDocId }}
Obsidian + SFTP → Strapi v5 초안 연동
Obsidian에서 작성한 마크다운을 ready/ 폴더로 이동하면 n8n이 SFTP로 읽어서 Strapi v5에 Draft로 자동 생성합니다.
SFTP 다운로드 → frontmatter 파싱 → Strapi POST 요청 구조는 동일합니다. Draft 생성(POST만)에서는 응답 파싱이 필요 없으므로 실질적으로 변경 사항이 없습니다.
Obsidian frontmatter 템플릿 (v5 기준)
--- title: category: home-lab subCategory: devops excerpt: seoTitle: focusKeyword: secondaryKeywords: metaDescription: categoryPath: wpTags: snsTags: fileName: altText: imageTitle: caption: description: snsSummary: snsComment: tistorySummary: --- <div class="dp"> <p>여기부터 본문 작성...</p> </div>
한 글자라도 다르면 ValidationError 400이 발생합니다. STEP 04의 Enum 값 목록을 참고해 정확히 입력하세요. 특히 stock_etf가 아닌 stock-etf(하이픈)으로 통일되어 있습니다.
Meilisearch 플러그인 연동
v4: @strapi/plugin-meilisearch (존재하지 않음)
v5: strapi-plugin-meilisearch (앞에 @ 없음, 소문자 전체)
① 플러그인 설치
docker exec -it strapi sh -c "cd /opt/app && npm install strapi-plugin-meilisearch" docker compose restart strapi
② 플러그인 설정 파일
export default ({ env }: { env: (key: string) => string }) => ({
meilisearch: {
config: {
host: 'http://meilisearch:7700',
apiKey: env('MEILI_MASTER_KEY'),
},
},
});docker-compose.yml의 strapi 서비스 environment에 MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}를 추가하고, .env 파일에도 해당 값을 넣어주세요.
③ Admin에서 인덱싱 설정
WordPress → Strapi v5 역동기화
이미 WordPress에 발행된 글을 Strapi v5 Draft로 가져와 중앙 관리합니다. n8n에서 수동으로 한 번만 실행합니다.
{
"data": {
"title": "글 제목",
"slug": "geul-jeomok",
"content": "본문 HTML",
"excerpt": "요약",
"category": "home-lab",
"subCategory": "devops",
"wordpressPostId": 123
}
}
# v4와 동일한 Body 구조 — v5에서도 POST 요청 방식은 동일합니다실전 발행 테스트 — 처음부터 끝까지
① Strapi Admin → Content Manager → Blog Posts → + Create new entry
→ 모든 필드 채우기 (title, category, subCategory, excerpt, seoMeta, socialMeta)
→ coverImage는 비워둠 (ComfyUI가 자동 생성)
→ Draft 저장 → 내용 확인 후 Publish 버튼 클릭
↓
② Webhook 발생 → n8n 1번 노드(Webhook) 수신
↓
③ n8n 파이프라인 자동 진행:
3번: X-Webhook-Secret 헤더 시크릿 검증 ✅
4번: entry.documentId 추출 (v5 핵심)
5~9번: ComfyUI 대표 이미지 생성
10번: Strapi에 이미지 파일 업로드
11번: coverImage 연결 (PUT by documentId)
12~16번: WordPress에 글 + 이미지 발행
17번: Strapi에 WP Post ID 역기록 (PUT by documentId)
↓
④ 확인:
WordPress agibop.com → 새 글 발행 확인
Strapi Blog Post → wordpressPostId 필드에 WP ID 기록됐는지 확인중간 단계 API 확인 명령어
# v5 API 응답 구조 확인 (documentId, flat 구조 눈으로 확인) curl -s "http://192.168.1.253:1337/api/blog-posts?populate=coverImage" \ -H "Authorization: Bearer ${STRAPI_API_TOKEN}" | python3 -m json.tool | head -40 # n8n 실행 로그 확인 docker logs -f n8n --tail 50
트러블슈팅 & 운영 체크리스트
빠른 점검 순서
실패한 실행을 클릭 → 어느 노드에서 실패했는지, 정확한 에러 메시지 확인
에러 메시지 없이는 원인을 추정만 하게 됩니다. 항상 이 탭 먼저 확인하세요.
curl -X POST http://192.168.1.253:5678/webhook/strapi-publish \
-H "Content-Type: application/json" \
-H "X-Webhook-Secret: 설정한_시크릿값" \
-d '{
"event": "entry.publish",
"model": "blog-post",
"uid": "api::blog-post.blog-post",
"entry": {
"documentId": "test-document-id-abc123",
"id": 1,
"title": "테스트 발행",
"slug": "test-publish"
}
}'
# 성공 시 n8n Executions 탭에 실행 기록이 생성됩니다# Strapi Admin → Settings → Webhooks → 해당 Webhook → Trigger 버튼 # 또는 Strapi API로 직접 테스트 curl -X POST "http://192.168.1.253:1337/api/blog-posts/문서ID/actions/publish" \ -H "Authorization: Bearer ${STRAPI_API_TOKEN}" \ -H "Content-Type: application/json"
에러 유형별 해결법
| 에러 | 원인 | 해결 |
|---|---|---|
ValidationError 400 (category) | Enum 값 불일치 또는 한글 입력 | STEP 04 Enum 값 목록과 정확히 대조 |
coverImage.url is undefined | v4 응답 경로 사용 중 | data.coverImage.url (flat)으로 변경 |
PUT 404 (documentId) | 숫자 id 대신 사용 | 노드 4에서 entry.documentId 추출 확인 |
npm E404 (@strapi/plugin-meilisearch) | 잘못된 패키지명 | strapi-plugin-meilisearch (@ 없음) |
| Webhook 미수신 | n8n 워크플로우 비활성 | 워크플로우 Active 토글 ON 확인 |
| 시크릿 검증 실패 (3번 노드) | 헤더명 대소문자 불일치 | n8n에서 $headers['x-webhook-secret'] (소문자) |
| 컨테이너 재기동 후 작동 안 함 | 볼륨 전체 마운트로 코드 덮어씌워짐 | STEP 02 볼륨 설정 재확인 — uploads만 마운트 |
| 이미지 404 (Strapi 업로드 후) | uploads 볼륨 미마운트 | docker-compose.yml uploads 볼륨 확인 |
Content-Type Builder 메뉴 없음 | production 모드에서 접속 | NODE_ENV=development로 변경 후 재시작 |
| DB 연결 오류 | DATABASE_NAME과 POSTGRES_DB 불일치 | 둘 다 strapi_db로 통일 확인 |
최종 운영 체크리스트
- ✓Strapi Admin 접속:
http://192.168.1.253:1337/admin - ✓볼륨 설정: uploads 폴더만 마운트, 전체 /opt/app 마운트 없음
- ✓DB 이름: POSTGRES_DB와 DATABASE_NAME 모두
strapi_db로 동일 - ✓Blog Post 스키마: 11개 필드 + 3개 컴포넌트 정상 생성
- ✓NODE_ENV: 스키마 확정 후 production으로 복귀, 이미지 재빌드
- ✓API 토큰: n8n Credential에 Bearer 형식으로 등록
- ✓Webhook: X-Webhook-Secret 헤더 설정, n8n 3번 노드 검증 일치
- ✓n8n: 워크플로우 Active ON, Executions 탭으로 동작 확인
- ✓Meilisearch 플러그인:
strapi-plugin-meilisearch, Blog Post 인덱싱 활성화 - ✓실전 테스트: Draft → Publish → n8n 실행 → WP 발행 → wordpressPostId 역기록 확인
볼륨 버그 수정 · UI 메뉴명 정확화 · Webhook 시크릿 완전 가이드 포함



