Skip to content

Commit de7d2b2

Browse files
trz-21claude
andcommitted
feat: 분석 결과 전문성·신뢰도 보강 — 방법론·맥락 카피·면책
- 방법론 블록(접이식): 데이터 출처(쿠팡 공개 리뷰) + 표본 수(총 리뷰/상품 수) + AI 분류 안내 - 섹션별 맥락 카피: TOP3/경쟁사 약점/구매 결정 요인/불만·긍정/평점 분포 각 "왜 중요한가" 설명 - 면책 고지: "참고용 인사이트, 원문 리뷰 병행 확인" 정직한 한계 고지 - 기존 테스트 유지 + 보강(8 tests), 76개 전체 통과 Refs #23 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent ba4b365 commit de7d2b2

2 files changed

Lines changed: 92 additions & 8 deletions

File tree

frontend/src/features/analysis/components/InsightReport.test.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,24 @@ describe('InsightReport', () => {
5959
expect(screen.getByText('무선 청소기')).toBeInTheDocument();
6060
expect(screen.getByText(/4\.3/)).toBeInTheDocument();
6161
});
62+
63+
it('renders the methodology sample size', () => {
64+
render(<InsightReport result={result} />);
65+
expect(screen.getByText('분석 방법 · 데이터 출처')).toBeInTheDocument();
66+
expect(
67+
screen.getByText(/ : 120 \( 1\)/),
68+
).toBeInTheDocument();
69+
});
70+
71+
it('renders a section description', () => {
72+
render(<InsightReport result={result} />);
73+
expect(
74+
screen.getByText(/ /),
75+
).toBeInTheDocument();
76+
});
77+
78+
it('renders the disclaimer', () => {
79+
render(<InsightReport result={result} />);
80+
expect(screen.getByText(/ /)).toBeInTheDocument();
81+
});
6282
});

frontend/src/features/analysis/components/InsightReport.tsx

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,60 @@ function severityVariant(severity: string): NonNullable<BadgeProps['variant']> {
1515
return SEVERITY_VARIANT[severity] ?? 'neutral';
1616
}
1717

18-
function Section({ title, children }: { title: string; children: React.ReactNode }) {
18+
function Section({
19+
title,
20+
description,
21+
children,
22+
}: {
23+
title: string;
24+
description?: string;
25+
children: React.ReactNode;
26+
}) {
1927
return (
2028
<Card className="p-6">
21-
<h2 className="mb-4 text-lg font-semibold text-gray-900">{title}</h2>
22-
{children}
29+
<h2 className="text-lg font-semibold text-gray-900">{title}</h2>
30+
{description ? (
31+
<p className="mt-1 text-sm text-gray-500">{description}</p>
32+
) : null}
33+
<div className="mt-4">{children}</div>
2334
</Card>
2435
);
2536
}
2637

38+
function Methodology({ products }: { products: ProductSummary[] }) {
39+
const totalReviews = products.reduce((sum, p) => sum + p.total_reviews, 0);
40+
const productCount = products.length;
41+
return (
42+
<Card className="border-brand-100 bg-brand-50 p-5">
43+
<details>
44+
<summary className="flex cursor-pointer items-center gap-2 font-medium text-gray-900">
45+
<Badge variant="info">info</Badge>
46+
분석 방법 · 데이터 출처
47+
</summary>
48+
<div className="mt-3 flex flex-col gap-2 text-sm text-gray-600">
49+
<p>
50+
쿠팡 공개 리뷰를 자동 수집해, 한국어 문맥 기준으로 AI가 불만·강점 표현을
51+
분류·집계했습니다.
52+
</p>
53+
<p className="font-medium text-gray-800">
54+
분석 표본: 총 {totalReviews}개 리뷰 (상품 {productCount}개)
55+
</p>
56+
<p>표본이 많을수록 패턴 신뢰도가 높아집니다.</p>
57+
</div>
58+
</details>
59+
</Card>
60+
);
61+
}
62+
63+
function Disclaimer() {
64+
return (
65+
<div className="border-t border-gray-100 pt-4 text-xs text-gray-500">
66+
본 분석은 공개 리뷰를 AI가 자동 분류·집계한 결과로 참고용 인사이트입니다. 중요한
67+
의사결정 전 원문 리뷰를 함께 확인하시기 바랍니다.
68+
</div>
69+
);
70+
}
71+
2772
function EmptyHint() {
2873
return <p className="text-sm text-gray-500">데이터 없음</p>;
2974
}
@@ -73,7 +118,12 @@ export function InsightReport({ result }: InsightReportProps) {
73118

74119
return (
75120
<div className="flex flex-col gap-6">
76-
<Section title="고쳐야 할 것 TOP 3">
121+
<Methodology products={products} />
122+
123+
<Section
124+
title="고쳐야 할 것 TOP 3"
125+
description="경쟁사 리뷰의 불만 패턴 중 개선 효과가 큰 순서입니다. 위에서부터 손대면 경쟁 우위를 빠르게 확보할 수 있습니다."
126+
>
77127
{improvements.length === 0 ? (
78128
<EmptyHint />
79129
) : (
@@ -93,7 +143,10 @@ export function InsightReport({ result }: InsightReportProps) {
93143
)}
94144
</Section>
95145

96-
<Section title="경쟁사 약점">
146+
<Section
147+
title="경쟁사 약점"
148+
description="경쟁사가 반복적으로 지적받는 지점입니다. 내 상품이 파고들 기회입니다."
149+
>
97150
{insights.competitor_weaknesses.length === 0 ? (
98151
<EmptyHint />
99152
) : (
@@ -108,7 +161,10 @@ export function InsightReport({ result }: InsightReportProps) {
108161
)}
109162
</Section>
110163

111-
<Section title="구매 결정 요인">
164+
<Section
165+
title="구매 결정 요인"
166+
description="고객이 구매를 결정할 때 실제로 언급한 핵심 요소입니다. 상세페이지·마케팅 메시지에 활용하세요."
167+
>
112168
{insights.purchase_drivers.length === 0 ? (
113169
<EmptyHint />
114170
) : (
@@ -125,7 +181,10 @@ export function InsightReport({ result }: InsightReportProps) {
125181
)}
126182
</Section>
127183

128-
<Section title="반복 불만 / 긍정 요인">
184+
<Section
185+
title="반복 불만 / 긍정 요인"
186+
description="리뷰에 자주 등장한 표현을 빈도순으로 집계했습니다."
187+
>
129188
<div className="grid gap-6 sm:grid-cols-2">
130189
<div>
131190
<h3 className="mb-2 text-sm font-medium text-gray-900">반복 불만</h3>
@@ -163,7 +222,10 @@ export function InsightReport({ result }: InsightReportProps) {
163222
</div>
164223
</Section>
165224

166-
<Section title="평점 분포">
225+
<Section
226+
title="평점 분포"
227+
description="수집된 리뷰의 별점 분포입니다."
228+
>
167229
{products.length === 0 ? (
168230
<EmptyHint />
169231
) : (
@@ -174,6 +236,8 @@ export function InsightReport({ result }: InsightReportProps) {
174236
</div>
175237
)}
176238
</Section>
239+
240+
<Disclaimer />
177241
</div>
178242
);
179243
}

0 commit comments

Comments
 (0)