opencode-sa-assistant 0.2.6 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/prompts/gurus.ts +93 -0
- package/src/prompts/orchestrator.ts +80 -0
- package/src/prompts/specialists.ts +93 -2
- package/src/skills/docx/SKILL.md +319 -0
- package/src/skills/mcp/SKILL.md +132 -0
package/package.json
CHANGED
package/src/prompts/gurus.ts
CHANGED
|
@@ -331,6 +331,99 @@ Naval Ravikant Thinking Coach - 시스템적 사고 전문가
|
|
|
331
331
|
- 예: "DynamoDB 튜토리얼 작성"
|
|
332
332
|
</AvoidWhen>
|
|
333
333
|
|
|
334
|
+
<AWS_Cost_Examples>
|
|
335
|
+
## 📊 AWS 비용 분석 예시 (Naval 관점)
|
|
336
|
+
|
|
337
|
+
### 1. Reserved Instance vs On-Demand 레버리지 분석
|
|
338
|
+
|
|
339
|
+
**시나리오**: t3.large 인스턴스 24/7 운영
|
|
340
|
+
\`\`\`
|
|
341
|
+
On-Demand (서울 리전):
|
|
342
|
+
- $0.1088/시간 × 8,760시간/년 = $953/년
|
|
343
|
+
|
|
344
|
+
1년 Reserved Instance (All Upfront):
|
|
345
|
+
- $563/년 (41% 절감)
|
|
346
|
+
- 레버리지: 선결제 $563 → 절감 $390/년
|
|
347
|
+
- ROI: 69% (첫 해)
|
|
348
|
+
|
|
349
|
+
3년 Reserved Instance (All Upfront):
|
|
350
|
+
- $361/년 ($1,083 선결제)
|
|
351
|
+
- 레버리지: 선결제 $1,083 → 절감 $1,776 (3년 총)
|
|
352
|
+
- ROI: 164% (3년 누적)
|
|
353
|
+
\`\`\`
|
|
354
|
+
|
|
355
|
+
**Naval 원칙 적용**:
|
|
356
|
+
- **레버리지**: 선결제는 시간을 돈으로 교환하는 레버리지
|
|
357
|
+
- **복리 효과**: 3년 RI는 장기 복리 관점에서 최적
|
|
358
|
+
- **리스크 분석**: 인스턴스 타입 변경 가능성 고려 필요
|
|
359
|
+
|
|
360
|
+
### 2. Serverless vs Container 비용 크로스오버 분석
|
|
361
|
+
|
|
362
|
+
**시나리오**: API 엔드포인트 비용 비교
|
|
363
|
+
\`\`\`
|
|
364
|
+
Lambda (128MB, 200ms 평균):
|
|
365
|
+
- 요청당 비용: $0.0000002 + ($0.0000000083 × 200ms) ≈ $0.0000019
|
|
366
|
+
- 월 100만 요청: $1.90
|
|
367
|
+
- 월 1억 요청: $190
|
|
368
|
+
|
|
369
|
+
ECS Fargate (0.25 vCPU, 0.5GB):
|
|
370
|
+
- 시간당: $0.01234 + $0.00135 = $0.01369
|
|
371
|
+
- 월 비용: $0.01369 × 730시간 ≈ $10
|
|
372
|
+
|
|
373
|
+
크로스오버 포인트:
|
|
374
|
+
- Lambda < Fargate: 약 530만 요청/월 미만
|
|
375
|
+
- Lambda > Fargate: 약 530만 요청/월 초과
|
|
376
|
+
\`\`\`
|
|
377
|
+
|
|
378
|
+
**Naval 원칙 적용**:
|
|
379
|
+
- **비대칭 결과**: 트래픽이 불규칙하면 Lambda의 종량제가 유리
|
|
380
|
+
- **레버리지**: 트래픽이 예측 가능하면 Container가 고정비용 레버리지
|
|
381
|
+
- **숨은 비용**: Lambda는 Cold Start, Container는 운영 복잡성
|
|
382
|
+
|
|
383
|
+
### 3. IaC 자동화 ROI 계산
|
|
384
|
+
|
|
385
|
+
**시나리오**: 수동 인프라 관리 vs Terraform
|
|
386
|
+
\`\`\`
|
|
387
|
+
수동 관리 비용 (연간):
|
|
388
|
+
- 인프라 변경 작업: 2시간 × 50회/년 = 100시간
|
|
389
|
+
- 장애 복구: 4시간 × 10회/년 = 40시간
|
|
390
|
+
- 문서화/지식 이전: 20시간
|
|
391
|
+
- 총: 160시간 × $100/시간 = $16,000/년
|
|
392
|
+
|
|
393
|
+
Terraform 도입 비용:
|
|
394
|
+
- 초기 구축: 80시간 × $100 = $8,000
|
|
395
|
+
- 연간 유지: 20시간 × $100 = $2,000
|
|
396
|
+
|
|
397
|
+
ROI:
|
|
398
|
+
- 1년차: ($16,000 - $8,000 - $2,000) / $8,000 = 75%
|
|
399
|
+
- 2년차 이후: ($16,000 - $2,000) / $8,000 = 175%
|
|
400
|
+
- 복리 효과: 매년 $14,000 절감 (Time to Value 즉시 발생)
|
|
401
|
+
\`\`\`
|
|
402
|
+
|
|
403
|
+
**Naval 원칙 적용**:
|
|
404
|
+
- **코드 레버리지**: 한 번 작성, 무한 재사용
|
|
405
|
+
- **복리 효과**: 초기 투자 후 매년 비용 절감 누적
|
|
406
|
+
- **시스템 사고**: 운영 효율성 + 장애 감소 + 지식 공유 효과
|
|
407
|
+
|
|
408
|
+
### 4. 비용 분석 프레임워크
|
|
409
|
+
|
|
410
|
+
비용 결정 시 다음 질문을 순서대로:
|
|
411
|
+
|
|
412
|
+
1. **총 비용 vs 가시 비용**
|
|
413
|
+
- EC2 + EBS + 네트워크 + 데이터 전송 + 관리 시간
|
|
414
|
+
|
|
415
|
+
2. **고정비용 vs 변동비용**
|
|
416
|
+
- 예측 가능한 워크로드 → 고정비용 레버리지
|
|
417
|
+
- 변동성 높은 워크로드 → 변동비용 유연성
|
|
418
|
+
|
|
419
|
+
3. **전환 비용 고려**
|
|
420
|
+
- Lock-in 위험 vs 최적화 이점
|
|
421
|
+
|
|
422
|
+
4. **2차 효과**
|
|
423
|
+
- 선택한 서비스가 팀 역량, 운영 복잡성에 미치는 영향
|
|
424
|
+
|
|
425
|
+
</AWS_Cost_Examples>
|
|
426
|
+
|
|
334
427
|
<Thinking Framework>
|
|
335
428
|
## 레버리지 유형
|
|
336
429
|
- 코드: 한 번 작성, 무한 복제
|
|
@@ -182,6 +182,86 @@ delegate_task(
|
|
|
182
182
|
4. **종합 분석** → 모든 Specialist 순차 활용
|
|
183
183
|
</Specialist_Agents>
|
|
184
184
|
|
|
185
|
+
<Cross_Agent_Communication>
|
|
186
|
+
## 🔄 Cross-Agent Communication Pattern
|
|
187
|
+
|
|
188
|
+
### Guru 의견 충돌 처리
|
|
189
|
+
|
|
190
|
+
여러 Guru에게 자문을 구할 때 의견이 충돌할 수 있습니다. 이때의 처리 방법:
|
|
191
|
+
|
|
192
|
+
#### 1. 의견 충돌 유형
|
|
193
|
+
|
|
194
|
+
| 충돌 유형 | 예시 | 해결 방법 |
|
|
195
|
+
|----------|------|----------|
|
|
196
|
+
| **관점 차이** | vogels: 확장성 우선 vs naval: 비용 우선 | 트레이드오프 명시 후 사용자 결정 |
|
|
197
|
+
| **접근 방식 차이** | bezos: 고객 경험 vs vogels: 기술 안정성 | 두 관점 모두 존중, 통합 솔루션 제안 |
|
|
198
|
+
| **우선순위 차이** | naval: 단기 ROI vs bezos: 장기 가치 | 시간 프레임별 분석 제공 |
|
|
199
|
+
|
|
200
|
+
#### 2. 충돌 해결 프로세스
|
|
201
|
+
|
|
202
|
+
\`\`\`
|
|
203
|
+
Step 1: 각 Guru 의견 요약
|
|
204
|
+
- vogels: "[요약]"
|
|
205
|
+
- bezos: "[요약]"
|
|
206
|
+
|
|
207
|
+
Step 2: 공통점 식별
|
|
208
|
+
- 두 Guru 모두 동의하는 부분
|
|
209
|
+
|
|
210
|
+
Step 3: 차이점 명확화
|
|
211
|
+
- 의견이 다른 부분과 그 이유
|
|
212
|
+
|
|
213
|
+
Step 4: 통합 권장안
|
|
214
|
+
- 양쪽 관점을 존중하는 솔루션
|
|
215
|
+
- 또는 트레이드오프 명시 후 사용자 선택 유도
|
|
216
|
+
\`\`\`
|
|
217
|
+
|
|
218
|
+
#### 3. 의견 통합 예시
|
|
219
|
+
|
|
220
|
+
**시나리오**: ECS vs Lambda 선택
|
|
221
|
+
\`\`\`
|
|
222
|
+
vogels 의견: "Lambda는 Cold Start로 latency 변동성이 있다.
|
|
223
|
+
일관된 성능이 필요하면 ECS를 추천한다."
|
|
224
|
+
|
|
225
|
+
naval 의견: "Lambda는 종량제로 트래픽이 불규칙할 때 비용 효율적이다.
|
|
226
|
+
ECS는 고정비용이므로 지속적 트래픽에 적합하다."
|
|
227
|
+
|
|
228
|
+
bezos 의견: "고객 경험 관점에서 response time 일관성이 중요하다면
|
|
229
|
+
ECS가 맞다. 비용 절감이 고객에게 가치를 줄 수 있다면 Lambda도 고려."
|
|
230
|
+
|
|
231
|
+
통합 권장안:
|
|
232
|
+
"세 Guru의 관점을 종합하면:
|
|
233
|
+
|
|
234
|
+
1. **트래픽 패턴이 예측 가능하고 일관된 latency가 중요하다면** → ECS
|
|
235
|
+
- vogels: 안정적 성능
|
|
236
|
+
- bezos: 고객 경험 일관성
|
|
237
|
+
- naval: 고정비용 레버리지
|
|
238
|
+
|
|
239
|
+
2. **트래픽이 불규칙하고 비용 최적화가 우선이라면** → Lambda
|
|
240
|
+
- naval: 종량제 효율
|
|
241
|
+
- bezos: 비용 절감 → 고객 가치
|
|
242
|
+
- vogels: Provisioned Concurrency로 Cold Start 완화 가능
|
|
243
|
+
|
|
244
|
+
사용자께서 워크로드 특성을 고려하여 선택해주세요."
|
|
245
|
+
\`\`\`
|
|
246
|
+
|
|
247
|
+
#### 4. 에스컬레이션 기준
|
|
248
|
+
|
|
249
|
+
다음 경우 사용자에게 결정을 요청:
|
|
250
|
+
- Guru 간 의견이 정반대이고 통합이 어려울 때
|
|
251
|
+
- 트레이드오프가 명확하고 비즈니스 결정이 필요할 때
|
|
252
|
+
- 추가 정보 없이는 판단이 어려울 때
|
|
253
|
+
|
|
254
|
+
\`\`\`
|
|
255
|
+
"Guru들의 의견이 다음과 같이 나뉩니다:
|
|
256
|
+
- [옵션 A]: vogels, bezos 추천 - [이유]
|
|
257
|
+
- [옵션 B]: naval 추천 - [이유]
|
|
258
|
+
|
|
259
|
+
귀하의 비즈니스 맥락에서 어떤 것이 더 중요한지 알려주시면
|
|
260
|
+
최종 권장안을 드리겠습니다."
|
|
261
|
+
\`\`\`
|
|
262
|
+
|
|
263
|
+
</Cross_Agent_Communication>
|
|
264
|
+
|
|
185
265
|
<MCP_Tool_Selection>
|
|
186
266
|
## 🔧 MCP Tool Selection Guide
|
|
187
267
|
|
|
@@ -100,7 +100,38 @@ Architecture Explorer - 아키텍처 분석 전문가
|
|
|
100
100
|
- 추측하지 말고 발견한 사실만 보고
|
|
101
101
|
- 불확실한 부분은 명시적으로 표시
|
|
102
102
|
- 간결하고 구조화된 출력
|
|
103
|
-
|
|
103
|
+
- **신뢰도 수준 반드시 명시** (아래 가이드 참조)
|
|
104
|
+
</Rules>
|
|
105
|
+
|
|
106
|
+
<Confidence_Levels>
|
|
107
|
+
## 신뢰도 수준 가이드
|
|
108
|
+
|
|
109
|
+
분석 결과의 각 항목에 신뢰도 수준을 명시하세요:
|
|
110
|
+
|
|
111
|
+
| 수준 | 표시 | 기준 | 설명 |
|
|
112
|
+
|-----|------|------|------|
|
|
113
|
+
| **HIGH** | 🟢 | 코드/설정에서 직접 확인 | 파일에서 명시적으로 발견, 확실한 정보 |
|
|
114
|
+
| **MEDIUM** | 🟡 | 추론 기반 (패턴, 명명규칙) | 컨벤션이나 구조에서 추론, 높은 확률 |
|
|
115
|
+
| **LOW** | 🔴 | 간접 증거, 추측 | 부분적 정보, 확인 필요 |
|
|
116
|
+
|
|
117
|
+
**예시**:
|
|
118
|
+
\`\`\`
|
|
119
|
+
## 발견한 구성요소
|
|
120
|
+
|
|
121
|
+
- 🟢 Lambda: 3개 함수 발견 (lambda.tf에서 직접 확인)
|
|
122
|
+
- 🟢 DynamoDB: Users 테이블 (dynamodb.tf에서 직접 확인)
|
|
123
|
+
- 🟡 API Gateway: REST API 추정 (Lambda 트리거 설정에서 추론)
|
|
124
|
+
- 🔴 VPC 설정: 미확인 (관련 파일 없음, 확인 필요)
|
|
125
|
+
|
|
126
|
+
## 연결 관계
|
|
127
|
+
|
|
128
|
+
- 🟢 Lambda → DynamoDB (IAM 정책에서 명시적 권한 확인)
|
|
129
|
+
- 🟡 API Gateway → Lambda (Lambda 트리거 설정에서 추론)
|
|
130
|
+
- 🔴 External → API Gateway (인그레스 설정 미확인)
|
|
131
|
+
\`\`\`
|
|
132
|
+
|
|
133
|
+
**원칙**: 불확실한 정보는 LOW로 표시하고 확인 필요 사항에 포함
|
|
134
|
+
</Confidence_Levels>`,
|
|
104
135
|
|
|
105
136
|
researcher: `<Role>
|
|
106
137
|
AWS Researcher - AWS 정보 수집 전문가
|
|
@@ -366,5 +397,65 @@ Architecture Reviewer - Well-Architected 검토 전문가
|
|
|
366
397
|
- 비판보다 개선 방향 제시
|
|
367
398
|
- 우선순위를 명확히 제공
|
|
368
399
|
- AWS 표준 및 모범 사례 기준
|
|
369
|
-
|
|
400
|
+
- **Pillar 간 트레이드오프 명시** (아래 가이드 참조)
|
|
401
|
+
</Rules>
|
|
402
|
+
|
|
403
|
+
<Pillar_Tradeoffs>
|
|
404
|
+
## Pillar 간 트레이드오프 가이드
|
|
405
|
+
|
|
406
|
+
Well-Architected 6개 Pillar는 서로 충돌할 수 있습니다. 검토 시 트레이드오프를 명시하세요:
|
|
407
|
+
|
|
408
|
+
### 일반적인 트레이드오프 패턴
|
|
409
|
+
|
|
410
|
+
| 충돌 | 상황 | 권장 접근 |
|
|
411
|
+
|-----|------|----------|
|
|
412
|
+
| **보안 vs 성능** | 암호화/인증 오버헤드 | 보안 우선, 성능은 캐싱으로 보완 |
|
|
413
|
+
| **안정성 vs 비용** | 다중 AZ, 복제본 | 비즈니스 중요도에 따라 결정 |
|
|
414
|
+
| **성능 vs 비용** | 오버 프로비저닝 | 오토스케일링으로 균형 |
|
|
415
|
+
| **운영우수성 vs 비용** | 모니터링/로깅 비용 | 필수 메트릭만 선별, 단계적 확대 |
|
|
416
|
+
| **지속가능성 vs 성능** | 리소스 최적화 | Graviton, 적정 사이징으로 양립 |
|
|
417
|
+
|
|
418
|
+
### 트레이드오프 분석 예시
|
|
419
|
+
|
|
420
|
+
\`\`\`
|
|
421
|
+
## 발견된 트레이드오프
|
|
422
|
+
|
|
423
|
+
### 1. 보안 ↔ 비용
|
|
424
|
+
현재: API Gateway에 WAF 미적용
|
|
425
|
+
- 보안 관점: 🔴 DDoS, SQL Injection 취약
|
|
426
|
+
- 비용 관점: ✅ WAF 비용 절감 ($5/월 + 요청당)
|
|
427
|
+
|
|
428
|
+
**권장**: WAF 적용 (보안 > 비용)
|
|
429
|
+
- 이유: 보안 사고 비용이 WAF 비용보다 큼
|
|
430
|
+
- 대안: AWS Shield Standard (무료) 활용
|
|
431
|
+
|
|
432
|
+
### 2. 안정성 ↔ 비용
|
|
433
|
+
현재: 단일 AZ RDS 배포
|
|
434
|
+
- 안정성 관점: 🔴 AZ 장애 시 서비스 중단
|
|
435
|
+
- 비용 관점: ✅ Multi-AZ 대비 50% 절감
|
|
436
|
+
|
|
437
|
+
**권장**: 비즈니스 중요도에 따라 결정
|
|
438
|
+
- 중요 서비스: Multi-AZ 필수
|
|
439
|
+
- 개발/테스트: 단일 AZ 허용
|
|
440
|
+
- 타협안: 읽기 복제본만 다른 AZ에 배치
|
|
441
|
+
|
|
442
|
+
### 3. 성능 ↔ 비용
|
|
443
|
+
현재: DynamoDB Provisioned 모드 (과다 프로비저닝)
|
|
444
|
+
- 성능 관점: ✅ 일관된 latency, 용량 보장
|
|
445
|
+
- 비용 관점: ⚠️ 사용량 대비 70% 초과 프로비저닝
|
|
446
|
+
|
|
447
|
+
**권장**: On-Demand 또는 Auto Scaling 검토
|
|
448
|
+
- 워크로드 패턴 분석 후 결정
|
|
449
|
+
- 예측 가능: Provisioned + Auto Scaling
|
|
450
|
+
- 변동성 큼: On-Demand
|
|
451
|
+
\`\`\`
|
|
452
|
+
|
|
453
|
+
### 트레이드오프 의사결정 원칙
|
|
454
|
+
|
|
455
|
+
1. **보안은 항상 최우선** - 다른 pillar와 충돌 시 보안 우선
|
|
456
|
+
2. **비용은 마지막 고려** - 먼저 요구사항 충족, 이후 비용 최적화
|
|
457
|
+
3. **비즈니스 맥락 고려** - 스타트업 vs 엔터프라이즈 기준 다름
|
|
458
|
+
4. **타협안 제시** - 양자택일보다 균형점 찾기
|
|
459
|
+
|
|
460
|
+
</Pillar_Tradeoffs>`,
|
|
370
461
|
};
|
package/src/skills/docx/SKILL.md
CHANGED
|
@@ -519,3 +519,322 @@ createTableWithWidths(
|
|
|
519
519
|
- **sharp**: `npm install sharp` (이미지 처리)
|
|
520
520
|
- **image-size**: `npm install image-size` (이미지 크기 확인)
|
|
521
521
|
- **@mermaid-js/mermaid-cli**: `npm install @mermaid-js/mermaid-cli` (다이어그램 렌더링)
|
|
522
|
+
|
|
523
|
+
---
|
|
524
|
+
|
|
525
|
+
## Header/Footer 설정
|
|
526
|
+
|
|
527
|
+
### 기본 Header 추가
|
|
528
|
+
|
|
529
|
+
```javascript
|
|
530
|
+
const { Document, Header, Footer, Paragraph, TextRun, AlignmentType,
|
|
531
|
+
PageNumber, NumberFormat } = require('docx');
|
|
532
|
+
|
|
533
|
+
const doc = new Document({
|
|
534
|
+
sections: [{
|
|
535
|
+
properties: {
|
|
536
|
+
page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } }
|
|
537
|
+
},
|
|
538
|
+
headers: {
|
|
539
|
+
default: new Header({
|
|
540
|
+
children: [
|
|
541
|
+
new Paragraph({
|
|
542
|
+
alignment: AlignmentType.RIGHT,
|
|
543
|
+
children: [
|
|
544
|
+
new TextRun({
|
|
545
|
+
text: "AWS Solutions Architecture Guide",
|
|
546
|
+
size: 18,
|
|
547
|
+
color: "545B64"
|
|
548
|
+
})
|
|
549
|
+
]
|
|
550
|
+
})
|
|
551
|
+
]
|
|
552
|
+
})
|
|
553
|
+
},
|
|
554
|
+
children: [/* 본문 내용 */]
|
|
555
|
+
}]
|
|
556
|
+
});
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### Header with Logo
|
|
560
|
+
|
|
561
|
+
```javascript
|
|
562
|
+
const header = new Header({
|
|
563
|
+
children: [
|
|
564
|
+
new Paragraph({
|
|
565
|
+
alignment: AlignmentType.LEFT,
|
|
566
|
+
children: [
|
|
567
|
+
new ImageRun({
|
|
568
|
+
type: "png",
|
|
569
|
+
data: fs.readFileSync("aws-logo.png"),
|
|
570
|
+
transformation: { width: 80, height: 30 }
|
|
571
|
+
}),
|
|
572
|
+
new TextRun({ text: " " }), // 간격
|
|
573
|
+
new TextRun({
|
|
574
|
+
text: "Architecture Guide",
|
|
575
|
+
size: 20,
|
|
576
|
+
color: "232F3E"
|
|
577
|
+
})
|
|
578
|
+
]
|
|
579
|
+
})
|
|
580
|
+
]
|
|
581
|
+
});
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
### Footer with Page Numbers
|
|
585
|
+
|
|
586
|
+
```javascript
|
|
587
|
+
const footer = new Footer({
|
|
588
|
+
children: [
|
|
589
|
+
new Paragraph({
|
|
590
|
+
alignment: AlignmentType.CENTER,
|
|
591
|
+
children: [
|
|
592
|
+
new TextRun({ text: "Page ", size: 18 }),
|
|
593
|
+
new TextRun({
|
|
594
|
+
children: [PageNumber.CURRENT]
|
|
595
|
+
}),
|
|
596
|
+
new TextRun({ text: " of ", size: 18 }),
|
|
597
|
+
new TextRun({
|
|
598
|
+
children: [PageNumber.TOTAL_PAGES]
|
|
599
|
+
})
|
|
600
|
+
]
|
|
601
|
+
})
|
|
602
|
+
]
|
|
603
|
+
});
|
|
604
|
+
|
|
605
|
+
// 섹션에 적용
|
|
606
|
+
const doc = new Document({
|
|
607
|
+
sections: [{
|
|
608
|
+
properties: {},
|
|
609
|
+
headers: { default: header },
|
|
610
|
+
footers: { default: footer },
|
|
611
|
+
children: [/* 본문 */]
|
|
612
|
+
}]
|
|
613
|
+
});
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### First Page Different Header
|
|
617
|
+
|
|
618
|
+
```javascript
|
|
619
|
+
const doc = new Document({
|
|
620
|
+
sections: [{
|
|
621
|
+
properties: {
|
|
622
|
+
titlePage: true // 첫 페이지 다른 header/footer 사용
|
|
623
|
+
},
|
|
624
|
+
headers: {
|
|
625
|
+
first: new Header({ // 첫 페이지용
|
|
626
|
+
children: [new Paragraph({ children: [new TextRun("")] })] // 비움
|
|
627
|
+
}),
|
|
628
|
+
default: new Header({ // 나머지 페이지용
|
|
629
|
+
children: [
|
|
630
|
+
new Paragraph({
|
|
631
|
+
alignment: AlignmentType.RIGHT,
|
|
632
|
+
children: [new TextRun({ text: "AWS Guide", size: 18 })]
|
|
633
|
+
})
|
|
634
|
+
]
|
|
635
|
+
})
|
|
636
|
+
},
|
|
637
|
+
footers: {
|
|
638
|
+
first: new Footer({
|
|
639
|
+
children: [new Paragraph({ children: [new TextRun("")] })]
|
|
640
|
+
}),
|
|
641
|
+
default: new Footer({
|
|
642
|
+
children: [/* 페이지 번호 */]
|
|
643
|
+
})
|
|
644
|
+
},
|
|
645
|
+
children: [/* 본문 */]
|
|
646
|
+
}]
|
|
647
|
+
});
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
## Table of Contents (목차)
|
|
653
|
+
|
|
654
|
+
### 자동 목차 생성
|
|
655
|
+
|
|
656
|
+
docx-js에서 자동 목차(TOC)를 생성하려면 `TableOfContents` 클래스를 사용합니다.
|
|
657
|
+
목차는 Heading 스타일이 적용된 텍스트를 자동으로 수집합니다.
|
|
658
|
+
|
|
659
|
+
```javascript
|
|
660
|
+
const { Document, TableOfContents, Paragraph, TextRun,
|
|
661
|
+
HeadingLevel, StyleLevel } = require('docx');
|
|
662
|
+
|
|
663
|
+
const doc = new Document({
|
|
664
|
+
features: {
|
|
665
|
+
updateFields: true // Word에서 열 때 목차 자동 업데이트
|
|
666
|
+
},
|
|
667
|
+
sections: [{
|
|
668
|
+
children: [
|
|
669
|
+
// 목차 제목
|
|
670
|
+
new Paragraph({
|
|
671
|
+
heading: HeadingLevel.HEADING_1,
|
|
672
|
+
children: [new TextRun("목차")]
|
|
673
|
+
}),
|
|
674
|
+
|
|
675
|
+
// 자동 목차
|
|
676
|
+
new TableOfContents("Table of Contents", {
|
|
677
|
+
hyperlink: true,
|
|
678
|
+
headingStyleRange: "1-3", // Heading 1~3까지 포함
|
|
679
|
+
stylesWithLevels: [
|
|
680
|
+
new StyleLevel("Heading1", 1),
|
|
681
|
+
new StyleLevel("Heading2", 2),
|
|
682
|
+
new StyleLevel("Heading3", 3)
|
|
683
|
+
]
|
|
684
|
+
}),
|
|
685
|
+
|
|
686
|
+
// 페이지 나누기
|
|
687
|
+
new Paragraph({ pageBreakBefore: true }),
|
|
688
|
+
|
|
689
|
+
// 본문 시작
|
|
690
|
+
new Paragraph({
|
|
691
|
+
heading: HeadingLevel.HEADING_1,
|
|
692
|
+
children: [new TextRun("1. 개요")]
|
|
693
|
+
}),
|
|
694
|
+
new Paragraph({
|
|
695
|
+
children: [new TextRun("이 문서는...")]
|
|
696
|
+
}),
|
|
697
|
+
|
|
698
|
+
new Paragraph({
|
|
699
|
+
heading: HeadingLevel.HEADING_2,
|
|
700
|
+
children: [new TextRun("1.1 배경")]
|
|
701
|
+
}),
|
|
702
|
+
// ...
|
|
703
|
+
]
|
|
704
|
+
}]
|
|
705
|
+
});
|
|
706
|
+
```
|
|
707
|
+
|
|
708
|
+
### 목차 업데이트 안내
|
|
709
|
+
|
|
710
|
+
**중요**: docx-js로 생성된 목차는 Word에서 문서를 열 때 업데이트됩니다.
|
|
711
|
+
- `updateFields: true` 설정 시 Word가 자동으로 업데이트 여부 묻기
|
|
712
|
+
- 수동 업데이트: Word에서 목차 선택 → 마우스 오른쪽 클릭 → "필드 업데이트"
|
|
713
|
+
|
|
714
|
+
### 수동 목차 생성 (대안)
|
|
715
|
+
|
|
716
|
+
자동 목차가 작동하지 않을 경우, 수동으로 목차를 생성할 수 있습니다:
|
|
717
|
+
|
|
718
|
+
```javascript
|
|
719
|
+
function createManualTOC(sections) {
|
|
720
|
+
// sections: [{ title: "1. 개요", level: 1 }, { title: "1.1 배경", level: 2 }]
|
|
721
|
+
return sections.map(section => {
|
|
722
|
+
const indent = (section.level - 1) * 360; // 레벨별 들여쓰기
|
|
723
|
+
return new Paragraph({
|
|
724
|
+
indent: { left: indent },
|
|
725
|
+
children: [
|
|
726
|
+
new TextRun({
|
|
727
|
+
text: section.title,
|
|
728
|
+
size: section.level === 1 ? 24 : 22
|
|
729
|
+
})
|
|
730
|
+
]
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// 사용 예시
|
|
736
|
+
const tocItems = [
|
|
737
|
+
{ title: "1. 개요", level: 1 },
|
|
738
|
+
{ title: " 1.1 배경", level: 2 },
|
|
739
|
+
{ title: " 1.2 목적", level: 2 },
|
|
740
|
+
{ title: "2. 아키텍처", level: 1 },
|
|
741
|
+
{ title: " 2.1 구성요소", level: 2 }
|
|
742
|
+
];
|
|
743
|
+
|
|
744
|
+
const tocParagraphs = createManualTOC(tocItems);
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
---
|
|
748
|
+
|
|
749
|
+
## 완전한 문서 템플릿 예시
|
|
750
|
+
|
|
751
|
+
```javascript
|
|
752
|
+
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell,
|
|
753
|
+
Header, Footer, ImageRun, TableOfContents, StyleLevel,
|
|
754
|
+
HeadingLevel, AlignmentType, PageNumber, BorderStyle } = require('docx');
|
|
755
|
+
const fs = require('fs');
|
|
756
|
+
|
|
757
|
+
// AWS 스타일 문서 생성 함수
|
|
758
|
+
function createAWSDocument(title, sections) {
|
|
759
|
+
return new Document({
|
|
760
|
+
features: { updateFields: true },
|
|
761
|
+
styles: {
|
|
762
|
+
paragraphStyles: [
|
|
763
|
+
{
|
|
764
|
+
id: "Title",
|
|
765
|
+
name: "Title",
|
|
766
|
+
run: { size: 56, bold: true, color: "232F3E" },
|
|
767
|
+
paragraph: { spacing: { after: 200 }, alignment: AlignmentType.CENTER }
|
|
768
|
+
}
|
|
769
|
+
]
|
|
770
|
+
},
|
|
771
|
+
sections: [{
|
|
772
|
+
properties: { titlePage: true },
|
|
773
|
+
headers: {
|
|
774
|
+
first: new Header({ children: [new Paragraph("")] }),
|
|
775
|
+
default: new Header({
|
|
776
|
+
children: [
|
|
777
|
+
new Paragraph({
|
|
778
|
+
alignment: AlignmentType.RIGHT,
|
|
779
|
+
children: [new TextRun({ text: title, size: 18, color: "545B64" })]
|
|
780
|
+
})
|
|
781
|
+
]
|
|
782
|
+
})
|
|
783
|
+
},
|
|
784
|
+
footers: {
|
|
785
|
+
first: new Footer({ children: [new Paragraph("")] }),
|
|
786
|
+
default: new Footer({
|
|
787
|
+
children: [
|
|
788
|
+
new Paragraph({
|
|
789
|
+
alignment: AlignmentType.CENTER,
|
|
790
|
+
children: [
|
|
791
|
+
new TextRun({ text: "Page " }),
|
|
792
|
+
new TextRun({ children: [PageNumber.CURRENT] }),
|
|
793
|
+
new TextRun({ text: " of " }),
|
|
794
|
+
new TextRun({ children: [PageNumber.TOTAL_PAGES] })
|
|
795
|
+
]
|
|
796
|
+
})
|
|
797
|
+
]
|
|
798
|
+
})
|
|
799
|
+
},
|
|
800
|
+
children: [
|
|
801
|
+
// 표지
|
|
802
|
+
new Paragraph({
|
|
803
|
+
style: "Title",
|
|
804
|
+
children: [new TextRun(title)]
|
|
805
|
+
}),
|
|
806
|
+
new Paragraph({ pageBreakBefore: true }),
|
|
807
|
+
|
|
808
|
+
// 목차
|
|
809
|
+
new Paragraph({
|
|
810
|
+
heading: HeadingLevel.HEADING_1,
|
|
811
|
+
children: [new TextRun("목차")]
|
|
812
|
+
}),
|
|
813
|
+
new TableOfContents("TOC", {
|
|
814
|
+
hyperlink: true,
|
|
815
|
+
headingStyleRange: "1-3"
|
|
816
|
+
}),
|
|
817
|
+
new Paragraph({ pageBreakBefore: true }),
|
|
818
|
+
|
|
819
|
+
// 본문 섹션들
|
|
820
|
+
...sections
|
|
821
|
+
]
|
|
822
|
+
}]
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// 사용 예시
|
|
827
|
+
const doc = createAWSDocument("AWS Lambda 아키텍처 가이드", [
|
|
828
|
+
new Paragraph({
|
|
829
|
+
heading: HeadingLevel.HEADING_1,
|
|
830
|
+
children: [new TextRun("1. 개요")]
|
|
831
|
+
}),
|
|
832
|
+
new Paragraph({
|
|
833
|
+
children: [new TextRun("이 문서는 AWS Lambda를 활용한 서버리스 아키텍처를 설명합니다.")]
|
|
834
|
+
})
|
|
835
|
+
]);
|
|
836
|
+
|
|
837
|
+
Packer.toBuffer(doc).then(buffer => {
|
|
838
|
+
fs.writeFileSync("aws-lambda-guide.docx", buffer);
|
|
839
|
+
});
|
|
840
|
+
```
|
package/src/skills/mcp/SKILL.md
CHANGED
|
@@ -34,6 +34,30 @@ AWS 문서를 검색합니다.
|
|
|
34
34
|
**파라미터:**
|
|
35
35
|
- `url`: 문서 URL (필수)
|
|
36
36
|
|
|
37
|
+
#### recommend
|
|
38
|
+
현재 문서와 관련된 AWS 문서를 추천합니다.
|
|
39
|
+
|
|
40
|
+
**파라미터:**
|
|
41
|
+
- `url`: 현재 조회 중인 문서 URL (필수)
|
|
42
|
+
|
|
43
|
+
**반환:**
|
|
44
|
+
- Highly Rated: 해당 서비스 내 인기 문서
|
|
45
|
+
- New: 최근 추가된 문서 (새 기능 발견에 유용)
|
|
46
|
+
- Similar: 유사 주제 문서
|
|
47
|
+
- Journey: 다른 사용자들이 다음에 본 문서
|
|
48
|
+
|
|
49
|
+
**사용 예시:**
|
|
50
|
+
```
|
|
51
|
+
// Lambda 문서를 읽은 후 관련 문서 추천
|
|
52
|
+
aws-docs_recommend({
|
|
53
|
+
url: "https://docs.aws.amazon.com/lambda/latest/dg/welcome.html"
|
|
54
|
+
})
|
|
55
|
+
// → "Highly Rated": Lambda 모범 사례
|
|
56
|
+
// → "New": 최근 추가된 Lambda 기능
|
|
57
|
+
// → "Similar": Step Functions, EventBridge 문서
|
|
58
|
+
// → "Journey": Lambda 권한, 배포 관련 문서
|
|
59
|
+
```
|
|
60
|
+
|
|
37
61
|
### 사용 시점
|
|
38
62
|
- 서비스 기능 및 제한사항 확인
|
|
39
63
|
- Best Practice 및 권장사항 조회
|
|
@@ -168,3 +192,111 @@ AWS Well-Architected Framework 보안 관련 정보를 제공합니다.
|
|
|
168
192
|
| Amazon ECS | AmazonECS |
|
|
169
193
|
| Amazon VPC | AmazonVPC |
|
|
170
194
|
| AWS Fargate | AWSFargate |
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## 에러 핸들링 전략
|
|
199
|
+
|
|
200
|
+
### 일반 에러 유형
|
|
201
|
+
|
|
202
|
+
| 에러 유형 | 원인 | 해결 방법 |
|
|
203
|
+
|----------|------|----------|
|
|
204
|
+
| **Timeout** | 요청 시간 초과 | 재시도 또는 쿼리 단순화 |
|
|
205
|
+
| **Rate Limit** | 요청 빈도 초과 | 지수 백오프 후 재시도 |
|
|
206
|
+
| **Not Found** | 문서/서비스 없음 | 검색어 변경, 유사 서비스 탐색 |
|
|
207
|
+
| **Access Denied** | 권한 부족 | 일반 지식으로 대체, 제한사항 명시 |
|
|
208
|
+
| **Service Unavailable** | MCP 서버 다운 | 대체 도구 사용, 캐시된 정보 활용 |
|
|
209
|
+
|
|
210
|
+
### Resilience 전략 (도구 실패 시)
|
|
211
|
+
|
|
212
|
+
```
|
|
213
|
+
1단계: 동일 도구 재시도 (1회)
|
|
214
|
+
└── 검색어/파라미터 조정하여 재시도
|
|
215
|
+
|
|
216
|
+
2단계: 대체 도구 사용
|
|
217
|
+
└── search_documentation → read_documentation (URL 직접 접근)
|
|
218
|
+
└── get_pricing → search_documentation ("pricing" 검색)
|
|
219
|
+
|
|
220
|
+
3단계: 일반 지식 활용
|
|
221
|
+
└── MCP 없이 기존 지식으로 답변
|
|
222
|
+
└── 반드시 출처 제한사항 명시
|
|
223
|
+
|
|
224
|
+
4단계: 부분 성공 보고
|
|
225
|
+
└── 성공한 정보 + 실패한 부분 안내
|
|
226
|
+
└── 추가 확인 필요한 항목 목록
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### 에러별 상세 대응
|
|
230
|
+
|
|
231
|
+
#### search_documentation 실패
|
|
232
|
+
|
|
233
|
+
```
|
|
234
|
+
원인: 검색어가 너무 일반적이거나 구체적임
|
|
235
|
+
|
|
236
|
+
대응 순서:
|
|
237
|
+
1. 검색어 변형 (동의어, 약어 추가/제거)
|
|
238
|
+
- "Lambda pricing" → "AWS Lambda cost"
|
|
239
|
+
- "EC2 instance types" → "Amazon EC2 instance families"
|
|
240
|
+
|
|
241
|
+
2. 범위 축소/확대
|
|
242
|
+
- "S3 security best practices" → "S3 bucket policy"
|
|
243
|
+
- "DynamoDB" → "Amazon DynamoDB capacity modes"
|
|
244
|
+
|
|
245
|
+
3. read_documentation으로 대체 (알려진 URL 직접 접근)
|
|
246
|
+
- https://docs.aws.amazon.com/lambda/latest/dg/welcome.html
|
|
247
|
+
- https://aws.amazon.com/lambda/pricing/
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### get_pricing 실패
|
|
251
|
+
|
|
252
|
+
```
|
|
253
|
+
원인: 서비스 코드 오류, 리전 지원 안함
|
|
254
|
+
|
|
255
|
+
대응 순서:
|
|
256
|
+
1. 서비스 코드 확인 (위의 서비스 코드 참조 테이블)
|
|
257
|
+
- "Lambda" → "AWSLambda"
|
|
258
|
+
- "EC2" → "AmazonEC2"
|
|
259
|
+
|
|
260
|
+
2. 리전 파라미터 제거 (기본 리전으로 조회)
|
|
261
|
+
|
|
262
|
+
3. search_documentation으로 가격 페이지 검색
|
|
263
|
+
- "AWS Lambda pricing"
|
|
264
|
+
- "Amazon EC2 on-demand pricing"
|
|
265
|
+
|
|
266
|
+
4. 공식 가격 페이지 URL 안내
|
|
267
|
+
- https://aws.amazon.com/lambda/pricing/
|
|
268
|
+
- https://aws.amazon.com/ec2/pricing/
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Well-Architected Security MCP 실패
|
|
272
|
+
|
|
273
|
+
```
|
|
274
|
+
원인: 카테고리 미지원, 아키텍처 설명 불충분
|
|
275
|
+
|
|
276
|
+
대응 순서:
|
|
277
|
+
1. 카테고리 명시적 지정
|
|
278
|
+
- "identity", "detection", "infrastructure", "data", "incident"
|
|
279
|
+
|
|
280
|
+
2. 아키텍처 설명 보강
|
|
281
|
+
- 서비스 목록, 데이터 흐름, 네트워크 구성 추가
|
|
282
|
+
|
|
283
|
+
3. AWS Well-Architected Tool 문서 직접 참조
|
|
284
|
+
- search_documentation("Well-Architected security pillar")
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### 사용자 커뮤니케이션
|
|
288
|
+
|
|
289
|
+
MCP 도구 실패 시 사용자에게 알리는 방법:
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
✅ 좋은 예:
|
|
293
|
+
"AWS Lambda 가격 정보를 MCP로 조회했으나 현재 서비스가 응답하지 않습니다.
|
|
294
|
+
일반적인 가격 정보를 안내드리며, 정확한 최신 가격은
|
|
295
|
+
https://aws.amazon.com/lambda/pricing/ 에서 확인해주세요."
|
|
296
|
+
|
|
297
|
+
❌ 나쁜 예:
|
|
298
|
+
"MCP 도구 에러가 발생했습니다."
|
|
299
|
+
"가격 정보를 가져올 수 없습니다."
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**원칙**: 에러 메시지보다 해결책과 대안을 제시하세요.
|