Ax Wave/Dx

UX UI 관련 긍/부정 여론 분석하기

김준아 2025. 9. 25. 14:04

좋아하는 회사의 UX/UI관점 긍부정 여론을 조사해서 분석 해보라고 하셔서

내가정말좋아하는 유튜브 코리아 ㅎㅎ 분석해봄,,, 근데 여론은 llm에게 물어보라고하셔서 일단 수집했고 다음과 같은 방식으로 분석했다. 주피터 썼음 그리고 최신 기사만 크롤링 해달라고했다던지 그런건 아니라서 이 결과가 신빙성이 있는건 전~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~혀 아니고 그냥 분석을 했다!! 잘 했 다 정도~로...... 당연히.(당연한게 아니라면 미안합니다) 나의 똑쟁이 클로드의 도움을 많이 받았다 ㅎㅎ정말 많이 ㅎㅎ...


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.graph_objects as go
import plotly.express as px
from plotly.subplots import make_subplots
import warnings
warnings.filterwarnings('ignore')

# 한글 폰트 설정
plt.rcParams['font.family'] = 'DejaVu Sans'
plt.rcParams['axes.unicode_minus'] = False

# ================================================================
# 📊 유튜브 UX 개선 인사이트 분석
# ================================================================

# 데이터 생성
데이터는 비밀!!

df = pd.DataFrame(data)

