Strapi v5 완전 정복 — 신규 설치부터 n8n WordPress 자동 발행 파이프라인까지 2026

-

Strapi v5 헤드리스CMS Docker n8n WordPress자동발행 실설치검증
작성일2026년 7월 8일
카테고리홈랩 > DevOps
난이도고급
소요시간4~6시간
버전Strapi v5 · n8n 2.x · Node.js 20
R730 실설치 검증
Strapi v5는 v4 대비 API 응답 구조가 전면 개편된 메이저 업그레이드입니다. 이 가이드는 v5 신규 설치부터 Blog Post 스키마 설계(실제 UI 기준), API 토큰·Webhook·n8n 23노드 파이프라인·ComfyUI 대표 이미지·WordPress 자동 발행· Meilisearch 플러그인까지 전체 흐름을 한 번에 다룹니다. 기존 가이드의 UI 메뉴명 오류, 볼륨 설정 버그, Webhook 설정 누락을 모두 수정한 최종본입니다.
⚠️
v4 → v5 마이그레이션이 아닙니다

이 가이드는 Strapi v5 신규 설치 기준입니다. v4 컨테이너는 중지만 해두고, v5를 완전히 새로 셋업한 뒤 WordPress 역동기화 워크플로우로 기존 글을 가져옵니다.

STEP01

Strapi v5란 — v4와 핵심 차이점

항목Strapi v4Strapi v5
엔트리 식별자id (숫자, 예: 42)documentId (문자열, 예: “a1b2c3def456”)
API 응답 구조{ data: { id, attributes: { title, ... } } }{ data: { documentId, title, ... } } (flat)
coverImage URLdata.attributes.coverImage.data.attributes.urldata.coverImage.url
PUT 경로/api/blog-posts/{id} (숫자)/api/blog-posts/{documentId} (문자열)
Meilisearch 패키지@strapi/plugin-meilisearchstrapi-plugin-meilisearch (@ 없음)
Node.js 최소 버전v18v20
Content-Type Builderproduction 모드에서도 사용 가능development 모드에서만 사용 가능

n8n에서 가장 많이 바뀌는 부분

JavaScript — v4 vs v5 핵심 차이
// ── 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
나머지 95%는 동일합니다

REST API 경로(/api/blog-posts), Bearer 인증, Webhook 시크릿, n8n HTTP Request 노드 방식, WordPress REST API 연동, ComfyUI 이미지 생성 — 이 모든 것은 v4와 동일하게 동작합니다. 바뀌는 건 식별자(id→documentId)와 응답 파싱 경로(attributes 제거) 두 가지뿐입니다.

STEP02

기존 v4 중지 & v5 신규 설치

① v4 컨테이너 중지 (데이터 보존)

bash — v4 중지 (삭제 아님)
docker stop strapi
docker ps | grep strapi
# 아무것도 안 나오면 중지 완료

② v5 프로젝트 디렉토리 생성

bash — 디렉토리 구성
# 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회)

bash — node:20 임시 컨테이너로 v5 프로젝트 생성
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 작성

dockerfile — /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 — 올바른 볼륨 설정

yaml — 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
💡
볼륨 설정 핵심 원칙 — 왜 uploads만 마운트해야 하나

/mnt/data/02_automation/strapi-v5:/opt/app처럼 소스 디렉토리 전체를 마운트하면, 컨테이너 기동 시 호스트 디렉토리가 컨테이너 내부 /opt/app을 덮어씌웁니다. Dockerfile에서 빌드된 node_modules와 dist 폴더가 모두 날아가 애플리케이션이 동작하지 않습니다. 유저 업로드 파일(uploads)만 호스트에 영구 보관하고, 나머지는 이미지 빌드 결과물을 그대로 사용합니다.

⑥ .env 시크릿 키 생성 및 추가

bash — 키 생성 후 .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)"

⑦ 빌드 & 실행

