n8n 책 스캐너
고급
이것은Content Creation, Multimodal AI분야의자동화 워크플로우로, 16개의 노드를 포함합니다.주로 Set, Code, Webhook, HttpRequest, OpenAi 등의 노드를 사용하며. GPT-4o와 Google Books를 사용하여 책셀 사진에서 책 제목 추출 및 검증
사전 요구사항
- •HTTP Webhook 엔드포인트(n8n이 자동으로 생성)
- •대상 API의 인증 정보가 필요할 수 있음
- •OpenAI API Key
워크플로우 미리보기
노드 연결 관계를 시각적으로 표시하며, 확대/축소 및 이동을 지원합니다
워크플로우 내보내기
다음 JSON 구성을 복사하여 n8n에 가져오면 이 워크플로우를 사용할 수 있습니다
{
"id": "n1UbcJnl7I5rMDIe",
"meta": {
"instanceId": "7d302cb44fba0420b6a4deb04edff9d7c47e83ef1f3f66f89fe519337b882186",
"templateCredsSetupCompleted": true
},
"name": "n8n submission book scanner",
"tags": [],
"nodes": [
{
"id": "8fc53cb4-d7bc-4fcb-8c6d-1ee90b4ad5b4",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"position": [
-896,
1376
],
"webhookId": "365ea003-fe66-4211-ae03-69f1456d768e",
"parameters": {
"path": "365ea003-fe66-4211-ae03-69f1456d768e",
"options": {},
"httpMethod": "POST",
"responseMode": "responseNode"
},
"typeVersion": 2.1
},
{
"id": "a140d496-9098-43b2-97df-089a811a909d",
"name": "Webhook에 응답",
"type": "n8n-nodes-base.respondToWebhook",
"position": [
592,
1376
],
"parameters": {
"options": {
"responseCode": 200,
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
},
"respondWith": "json",
"responseBody": "={{$json}}"
},
"typeVersion": 1.4
},
{
"id": "050a5432-4d7e-4855-b09f-5ca40a9e0999",
"name": "이미지 분석",
"type": "@n8n/n8n-nodes-langchain.openAi",
"position": [
-448,
1376
],
"parameters": {
"text": "=You are a STRICT transformer. Analyze the image of book spines and return only clearly readable titles and authors. \nDo NOT guess. If the author isn't clearly visible, set \"author\": null.\nNormalize capitalization. Deduplicate by title. \nOutput STRICT JSON only:\n{\"books\":[{\"title\":\"string\",\"author\":\"string|null\"}]}\n",
"modelId": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini",
"cachedResultName": "GPT-4O-MINI"
},
"options": {},
"resource": "image",
"imageUrls": "={{$json.image}}\n",
"operation": "analyze"
},
"credentials": {
"openAiApi": {
"id": "iJ4uczBur5RBMvV4",
"name": "OpenAi account"
}
},
"typeVersion": 1.8
},
{
"id": "50c4d4b8-b164-47fb-b9c6-2234f3cb5952",
"name": "스티키 노트",
"type": "n8n-nodes-base.stickyNote",
"position": [
-992,
1280
],
"parameters": {
"height": 80,
"content": "Webhook connects to front end that passes on JSON with imageURL (string)"
},
"typeVersion": 1
},
{
"id": "d245e1df-a5a2-487c-bd8f-41601be2f05c",
"name": "스티키 노트1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-736,
1520
],
"parameters": {
"height": 80,
"content": "Input is normalized"
},
"typeVersion": 1
},
{
"id": "2c44a9af-f395-45ff-bf4f-91a55c829d3e",
"name": "스티키 노트2",
"type": "n8n-nodes-base.stickyNote",
"position": [
-512,
1280
],
"parameters": {
"height": 80,
"content": "Image is analyzed and transformed."
},
"typeVersion": 1
},
{
"id": "1ec82294-d70b-4ff6-ab34-c7ef156a41b2",
"name": "스티키 노트3",
"type": "n8n-nodes-base.stickyNote",
"position": [
-288,
1520
],
"parameters": {
"content": "Splits the output (in this case, books) into individual items in preparation for the next step which is to verify the book against a known source to confirm the title and author."
},
"typeVersion": 1
},
{
"id": "44f65fae-f829-4b6b-976b-001d071b82ee",
"name": "스티키 노트4",
"type": "n8n-nodes-base.stickyNote",
"position": [
-96,
1280
],
"parameters": {
"height": 80,
"content": "Confirms each title against Google Books"
},
"typeVersion": 1
},
{
"id": "917a2da3-3691-4904-8cbc-4c00ee4ed72e",
"name": "스티키 노트5",
"type": "n8n-nodes-base.stickyNote",
"position": [
112,
1536
],
"parameters": {
"height": 80,
"content": "Normalizes data"
},
"typeVersion": 1
},
{
"id": "62b507e0-5b7d-48a3-9e44-aa4ccf339331",
"name": "스티키 노트6",
"type": "n8n-nodes-base.stickyNote",
"position": [
304,
1280
],
"parameters": {
"height": 80,
"content": "Reaggregates book list and dedupes"
},
"typeVersion": 1
},
{
"id": "94b96cbc-3bd4-4db8-83ff-eb57b4e516c3",
"name": "스티키 노트7",
"type": "n8n-nodes-base.stickyNote",
"position": [
544,
1520
],
"parameters": {
"height": 80,
"content": "Returns list back to frontend."
},
"typeVersion": 1
},
{
"id": "c4796062-4c64-474a-85b9-8306585c18b1",
"name": "정규화된 입력",
"type": "n8n-nodes-base.set",
"position": [
-672,
1376
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "94b88376-fed9-46cf-882f-d4c0d7670350",
"name": "image",
"type": "string",
"value": "={{ ($json.body?.imageUrl || $json.body?.image || $json.imageUrl || $json.image || '').trim() }}\n"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "dbe25007-44da-403b-89bf-bcbf57591d58",
"name": "항목 목록 분할",
"type": "n8n-nodes-base.code",
"position": [
-240,
1376
],
"parameters": {
"jsCode": "const items = await $input.all();\nconst out = [];\n\nfunction stripCodeFence(s) {\n return String(s || '')\n .replace(/^```json\\s*/i, '')\n .replace(/^```\\s*/i, '')\n .replace(/```$/, '')\n .trim();\n}\n\nfunction firstAuthor(a) {\n if (!a) return null;\n // keep a single name for better \"inauthor:\" matching\n const s = String(a);\n const parts = s.split(/\\s*(?:,| and |&)\\s*/i);\n return (parts[0] || '').trim() || null;\n}\n\nfor (const item of items) {\n let books = null;\n\n // Case 1: you already have an object with books[]\n if (Array.isArray(item.json?.books)) {\n books = item.json.books;\n }\n\n // Case 2: you have a string in `content` with ```json ... ```\n if (!books && typeof item.json?.content === 'string') {\n const cleaned = stripCodeFence(item.json.content);\n try {\n const parsed = JSON.parse(cleaned);\n if (Array.isArray(parsed.books)) books = parsed.books;\n } catch (e) {\n // ignore; we'll fall back\n }\n }\n\n if (!books) continue;\n\n for (const b of books) {\n out.push({\n json: {\n title: b.title,\n author: b.author ?? null,\n // helper field only for the search query:\n searchAuthor: firstAuthor(b.author)\n }\n });\n }\n}\n\nreturn out;\n"
},
"typeVersion": 2
},
{
"id": "2017d011-6d85-4844-a08a-0a7e88ae052d",
"name": "제목 검증",
"type": "n8n-nodes-base.httpRequest",
"position": [
-32,
1376
],
"parameters": {
"url": "https://www.googleapis.com/books/v1/volumes",
"options": {
"response": {
"response": {
"responseFormat": "json"
}
}
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "=q",
"value": "={{ \n 'intitle:\"' + $json.title.replace(/\"/g,'') + '\"' +\n ($json.searchAuthor ? ' inauthor:\"' + $json.searchAuthor.replace(/\"/g,'') + '\"' : '')\n}}\n"
},
{
"name": "maxResults",
"value": "5"
},
{
"name": "printType",
"value": "books"
},
{
"name": "orderBy",
"value": "relevance"
}
]
}
},
"typeVersion": 4.2
},
{
"id": "7d94ce36-fc7c-44cb-8df6-6f13293160a4",
"name": "정규화된 데이터",
"type": "n8n-nodes-base.set",
"position": [
176,
1376
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "67464bb0-8615-41a5-8408-11a95708d200",
"name": "=title",
"type": "string",
"value": "={{ $json.items?.[0]?.volumeInfo?.title || $prevNode('Code').json.title }}\n"
},
{
"id": "8db9c2f0-3193-428e-adab-2745f397233c",
"name": "author",
"type": "string",
"value": "={{ $json.items?.[0]?.volumeInfo?.authors?.[0] || $prevNode('Code').json.author || null }}\n"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "99d74571-f35d-4086-93ce-f7f67768a8f0",
"name": "목록 재집계",
"type": "n8n-nodes-base.code",
"position": [
384,
1376
],
"parameters": {
"jsCode": "const items = await $input.all();\nconst seen = new Set();\nconst books = [];\n\nfor (const it of items) {\n const t = (it.json.title || '').toLowerCase().trim();\n if (t && !seen.has(t)) {\n seen.add(t);\n books.push({ title: it.json.title, author: it.json.author ?? null });\n }\n}\n\nreturn [{ json: { books } }];\n"
},
"typeVersion": 2
}
],
"active": false,
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"versionId": "5f454fe8-f8b7-4302-820e-ec24a00f13bd",
"connections": {
"8fc53cb4-d7bc-4fcb-8c6d-1ee90b4ad5b4": {
"main": [
[
{
"node": "c4796062-4c64-474a-85b9-8306585c18b1",
"type": "main",
"index": 0
}
]
]
},
"050a5432-4d7e-4855-b09f-5ca40a9e0999": {
"main": [
[
{
"node": "dbe25007-44da-403b-89bf-bcbf57591d58",
"type": "main",
"index": 0
}
]
]
},
"7d94ce36-fc7c-44cb-8df6-6f13293160a4": {
"main": [
[
{
"node": "99d74571-f35d-4086-93ce-f7f67768a8f0",
"type": "main",
"index": 0
}
]
]
},
"dbe25007-44da-403b-89bf-bcbf57591d58": {
"main": [
[
{
"node": "2017d011-6d85-4844-a08a-0a7e88ae052d",
"type": "main",
"index": 0
}
]
]
},
"c4796062-4c64-474a-85b9-8306585c18b1": {
"main": [
[
{
"node": "050a5432-4d7e-4855-b09f-5ca40a9e0999",
"type": "main",
"index": 0
}
]
]
},
"2017d011-6d85-4844-a08a-0a7e88ae052d": {
"main": [
[
{
"node": "7d94ce36-fc7c-44cb-8df6-6f13293160a4",
"type": "main",
"index": 0
}
]
]
},
"99d74571-f35d-4086-93ce-f7f67768a8f0": {
"main": [
[
{
"node": "a140d496-9098-43b2-97df-089a811a909d",
"type": "main",
"index": 0
}
]
]
}
}
}자주 묻는 질문
이 워크플로우를 어떻게 사용하나요?
위의 JSON 구성 코드를 복사하여 n8n 인스턴스에서 새 워크플로우를 생성하고 "JSON에서 가져오기"를 선택한 후, 구성을 붙여넣고 필요에 따라 인증 설정을 수정하세요.
이 워크플로우는 어떤 시나리오에 적합한가요?
고급 - 콘텐츠 제작, 멀티모달 AI
유료인가요?
이 워크플로우는 완전히 무료이며 직접 가져와 사용할 수 있습니다. 다만, 워크플로우에서 사용하는 타사 서비스(예: OpenAI API)는 사용자 직접 비용을 지불해야 할 수 있습니다.
관련 워크플로우 추천
회의록 및 액션 아이템 트래커
AI 기반 회의록: GPT-4, 작업 할당 및 다중 채널 배포 활용
If
Set
Code
+
If
Set
Code
38 노드Jitesh Dugar
콘텐츠 제작
콘텐츠 생성기
AI 기반 소셜 미디어 콘텐츠 생성기, GPT-4 모델 전략 방법 적용
Set
Code
Webhook
+
Set
Code
Webhook
22 노드inderjeet Bhambra
콘텐츠 제작
잠재 리드 전화 자동화: VAPI, Google Sheets 기록 및 캘린더 예약
잠재 고객 전화 자동화: VAPI, Google Sheets 기록 및 캘린더 약속
Set
Code
Webhook
+
Set
Code
Webhook
13 노드Meak
콘텐츠 제작
AI를 사용한 WordPress 글 작성 (몇 가지 키워드로 시작)
GPT-4, DALL-E 및 Wikipedia 기반 자동화된 블로그 글 생성기 (WordPress용)
If
Set
Code
+
If
Set
Code
37 노드Punit
콘텐츠 제작
OpenAI, LangChain, API 통합을 사용한 작업 자동화 초보자 가이드
OpenAI, LangChain 및 API 통합을 사용한 작업 자동화 시작자 가이드
If
Set
Code
+
If
Set
Code
33 노드Meelioo
콘텐츠 제작
Zonos를 통해 API를 사용하여 텍스트를 음성으로 변환하는 음성 클론 (로컬 스토리지)
Zyphra Zonos API를 사용하여 텍스트에서 음성으로 복제
If
Set
Code
+
If
Set
Code
18 노드Tiartyos
콘텐츠 제작