class YouTubeUXAnalyzer:
    def __init__(self, df):
        self.df = df
        self.sentiment_scores = {'긍정': 1, '부정': -1}
        print("🎬 유튜브 UX 개선 인사이트 분석을 시작합니다!")
        print(f"📊 총 {len(df)}개의 피드백을 분석합니다\n")
    
    def create_overview_dashboard(self):
        """📊 전체 현황 대시보드"""
        print("📊 전체 현황 분석 중...")
        
        # 기본 통계
        total_feedback = len(self.df)
        negative_ratio = (self.df['감성'] == '부정').mean() * 100
        positive_ratio = (self.df['감성'] == '긍정').mean() * 100
        
        # 서브플롯 생성
        fig = make_subplots(
            rows=2, cols=2,
            specs=[[{"type": "pie"}, {"type": "bar"}],
                   [{"type": "bar"}, {"type": "bar"}]],
            subplot_titles=['🎭 전체 감성 분포', '📰 출처별 피드백 수', 
                          '🎯 범주별 감성 분포', '⭐ 기능별 문제점 수']
        )
        
        # 1. 전체 감성 분포
        sentiment_counts = self.df['감성'].value_counts()
        colors = ['red' if x == '부정' else 'green' for x in sentiment_counts.index]
        
        fig.add_trace(go.Pie(
            labels=sentiment_counts.index,
            values=sentiment_counts.values,
            name="전체 감성",
            marker_colors=colors,
            textinfo='label+percent'
        ), row=1, col=1)
        
        # 2. 출처별 피드백 수
        source_counts = self.df['출처'].value_counts()
        fig.add_trace(go.Bar(
            x=source_counts.index,
            y=source_counts.values,
            name="출처별 피드백",
            marker_color='lightblue'
        ), row=1, col=2)
        
        # 3. 범주별 감성 분포
        category_sentiment = pd.crosstab(self.df['범주'], self.df['감성'])
        fig.add_trace(go.Bar(
            x=category_sentiment.index,
            y=category_sentiment['부정'],
            name="부정",
            marker_color='red',
            opacity=0.7
        ), row=2, col=1)
        
        fig.add_trace(go.Bar(
            x=category_sentiment.index,
            y=category_sentiment['긍정'],
            name="긍정", 
            marker_color='green',
            opacity=0.7
        ), row=2, col=1)
        
        # 4. 주요 문제 기능들
        problem_functions = self.df[self.df['감성'] == '부정']['기능'].value_counts().head(6)
        fig.add_trace(go.Bar(
            x=problem_functions.values,
            y=problem_functions.index,
            orientation='h',
            name="문제 기능",
            marker_color='coral'
        ), row=2, col=2)
        
        fig.update_layout(
            title="🎬 유튜브 UX 피드백 전체 현황",
            width=1400,
            height=800,
            showlegend=True
        )
        fig.show()
        
        # 핵심 통계 출력
        print(f"\n📈 핵심 통계:")
        print(f"   • 전체 피드백: {total_feedback}개")
        print(f"   • 부정적 피드백: {negative_ratio:.1f}% ({int(negative_ratio/100*total_feedback)}개)")
        print(f"   • 긍정적 피드백: {positive_ratio:.1f}% ({int(positive_ratio/100*total_feedback)}개)")
        print(f"   • 가장 많은 불만 영역: {category_sentiment['부정'].idxmax()}")
    
    def create_priority_matrix(self):
        """🎯 개선 우선순위 매트릭스"""
        print("🎯 개선 우선순위 분석 중...")
        
        # 범주별 문제점 분석
        category_analysis = []
        
        for category in self.df['범주'].unique():
            cat_data = self.df[self.df['범주'] == category]
            
            total_feedback = len(cat_data)
            negative_count = len(cat_data[cat_data['감성'] == '부정'])
            negative_ratio = negative_count / total_feedback * 100 if total_feedback > 0 else 0
            
            # 심각도 점수 (부정 비율 + 피드백 수)
            severity_score = negative_ratio + (total_feedback * 10)
            
            category_analysis.append({
                '범주': category,
                '전체_피드백수': total_feedback,
                '부정_피드백수': negative_count,
                '부정_비율': negative_ratio,
                '심각도_점수': severity_score
            })
        
        priority_df = pd.DataFrame(category_analysis)
        priority_df = priority_df.sort_values('심각도_점수', ascending=False)
        
        # 우선순위 매트릭스 시각화
        fig = px.scatter(priority_df, 
                        x='전체_피드백수', 
                        y='부정_비율',
                        size='심각도_점수',
                        color='범주',
                        hover_data=['부정_피드백수'],
                        title='🎯 개선 우선순위 매트릭스',
                        labels={
                            '전체_피드백수': '피드백 수 (많을수록 중요도 높음)',
                            '부정_비율': '부정 비율 % (높을수록 심각)',
                            '범주': '기능 범주'
                        })
        
        # 사분면 경계선 추가
        avg_feedback = priority_df['전체_피드백수'].mean()
        avg_negative = priority_df['부정_비율'].mean()
        
        fig.add_hline(y=avg_negative, line_dash="dash", line_color="gray", opacity=0.5)
        fig.add_vline(x=avg_feedback, line_dash="dash", line_color="gray", opacity=0.5)
        
        # 사분면 텍스트 추가
        fig.add_annotation(x=priority_df['전체_피드백수'].max()*0.8, 
                          y=priority_df['부정_비율'].max()*0.9,
                          text="🚨 최우선<br>개선 필요", showarrow=False,
                          font=dict(size=12, color="red"))
        
        fig.add_annotation(x=priority_df['전체_피드백수'].max()*0.8, 
                          y=priority_df['부정_비율'].min()*1.1,
                          text="💡 기능<br>확장 고려", showarrow=False,
                          font=dict(size=12, color="green"))
        
        fig.update_layout(width=1000, height=600)
        fig.show()
        
        # 우선순위 순서 출력
        print(f"\n🏆 개선 우선순위 (심각도 점수 기준):")
        for i, row in priority_df.iterrows():
            rank = priority_df.index.get_loc(i) + 1
            print(f"   {rank}. {row['범주']}: 심각도 {row['심각도_점수']:.1f} "
                  f"(부정 {row['부정_비율']:.1f}%, 피드백 {row['전체_피드백수']}개)")
        
        return priority_df
    
    def create_detailed_issue_analysis(self):
        """🔍 세부 이슈 분석"""
        print("🔍 세부 이슈 분석 중...")
        
        # 출처별 감성 차이
        source_sentiment = pd.crosstab(self.df['출처'], self.df['감성'], normalize='index') * 100
        
        # 주요 문제점별 상세 분석
        negative_df = self.df[self.df['감성'] == '부정']
        issue_categories = negative_df.groupby(['범주', '기능']).size().reset_index(name='count')
        issue_categories = issue_categories.sort_values('count', ascending=False)
        
        # 시각화
        fig, axes = plt.subplots(2, 2, figsize=(16, 12))
        
        # 1. 출처별 감성 차이
        source_sentiment.plot(kind='bar', ax=axes[0,0], color=['red', 'green'])
        axes[0,0].set_title('📰 출처별 감성 분포 (%)')
        axes[0,0].set_xlabel('출처')
        axes[0,0].set_ylabel('비율 (%)')
        axes[0,0].legend(['부정', '긍정'])
        axes[0,0].tick_params(axis='x', rotation=45)
        
        # 2. 상위 문제점들
        top_issues = issue_categories.head(8)
        issue_labels = [f"{row['범주']}\n{row['기능']}" for _, row in top_issues.iterrows()]
        axes[0,1].barh(issue_labels, top_issues['count'], color='coral')
        axes[0,1].set_title('🚨 주요 문제점 TOP 8')
        axes[0,1].set_xlabel('피드백 수')
        
        # 3. 범주별 부정 비율
        category_negative = self.df.groupby('범주')['감성'].apply(lambda x: (x == '부정').mean() * 100)
        category_negative = category_negative.sort_values(ascending=True)
        axes[1,0].barh(category_negative.index, category_negative.values, 
                      color=['red' if x > 50 else 'orange' if x > 30 else 'yellow' for x in category_negative.values])
        axes[1,0].set_title('📊 범주별 부정 피드백 비율 (%)')
        axes[1,0].set_xlabel('부정 비율 (%)')
        axes[1,0].axvline(x=50, color='red', linestyle='--', alpha=0.5, label='50% 기준선')
        
        # 4. 기능 개선 시급도
        function_urgency = negative_df['기능'].value_counts().head(10)
        axes[1,1].bar(range(len(function_urgency)), function_urgency.values, color='darkred')
        axes[1,1].set_title('⚡ 개선 시급 기능 TOP 10')
        axes[1,1].set_ylabel('불만 건수')
        axes[1,1].set_xticks(range(len(function_urgency)))
        axes[1,1].set_xticklabels(function_urgency.index, rotation=45, ha='right')
        
        plt.tight_layout()
        plt.show()
        
        # 핵심 인사이트 출력
        print(f"\n🔍 세부 인사이트:")
        most_critical_source = source_sentiment['부정'].idxmax()
        most_critical_category = category_negative.idxmax()
        
        print(f"   📰 가장 비판적인 출처: {most_critical_source} ({source_sentiment.loc[most_critical_source, '부정']:.1f}% 부정)")
        print(f"   🎯 가장 문제가 많은 범주: {most_critical_category} ({category_negative[most_critical_category]:.1f}% 부정)")
        print(f"   🚨 최대 문제점: {function_urgency.index[0]} ({function_urgency.iloc[0]}건 불만)")
    
    def create_improvement_roadmap(self):
        """🛣️ 개선 로드맵 제안"""
        print("🛣️ 개선 로드맵 생성 중...")
        
        # 문제점을 심각도와 난이도로 분류
        negative_df = self.df[self.df['감성'] == '부정']
        
        # 각 문제에 대한 개선 방안 매핑
        improvement_suggestions = {
            '스와이프 기능': {'난이도': '중', '영향도': '높음', '개선방안': 'A/B 테스트로 최적 UX 찾기'},
            '미니 플레이어': {'난이도': '낮음', '영향도': '중간', '개선방안': '사용자 설정으로 선택 가능하게'},
            '영상 배속 조절': {'난이도': '낮음', '영향도': '중간', '개선방안': '직관적 슬라이더 UI로 변경'},
            '백그라운드 재생': {'난이도': '낮음', '영향도': '높음', '개선방안': '기술적 버그 수정 우선'},
            '재생바': {'난이도': '중', '영향도': '높음', '개선방안': '쇼츠에도 미니 재생바 추가'},
            '채널 이동': {'난이도': '낮음', '영향도': '중간', '개선방안': '원터치 채널 이동 버튼 추가'},
            '악성 댓글': {'난이도': '높음', '영향도': '높음', '개선방안': 'AI 기반 댓글 필터링 강화'},
            '로딩 오류': {'난이도': '중', '영향도': '높음', '개선방안': '서버 안정성 및 캐싱 개선'},
            'UI 변경': {'난이도': '낮음', '영향도': '중간', '개선방안': '사용자 맞춤 레이아웃 옵션'},
            '댓글 UI': {'난이도': '낮음', '영향도': '중간', '개선방안': '댓글창 크기 조절 가능하게'},
            '추천 방식': {'난이도': '높음', '영향도': '높음', '개선방안': '다양성 알고리즘 도입'},
            '가족 요금제': {'난이도': '낮음', '영향도': '높음', '개선방안': '한국 시장 가족요금제 출시'},
            '콘텐츠 신뢰성': {'난이도': '높음', '영향도': '높음', '개선방안': '팩트체크 시스템 도입'}
        }
        
        # 로드맵 데이터 생성
        roadmap_data = []
        for func in negative_df['기능'].unique():
            count = len(negative_df[negative_df['기능'] == func])
            if func in improvement_suggestions:
                suggestion = improvement_suggestions[func]
                
                # 우선순위 점수 계산 (불만 건수 + 영향도 + 난이도 역산)
                impact_score = {'높음': 3, '중간': 2, '낮음': 1}[suggestion['영향도']]
                difficulty_score = {'낮음': 3, '중': 2, '높음': 1}[suggestion['난이도']]
                priority_score = count * 2 + impact_score * 3 + difficulty_score * 2
                
                roadmap_data.append({
                    '기능': func,
                    '불만_건수': count,
                    '난이도': suggestion['난이도'],
                    '영향도': suggestion['영향도'],
                    '우선순위_점수': priority_score,
                    '개선방안': suggestion['개선방안']
                })
        
        roadmap_df = pd.DataFrame(roadmap_data)
        roadmap_df = roadmap_df.sort_values('우선순위_점수', ascending=False)
        
        # 로드맵 시각화
        fig = px.scatter(roadmap_df,
                        x='불만_건수',
                        y='우선순위_점수', 
                        size='우선순위_점수',
                        color='영향도',
                        hover_name='기능',
                        hover_data=['난이도', '개선방안'],
                        title='🛣️ 유튜브 UX 개선 로드맵',
                        labels={
                            '불만_건수': '사용자 불만 건수',
                            '우선순위_점수': '개선 우선순위 점수',
                            '영향도': '비즈니스 영향도'
                        },
                        color_discrete_map={'높음': 'red', '중간': 'orange', '낮음': 'yellow'})
        
        fig.update_layout(width=1200, height=600)
        fig.show()
        
        # 단계별 로드맵 출력
        print(f"\n🚀 3단계 개선 로드맵:")
        
        # 1단계: 빠른 승리 (난이도 낮음 + 영향도 높음)
        phase1 = roadmap_df[(roadmap_df['난이도'] == '낮음') & (roadmap_df['영향도'] == '높음')]
        print(f"\n   📅 1단계 (Quick Wins - 1-2개월):")
        for _, row in phase1.head(3).iterrows():
            print(f"      • {row['기능']}: {row['개선방안']}")
        
        # 2단계: 중요한 개선 (중간 난이도)
        phase2 = roadmap_df[roadmap_df['난이도'] == '중']
        print(f"\n   📅 2단계 (Major Improvements - 3-6개월):")
        for _, row in phase2.head(3).iterrows():
            print(f"      • {row['기능']}: {row['개선방안']}")
        
        # 3단계: 장기 프로젝트 (높은 난이도)
        phase3 = roadmap_df[roadmap_df['난이도'] == '높음'].sort_values('우선순위_점수', ascending=False)
        print(f"\n   📅 3단계 (Long-term Projects - 6-12개월):")
        for _, row in phase3.head(3).iterrows():
            print(f"      • {row['기능']}: {row['개선방안']}")
        
        return roadmap_df
    
    def create_sentiment_flow_sankey(self):
        """🌊 감정 흐름 산키 다이어그램"""
        print("🌊 감정 흐름 산키 다이어그램 생성 중...")
        
        # 출처 → 범주 → 감성 흐름 생성
        flow_data = []
        
        for _, row in self.df.iterrows():
            flow_data.append({
                'source': f"출처_{row['출처']}",
                'target': f"범주_{row['범주']}",
                'value': 1
            })
            flow_data.append({
                'source': f"범주_{row['범주']}",
                'target': f"감성_{row['감성']}",
                'value': 1
            })
        
        flow_df = pd.DataFrame(flow_data)
        flow_summary = flow_df.groupby(['source', 'target']).sum().reset_index()
        
        # 모든 노드 수집
        all_nodes = list(set(flow_summary['source'].tolist() + flow_summary['target'].tolist()))
        node_dict = {node: i for i, node in enumerate(all_nodes)}
        
        # 노드 색상 설정
        node_colors = []
        for node in all_nodes:
            if '출처_' in node:
                node_colors.append('lightblue')
            elif '범주_' in node:
                node_colors.append('lightgreen')
            elif '감성_긍정' in node:
                node_colors.append('green')
            elif '감성_부정' in node:
                node_colors.append('red')
            else:
                node_colors.append('gray')
        
        # 산키 다이어그램
        fig = go.Figure(data=[go.Sankey(
            node=dict(
                pad=15,
                thickness=20,
                line=dict(color="black", width=0.5),
                label=all_nodes,
                color=node_colors
            ),
            link=dict(
                source=[node_dict[src] for src in flow_summary['source']],
                target=[node_dict[tgt] for tgt in flow_summary['target']],
                value=flow_summary['value'].tolist(),
                color="rgba(0, 100, 200, 0.4)"
            )
        )])
        
        fig.update_layout(
            title="🌊 유튜브 피드백 흐름: 출처 → 범주 → 감성",
            font_size=10,
            width=1200,
            height=600
        )
        fig.show()
    
    def generate_executive_summary(self):
        """📋 경영진 요약 보고서"""
        print("📋 경영진 요약 보고서 생성 중...")
        
        total_feedback = len(self.df)
        negative_count = len(self.df[self.df['감성'] == '부정'])
        negative_ratio = negative_count / total_feedback * 100
        
        # 가장 큰 문제점들
        top_issues = self.df[self.df['감성'] == '부정']['범주'].value_counts()
        critical_functions = self.df[self.df['감성'] == '부정']['기능'].value_counts().head(5)
        
        print(f"""
📊 ============ 유튜브 UX 개선 요약 보고서 ============
        
🎯 핵심 지표:
   • 전체 피드백: {total_feedback}건 분석
   • 부정적 피드백: {negative_count}건 ({negative_ratio:.1f}%)
   • 긍정적 피드백: {total_feedback - negative_count}건 ({100-negative_ratio:.1f}%)

🚨 주요 문제 영역:
   1. {top_issues.index[0]}: {top_issues.iloc[0]}건 ({top_issues.iloc[0]/negative_count*100:.1f}%)
   2. {top_issues.index[1] if len(top_issues) > 1 else 'N/A'}: {top_issues.iloc[1] if len(top_issues) > 1 else 0}건
   3. {top_issues.index[2] if len(top_issues) > 2 else 'N/A'}: {top_issues.iloc[2] if len(top_issues) > 2 else 0}건

⚡ 시급한 개선 대상:
   1. {critical_functions.index[0]}: {critical_functions.iloc[0]}건 불만
   2. {critical_functions.index[1]}: {critical_functions.iloc[1]}건 불만  
   3. {critical_functions.index[2]}: {critical_functions.iloc[2]}건 불만

💡 핵심 권장사항:
   • UI/UX 변경 시 사용자 사전 테스트 강화 필요
   • 쇼츠 기능의 사용성 개선이 시급함
   • 댓글 시스템 전반적 재설계 검토 필요
   • 기술적 오류(로딩, 재생 등) 안정성 확보

🎯 예상 효과:
   • 상위 5개 이슈 해결 시 전체 불만의 {critical_functions.head().sum()/negative_count*100:.1f}% 감소 예상
   • 사용자 만족도 {100-negative_ratio+20:.1f}%까지 개선 가능
   
================================================
        """)
        
        return {
            'total_feedback': total_feedback,
            'negative_ratio': negative_ratio,
            'top_issues': top_issues,
            'critical_functions': critical_functions
        }
    
    def run_full_analysis(self):
        """🚀 전체 분석 실행"""
        print("🚀 유튜브 UX 개선 인사이트 분석을 시작합니다!\n")
        
        try:
            # 1. 전체 현황 대시보드
            self.create_overview_dashboard()
            print("\n" + "="*60 + "\n")
            
            # 2. 우선순위 매트릭스  
            priority_df = self.create_priority_matrix()
            print("\n" + "="*60 + "\n")
            
            # 3. 세부 이슈 분석
            self.create_detailed_issue_analysis()
            print("\n" + "="*60 + "\n")
            
            # 4. 개선 로드맵
            roadmap_df = self.create_improvement_roadmap()
            print("\n" + "="*60 + "\n")
            
            # 5. 감정 흐름 다이어그램
            self.create_sentiment_flow_sankey()
            print("\n" + "="*60 + "\n")
            
            # 6. 경영진 요약 보고서
            summary = self.generate_executive_summary()
            
            print("\n✅ 모든 분석이 완료되었습니다!")
            
            return {
                'priority_analysis': priority_df,
                'improvement_roadmap': roadmap_df,
                'executive_summary': summary
            }
            
        except Exception as e:
            print(f"❌ 분석 중 오류 발생: {e}")
            return None