1
이미지 빌드 (5~10분 소요)
docker compose build strapi
2
컨테이너 실행
docker compose up -d strapi-pg-db strapi
3
로그 확인 — 준비 완료 메시지 확인
docker logs -f strapiProject is running at http://localhost:1337 메시지가 나오면 성공
4
Admin 패널 접속 확인
브라우저에서 http://192.168.1.253:1337/admin 접속
STEP03

초기 설정 — Admin 계정 & 기본 구성

1
Admin 계정 생성
첫 접속 시 계정 생성 화면 → First name / Last name / Email / Password 입력 → Let’s Start!
2
회원가입 차단 (보안)
Settings (좌측 하단 톱니바퀴) → Users & Permissions PluginAdvanced settings
Enable sign-ups 토글 OFF → Save
3
스키마 설계를 위한 개발 모드 전환 (필수)
Content-Type Builder는 NODE_ENV=development 일 때만 사용 가능합니다.
docker-compose.yml에서 NODE_ENV: development로 변경 후 재시작합니다.
🚨
개발 모드 ↔ 운영 모드 전환 순서

스키마 설계 시: NODE_ENV=development → Content-Type Builder 사용 → 스키마 저장
운영 복귀 시: NODE_ENV=production으로 변경 → docker compose build strapidocker compose up -d strapi
스키마를 수정한 뒤에는 반드시 이미지를 다시 빌드해야 변경사항이 production에 반영됩니다.

STEP04

Content-Type Builder — Blog Post 스키마 설계

⚠️
Strapi UI 타입명 vs DB/코드 타입명 — 혼동 주의

Content-Type Builder 화면에서 보이는 이름과 schema.json의 실제 타입명이 다릅니다.

Admin UI에서 선택하는 이름세부 선택schema.json 타입용도
TextShort text 선택string제목, 짧은 단일 행 텍스트
TextLong text 선택text요약문, 여러 줄 텍스트
Rich TextBlocks 선택blocks본문 (블록 에디터)
UIDAttached field 선택uid슬러그 (자동 생성+중복 방지)
NumberInteger 선택integer숫자 값
MediaSingle media 선택media이미지 1장
Enumeration값 목록 입력enumeration정해진 값 중 하나 선택
Component컴포넌트 선택component재사용 가능한 필드 묶음
💡
필드 이름(Name) vs 표시 이름(Label) — 이것이 핵심

필드를 추가할 때 두 가지 이름을 설정합니다.
Name(이름): 반드시 영문 소문자+카멜케이스로 입력. 이것이 API 필드명이 됩니다. (예: wordpressPostId)
Label(표시 이름): Admin UI에서 보이는 이름으로, 한글도 가능합니다. (예: WordPress 포스트 ID)
영문 Name으로 생성 후 Advanced settings에서 Label만 한글로 변경하면 됩니다.

Blog Post 컬렉션 기본 정보

진입: Admin 패널 좌측 사이드바 → Content-Type Builder+ Create new collection type

항목
Display nameBlog Post
API ID (단수형)blog-post
API ID (복수형)blog-posts
Draft/Publish✅ 활성화 (반드시 체크)

필드 전체 목록 — 실제 UI 기준

필드 Name (영문, API명)UI 타입 선택세부 옵션설명
titleTextShort text · Required 체크글 제목
slugUIDAttached to: title · Required 자동 · Unique 자동WP 퍼머링크. Finish 후 Save 클릭
contentRich TextBlocks 선택 · Required 체크본문 블록 에디터
excerptTextLong text 선택요약문 (여러 줄 가능)
categoryEnumeration값 목록 입력 · Required 체크아래 Enum 값 참고
subCategoryEnumeration값 목록 입력 · Required 체크아래 Enum 값 참고
coverImageMediaSingle media · 이미지 타입만 허용대표 이미지 (ComfyUI 자동 생성)
wordpressPostIdNumberInteger 선택WP 역기록용 포스트 ID
imageMetaComponentimageMeta 컴포넌트이미지 메타 (아래 컴포넌트 참고)
seoMetaComponentseoMeta 컴포넌트SEO / Rank Math 데이터
socialMetaComponentsocialMeta 컴포넌트SNS 발행용 텍스트

