refactor(topics): 멀티 에이전트용 지식 재편 — _Common(공통 기본기) + Domain_* 구조
에이전트 8종(대화형/프로그래머 C·S/디자이너/설계자/기획자/QA/PD/PM)에게 [공통 기본 능력 + 롤별 Specialty] 2층으로 지식을 주입하기 위한 재분류. 문서 내용·포맷은 무수정, 폴더 이동만 (6,372개 문서 수 보존 확인). - Topic_Programming → Domain_Programming (내부 구조 보존) - Topic_Graphic → Domain_Design - Topic_Business → Domain_Product - Topic_General → Domain_General - _Common 신설: Math(구 Topic_Math_Specialty), Reasoning(구 General/From_Thinking & Reasoning), Reasoning_Creativity(구 General/From_창의성), Communication(Poetic_Blog_Writing + From_writing) - 타 도메인의 From_* 폴더는 유지 (출처 표기일 뿐, 이미 도메인에 맞게 분류된 문서) - 빈 폴더 정리 (memory/procedures) - 에이전트→폴더 매핑은 workspace의 .astra/agent-knowledge-map.json (9개 에이전트) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
---
|
||||
id: wiki-2026-0508-사용자-제작-콘텐츠-ugc
|
||||
title: 사용자 제작 콘텐츠 (UGC)
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [User-Generated Content, UGC, User Content]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [ugc, content, moderation, platform, architecture]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: typescript
|
||||
framework: nextjs
|
||||
---
|
||||
|
||||
# 사용자 제작 콘텐츠 (UGC)
|
||||
|
||||
## 매 한 줄
|
||||
> **"매 user 의 platform 에서 create 하는 content"**. 매 Web 2.0 (2004) 의 core concept — Wikipedia, YouTube, Reddit 의 fuel. 2026 년 매 LLM-generated content + human content 의 mix 의 challenge — 매 provenance, moderation, copyright 의 critical.
|
||||
|
||||
## 매 핵심
|
||||
|
||||
### 매 lifecycle
|
||||
1. **Creation**: 매 upload, post, comment.
|
||||
2. **Storage**: 매 object storage (S3, R2) + DB metadata.
|
||||
3. **Moderation**: 매 automated (Perspective API, OpenAI Moderation) + human review.
|
||||
4. **Distribution**: 매 CDN + recommendation algorithm.
|
||||
5. **Lifecycle end**: 매 delete, archive, takedown (DMCA).
|
||||
|
||||
### 매 challenges (2026)
|
||||
- **AI-generated content**: 매 deepfake, slop — provenance (C2PA) 의 필요.
|
||||
- **Moderation scale**: 매 LLM moderator 의 cost-effective.
|
||||
- **Copyright**: 매 training data 의 lawsuit (NYT v OpenAI 등).
|
||||
- **Liability**: 매 Section 230 (US), DSA (EU) 의 compliance.
|
||||
|
||||
### 매 응용
|
||||
1. Social media — 매 post, video, comment.
|
||||
2. Reviews/ratings — 매 e-commerce.
|
||||
3. Forums — 매 Reddit, Discord, HN.
|
||||
4. Wiki — 매 collaborative knowledge.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Upload + S3 presigned URL
|
||||
```typescript
|
||||
// API: generate presigned URL
|
||||
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
|
||||
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
|
||||
|
||||
export async function POST(req: Request) {
|
||||
const { userId } = await authenticate(req);
|
||||
const { filename, contentType } = await req.json();
|
||||
|
||||
if (!ALLOWED_TYPES.includes(contentType)) {
|
||||
return Response.json({ error: 'invalid type' }, { status: 400 });
|
||||
}
|
||||
|
||||
const key = `uploads/${userId}/${crypto.randomUUID()}-${filename}`;
|
||||
const url = await getSignedUrl(
|
||||
s3,
|
||||
new PutObjectCommand({ Bucket: 'ugc', Key: key, ContentType: contentType }),
|
||||
{ expiresIn: 300 }
|
||||
);
|
||||
|
||||
return Response.json({ url, key });
|
||||
}
|
||||
```
|
||||
|
||||
### Moderation pipeline (text)
|
||||
```typescript
|
||||
import OpenAI from 'openai';
|
||||
const openai = new OpenAI();
|
||||
|
||||
async function moderateText(text: string) {
|
||||
const result = await openai.moderations.create({
|
||||
model: 'omni-moderation-latest',
|
||||
input: text,
|
||||
});
|
||||
const r = result.results[0];
|
||||
if (r.flagged) {
|
||||
return { allowed: false, categories: r.categories };
|
||||
}
|
||||
return { allowed: true };
|
||||
}
|
||||
```
|
||||
|
||||
### Image moderation (vision)
|
||||
```typescript
|
||||
// 매 NSFW + violence detection — Claude Opus 4.7 vision.
|
||||
import Anthropic from '@anthropic-ai/sdk';
|
||||
const client = new Anthropic();
|
||||
|
||||
async function moderateImage(imageUrl: string) {
|
||||
const res = await client.messages.create({
|
||||
model: 'claude-opus-4-7',
|
||||
max_tokens: 200,
|
||||
messages: [{
|
||||
role: 'user',
|
||||
content: [
|
||||
{ type: 'image', source: { type: 'url', url: imageUrl } },
|
||||
{ type: 'text', text: 'Classify this image: SFW, NSFW, violence, hate, none. JSON only.' },
|
||||
],
|
||||
}],
|
||||
});
|
||||
return JSON.parse(res.content[0].text);
|
||||
}
|
||||
```
|
||||
|
||||
### Provenance (C2PA)
|
||||
```typescript
|
||||
// 매 image 의 origin metadata — AI 생성 여부 의 verify.
|
||||
import { read } from 'c2pa';
|
||||
|
||||
async function checkProvenance(imageUrl: string) {
|
||||
const c2pa = await read(imageUrl);
|
||||
if (!c2pa) return { verified: false };
|
||||
|
||||
const manifest = c2pa.manifestStore?.activeManifest;
|
||||
return {
|
||||
verified: c2pa.manifestStore?.validationStatus === 'valid',
|
||||
generator: manifest?.claimGenerator,
|
||||
aiGenerated: manifest?.assertions.some((a) => a.label.startsWith('c2pa.actions.ai_')),
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Vote + ranking
|
||||
```typescript
|
||||
// 매 Reddit-style — Wilson score interval.
|
||||
function wilsonScore(up: number, down: number) {
|
||||
const n = up + down;
|
||||
if (n === 0) return 0;
|
||||
const z = 1.96; // 95% confidence
|
||||
const p = up / n;
|
||||
return (p + z*z/(2*n) - z * Math.sqrt((p*(1-p) + z*z/(4*n))/n)) / (1 + z*z/n);
|
||||
}
|
||||
|
||||
const posts = await db.post.findMany();
|
||||
posts.sort((a, b) => wilsonScore(b.up, b.down) - wilsonScore(a.up, a.down));
|
||||
```
|
||||
|
||||
### Rate limit (anti-spam)
|
||||
```typescript
|
||||
import { Ratelimit } from '@upstash/ratelimit';
|
||||
import { Redis } from '@upstash/redis';
|
||||
|
||||
const ratelimit = new Ratelimit({
|
||||
redis: Redis.fromEnv(),
|
||||
limiter: Ratelimit.slidingWindow(10, '1 h'), // 10 posts/hour
|
||||
});
|
||||
|
||||
const { success } = await ratelimit.limit(`post:${userId}`);
|
||||
if (!success) throw new Error('rate limit');
|
||||
```
|
||||
|
||||
### DMCA takedown flow
|
||||
```typescript
|
||||
async function handleDmcaTakedown(claim: DmcaClaim) {
|
||||
// 1. Hide content immediately
|
||||
await db.content.update({
|
||||
where: { id: claim.contentId },
|
||||
data: { status: 'TAKEDOWN_PENDING' },
|
||||
});
|
||||
|
||||
// 2. Notify uploader (counter-notice option)
|
||||
await notifyUploader(claim);
|
||||
|
||||
// 3. Log for audit
|
||||
await db.dmcaLog.create({ data: { ...claim, processedAt: new Date() } });
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| Content type | Moderation |
|
||||
|---|---|
|
||||
| Text comment | OpenAI Moderation API + human review |
|
||||
| Image | Claude vision + perceptual hash (NCMEC PhotoDNA) |
|
||||
| Video | Frame sampling + ML + community flag |
|
||||
| Long-form (article) | Pre-publish review + post-flag |
|
||||
| Realtime chat | Profanity filter + ML in pipeline |
|
||||
|
||||
**기본값**: 매 LLM moderation + human escalation queue.
|
||||
|
||||
## 🔗 Graph
|
||||
- Adjacent: [[Content Moderation]] · [[C2PA]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: user-content platform 의 moderation, ranking, provenance 의 design 시.
|
||||
**언제 X**: closed editorial content (news site) — 매 UGC 무관.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **No moderation**: 매 spam/abuse 의 platform 의 destroy.
|
||||
- **Heavy pre-moderation only**: 매 latency + cost — 매 hybrid 의 better.
|
||||
- **Naive ranking** (`order by votes desc`): 매 first-mover advantage — Wilson score 의 better.
|
||||
- **Ignore copyright**: 매 DMCA 의 ignore — legal liability.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified (OpenAI Moderation docs; C2PA spec 2.0; OWASP UGC guidelines; DSA 2024).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — UGC lifecycle + moderation + C2PA |
|
||||
Reference in New Issue
Block a user