# ================================================================
# 🚀 분석 실행
# ================================================================

# 분석 실행
analyzer = YouTubeUXAnalyzer(df)
results = analyzer.run_full_analysis()

# 추가 인사이트
print(f"""
🎯 ============ 추가 비즈니스 인사이트 ============

📱 플랫폼 전략 제안:
   • 모바일 최적화: 쇼츠 기능 개선이 최우선
   • 데스크톱 경험: 댓글 시스템 재설계 필요
   • 크로스 플랫폼: 일관된 UX 경험 제공

🎭 사용자 세그먼트별 대응:
   • 파워유저: 고급 기능(배속, 재생바) 개선
   • 캐주얼유저: 직관적 UI 유지 및 강화
   • 크리에이터: 댓글 관리 도구 개선

💰 비즈니스 임팩트:
   • 긍정적 UX 개선으로 사용자 체류시간 증가 예상
   • 광고 수익 및 프리미엄 가입률 상승 효과
   • 브랜드 이미지 개선으로 장기적 충성도 향상

================================================
""")

1_overview_dashboard.html
4.36MB
2_priority_matrix.html
4.36MB
3_detailed_issue_analysis.png
0.18MB
4_improvement_roadmap.html
4.36MB
executive_summary.txt
0.00MB
youtube_ux_analysis_report.xlsx
0.01MB

 

분석결과들 ....  // ㅎㅎ