Enumeration 값 — 영문 소문자만 허용

🚨
Enumeration 값에 한글 입력 절대 금지

Enumeration의 값(Value)은 반드시 영문 소문자로 입력해야 합니다. 한글을 입력하면 Strapi가 내부적으로 처리할 수 없어 ValidationError 400이 발생합니다. Label(표시 이름)만 한글로 설정하세요.

category Enum 값 (이 값만 허용 — 정확히 입력)
ai-lab
finance
home-lab
subCategory Enum 값
local-ai
workflow
music-gen
image-media-gen
prompt
daily-stock-reports
investment-automation
stock-etf
nas
devops
security
server-network

컴포넌트 구성

컴포넌트필드 NameUI 타입설명
imageMetafileNameText (Short)영문 파일명
altTextText (Short)이미지 대체 텍스트
imageTitleText (Short)이미지 title 속성
captionText (Long)이미지 캡션
descriptionText (Long)이미지 설명
seoMetaseoTitleText (Short)Rank Math SEO 제목
focusKeywordText (Short)포커스 키워드
secondaryKeywordsText (Long)보조 키워드 목록
metaDescriptionText (Long)메타 설명 (160자 이내)
categoryPathText (Short)WP 카테고리 슬러그 경로
socialMetasnsTagsText (Long)SNS 해시태그
snsSummaryText (Long)SNS 게시글 본문
snsCommentText (Long)SNS 댓글 (링크용)
tistorySummaryText (Long)티스토리 요약
💡
컴포넌트 생성 순서 — Builder에서 직접 생성

Content-Type Builder → Blog Post → + Add another fieldComponentCreate a new component
컴포넌트 이름: imageMeta / 카테고리: shared → Finish → 위 필드들을 추가 → Save
seoMeta, socialMeta도 동일한 방법으로 생성합니다.

STEP05

API 토큰 발급 & Webhook 설정

① API 토큰 발급 — n8n 연동용

1
진입 경로
Admin 패널 좌측 하단 Settings(⚙️)API Tokens → 우측 상단 + Create new API Token
2
토큰 설정값
· Name: n8n-pipeline
· Token type: Full access
· Token duration: Unlimited
3
Save → 토큰 복사 (한 번만 표시)
생성된 토큰값을 반드시 복사해 두세요. 다시 볼 수 없습니다.
4
n8n Credential 등록
n8n → 우측 상단 계정 아이콘 → Credentials+ Add Credential
Header Auth 선택 → Name: Strapi v5 Bearer
→ Name 필드: Authorization, Value 필드: Bearer 복사한토큰값

② Webhook 설정 — 시크릿 전체 과정

💡
Webhook 시크릿 작동 원리

Strapi가 Webhook을 보낼 때 HTTP 헤더에 시크릿 값을 포함합니다. n8n이 이 헤더를 검증해 Strapi에서 보낸 정상 요청인지 확인합니다. 이 과정이 없으면 누구나 n8n Webhook URL로 가짜 요청을 보낼 수 있습니다.

1
시크릿 문자열 생성
아래 명령어로 생성 후 복사해둡니다.
bash — 시크릿 생성
openssl rand -hex 16
# 예: a3f8d2c1b9e4f7a0c5d2e8f1b6a3c9d4
2
Strapi Webhook 생성
Admin 패널 → Settings(⚙️)Webhooks+ Create new Webhook
· Name: n8n-publish
· URL: http://n8n:5678/webhook/strapi-publish
· HeadersAdd a header
  — Header Name: X-Webhook-Secret
  — Header Value: 위에서 생성한 시크릿 값 붙여넣기
· EventsEntryPublish ✅ 체크
· Save
3
n8n Webhook 노드에서 시크릿 검증 설정
n8n 워크플로우 → 3번 노드(IF: 시크릿 검증)
· Left Value: {{ $headers['x-webhook-secret'] }}
· Operator: equals
· Right Value: 위 시크릿 문자열 직접 입력

③ Blog Post API 공개 권한 설정

1
진입 경로
Settings(⚙️) → Users & Permissions PluginRolesPublic
2
조회 권한 열기
Blog-post 섹션 → find ✅ / findOne ✅ 체크 → Save
WordPress 역동기화 워크플로우가 인증 없이 조회할 수 있도록 설정합니다.
STEP06

WordPress 카테고리 & Rank Math 설정

Strapi Enum ↔ WordPress 카테고리 슬러그 매핑

Strapi categoryStrapi subCategoryWP 카테고리 슬러그WP 표시명
ai-lablocal-ailocal-ai로컬 AI
ai-labworkflowworkflow워크플로우
ai-labmusic-genmusic-genAI 음악
ai-labimage-media-genimage-media-genAI 이미지
ai-labpromptprompt프롬프트
financedaily-stock-reportsdaily-stock-reports일일 시황
financeinvestment-automationinvestment-automation투자 자동화
financestock-etfstock-etf주식·ETF
home-labnasnasNAS
home-labdevopsdevopsDevOps
home-labsecuritysecurity보안
home-labserver-networkserver-network서버·네트워크

WordPress functions.php — Rank Math REST API 확장

PHP — WordPress functions.php (하단에 추가)
// 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',
        ]);
    }
});
STEP07

n8n 워크플로우 Import & Credential 설정

📦
워크플로우 파일: strapi-v5-pipeline-workflow.json (23노드)

n8n → 좌측 사이드바 → Workflows → 우측 상단 + New WorkflowImport from File로 가져옵니다. 아래 표에 따라 Credential과 주요 설정값만 채우면 바로 동작합니다.

노드 번호설정 항목입력값
1. WebhookWebhook URL 확인/webhook/strapi-publish
3. IF: 시크릿 검증Left Value{{ $headers['x-webhook-secret'] }}
3. IF: 시크릿 검증Right ValueSTEP 05 ② 에서 설정한 시크릿 문자열
5. ComfyUIURLhttp://comfyui:8188/prompt
5. ComfyUIckpt_name 값실제 설치된 모델 파일명으로 교체 필수
10. Strapi Media 업로드CredentialStrapi v5 Bearer
11. Strapi coverImageCredentialStrapi v5 Bearer
12, 14, 15, 16, 20, 22CredentialWordPress Basic Auth
17. Strapi 역기록CredentialStrapi v5 Bearer
🚨
ComfyUI 모델명 교체 필수

5번 노드의 ckpt_name 기본값이 설정되어 있습니다. R730 ComfyUI에 실제로 설치된 모델 파일명과 정확히 일치해야 합니다.
설치된 모델 목록 확인: http://192.168.1.253:8188/object_infoCheckpointLoaderSimpleckpt_name

STEP08

v4 vs v5 n8n 코드 변경 상세

기존 v4 워크플로우에서 v5로 업그레이드할 때 반드시 수정해야 하는 부분입니다.

노드 4 — 식별자 추출 (핵심 변경)

JavaScript — 노드 4 Code 노드
// ❌ v4 방식 — 숫자 id
const blogPostId = entry.id;

// ✅ v5 방식 — 문자열 documentId
const blogPostDocId = entry.documentId;

노드 11 — coverImage 연결 및 URL 파싱

n8n Expression — 노드 11 PUT 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

n8n Expression — 노드 17 PUT 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 }}
STEP09

Obsidian + SFTP → Strapi v5 초안 연동

Obsidian에서 작성한 마크다운을 ready/ 폴더로 이동하면 n8n이 SFTP로 읽어서 Strapi v5에 Draft로 자동 생성합니다.

💡
v4와 거의 동일합니다

SFTP 다운로드 → frontmatter 파싱 → Strapi POST 요청 구조는 동일합니다. Draft 생성(POST만)에서는 응답 파싱이 필요 없으므로 실질적으로 변경 사항이 없습니다.

Obsidian frontmatter 템플릿 (v5 기준)

Markdown — templates/blog-post-template.md
---
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>
🚨
category / subCategory는 Enum 값과 정확히 일치해야 합니다

한 글자라도 다르면 ValidationError 400이 발생합니다. STEP 04의 Enum 값 목록을 참고해 정확히 입력하세요. 특히 stock_etf가 아닌 stock-etf(하이픈)으로 통일되어 있습니다.

STEP10

Meilisearch 플러그인 연동

⚠️
v5 패키지명 주의 — @ 없음

v4: @strapi/plugin-meilisearch (존재하지 않음)
v5: strapi-plugin-meilisearch (앞에 @ 없음, 소문자 전체)

① 플러그인 설치

bash — 컨테이너 내부에서 설치
docker exec -it strapi sh -c "cd /opt/app && npm install strapi-plugin-meilisearch"
docker compose restart strapi

② 플러그인 설정 파일

TypeScript — /mnt/data/02_automation/strapi-v5/config/plugins.ts
export default ({ env }: { env: (key: string) => string }) => ({
  meilisearch: {
    config: {
      host: 'http://meilisearch:7700',
      apiKey: env('MEILI_MASTER_KEY'),
    },
  },
});
💡
MEILI_MASTER_KEY 환경변수 추가

docker-compose.yml의 strapi 서비스 environment에 MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}를 추가하고, .env 파일에도 해당 값을 넣어주세요.

③ Admin에서 인덱싱 설정

1
Admin 패널 → 좌측 사이드바 → Plugins → Meilisearch
2
Collections 탭 → Blog Post 체크박스 ✅
체크 순간부터 발행 글이 자동으로 인덱싱됩니다.
3
Reload 버튼 → 기존 발행 글 전체 즉시 인덱싱
STEP11

WordPress → Strapi v5 역동기화

이미 WordPress에 발행된 글을 Strapi v5 Draft로 가져와 중앙 관리합니다. n8n에서 수동으로 한 번만 실행합니다.

HTTP Request Body — WP 글 목록 → Strapi v5 POST (flat 구조)
{
  "data": {
    "title": "글 제목",
    "slug": "geul-jeomok",
    "content": "본문 HTML",
    "excerpt": "요약",
    "category": "home-lab",
    "subCategory": "devops",
    "wordpressPostId": 123
  }
}
# v4와 동일한 Body 구조 — v5에서도 POST 요청 방식은 동일합니다
STEP12

실전 발행 테스트 — 처음부터 끝까지

전체 발행 흐름
① 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 확인 명령어

bash — Strapi v5 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
STEP13

트러블슈팅 & 운영 체크리스트

빠른 점검 순서

1
n8n Executions 탭 확인 (가장 먼저)
n8n 좌측 사이드바 → Executions
실패한 실행을 클릭 → 어느 노드에서 실패했는지, 정확한 에러 메시지 확인
에러 메시지 없이는 원인을 추정만 하게 됩니다. 항상 이 탭 먼저 확인하세요.
2
n8n Webhook 노드 수동 테스트
Webhook 수신 자체가 되는지 curl로 직접 테스트합니다.
bash — n8n Webhook 수동 테스트
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 탭에 실행 기록이 생성됩니다
bash — Strapi Webhook 직접 트리거 테스트
# 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 undefinedv4 응답 경로 사용 중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 역기록 확인
🚀
Strapi v5 파이프라인 완성
documentId 기반의 더 단순하고 강력한 CMS 허브
볼륨 버그 수정 · UI 메뉴명 정확화 · Webhook 시크릿 완전 가이드 포함
v5 신규 설치 23노드 자동 발행 볼륨 버그 수정 ComfyUI 대표 이미지 Meilisearch 연동

Leave A Reply

Please enter your comment!
Please enter your name here

Related Stories