⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

텍스트 분류와 감성 분석 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 11. 27. · 6 Views

텍스트 분류와 감성 분석 완벽 가이드

자연어 처리의 핵심인 텍스트 분류와 감성 분석을 JavaScript로 구현하는 방법을 배웁니다. 실무에서 바로 활용할 수 있는 예제와 함께 다국어 처리, 배치 처리, 시각화까지 다룹니다.


목차

  1. 감성_분석_구현하기
  2. 텍스트_분류_모델_사용
  3. 다국어_감성_분석
  4. 신뢰도_점수_해석
  5. 배치_처리하기
  6. 결과_시각화

1. 감성 분석 구현하기

김개발 씨는 이커머스 회사에서 일하는 주니어 개발자입니다. 어느 날 팀장님이 다가와 말했습니다.

"고객 리뷰가 긍정적인지 부정적인지 자동으로 분류하는 기능을 만들어 주세요." 수천 개의 리뷰를 일일이 읽어볼 수는 없는 노릇이었습니다.

감성 분석은 텍스트에 담긴 감정이나 의견을 자동으로 파악하는 기술입니다. 마치 베테랑 고객 상담사가 고객의 말투만 듣고도 기분을 알아채는 것과 같습니다.

이 기술을 활용하면 대량의 텍스트 데이터에서 사람들의 반응을 빠르게 파악할 수 있습니다.

다음 코드를 살펴봅시다.

const Sentiment = require('sentiment');
const sentiment = new Sentiment();

// 감성 분석 함수 구현
function analyzeSentiment(text) {
  const result = sentiment.analyze(text);

  // 점수에 따라 감성 레이블 결정
  let label = 'neutral';
  if (result.score > 2) label = 'positive';
  else if (result.score < -2) label = 'negative';

  return {
    text: text,
    score: result.score,        // 감성 점수
    comparative: result.comparative,  // 정규화된 점수
    label: label,
    words: result.words         // 감성에 영향을 준 단어들
  };
}

// 사용 예시
const review = "This product is amazing! Best purchase ever.";
console.log(analyzeSentiment(review));

김개발 씨는 입사 6개월 차 주니어 개발자입니다. 회사의 쇼핑몰에는 매일 수백 개의 상품 리뷰가 올라옵니다.

마케팅팀에서는 고객들의 반응이 전반적으로 어떤지 알고 싶어했습니다. "수작업으로 하면 며칠이 걸릴 텐데..." 김개발 씨가 한숨을 쉬자, 옆자리의 박시니어 씨가 말했습니다.

"감성 분석을 써보는 게 어때요? 텍스트의 감정을 자동으로 파악해주는 기술이에요." 그렇다면 감성 분석이란 정확히 무엇일까요?

쉽게 비유하자면, 감성 분석은 마치 숙련된 독심술사와 같습니다. 사람이 쓴 글을 읽고 그 안에 담긴 감정을 읽어내는 것입니다.

"정말 좋아요!"라는 문장에서는 긍정적인 감정을, "최악이에요"라는 문장에서는 부정적인 감정을 파악합니다. 감성 분석이 없던 시절에는 어땠을까요?

마케팅 담당자가 리뷰를 하나하나 읽어가며 엑셀에 긍정, 부정을 표시해야 했습니다. 리뷰가 100개만 되어도 하루가 꼬박 걸렸습니다.

더 큰 문제는 사람마다 판단 기준이 달라서 일관성이 없다는 것이었습니다. 바로 이런 문제를 해결하기 위해 감성 분석 기술이 발전했습니다.

JavaScript에서는 sentiment 라이브러리를 사용하면 손쉽게 감성 분석을 구현할 수 있습니다. 이 라이브러리는 AFINN 어휘 목록을 기반으로 각 단어에 점수를 부여합니다.

위의 코드를 한 줄씩 살펴보겠습니다. 먼저 sentiment 라이브러리를 불러오고 인스턴스를 생성합니다.

analyze 메서드에 텍스트를 전달하면 분석 결과가 반환됩니다. score는 전체 감성 점수이고, comparative는 단어 수로 나눈 정규화된 점수입니다.

점수가 2보다 크면 긍정, -2보다 작으면 부정, 그 사이면 중립으로 분류합니다. 이 임계값은 상황에 따라 조절할 수 있습니다.

실제 현업에서는 어떻게 활용할까요? 고객 리뷰 분석뿐 아니라 소셜 미디어 모니터링, 설문 조사 응답 분석, 고객 문의 우선순위 결정 등 다양한 분야에서 활용됩니다.

부정적인 리뷰가 갑자기 늘어나면 제품에 문제가 생겼다는 신호일 수 있습니다. 하지만 주의할 점도 있습니다.

감성 분석은 완벽하지 않습니다. "이 제품 안 나쁘네요"처럼 부정어가 포함된 긍정 표현이나, 비꼬는 말투는 잘못 분류될 수 있습니다.

따라서 결과를 맹신하기보다 참고 자료로 활용하는 것이 좋습니다. 다시 김개발 씨의 이야기로 돌아가 봅시다.

감성 분석을 적용한 후 마케팅팀은 실시간으로 고객 반응을 모니터링할 수 있게 되었습니다. 김개발 씨는 뿌듯한 미소를 지었습니다.

실전 팁

💡 - npm install sentiment로 라이브러리를 설치하세요

  • 임계값(threshold)은 도메인에 맞게 조절하세요
  • 분석 결과는 참고용으로 활용하고 중요한 결정은 사람이 검토하세요

2. 텍스트 분류 모델 사용

김개발 씨가 감성 분석을 성공적으로 구현하자, 팀장님이 새로운 과제를 주었습니다. "이번에는 고객 문의를 카테고리별로 자동 분류해주세요.

배송, 환불, 상품 문의 등으로 나눠서요." 단순한 긍정/부정을 넘어 더 정교한 분류가 필요해졌습니다.

텍스트 분류는 문서나 문장을 미리 정의된 카테고리로 자동 분류하는 기술입니다. 마치 우체국에서 편지를 지역별로 분류하는 것처럼, 텍스트를 적절한 카테고리에 배치합니다.

이를 통해 대량의 문서를 효율적으로 관리할 수 있습니다.

다음 코드를 살펴봅시다.

const { pipeline } = require('@xenova/transformers');

// 텍스트 분류 파이프라인 초기화
async function classifyText(text, labels) {
  // zero-shot 분류 모델 로드
  const classifier = await pipeline(
    'zero-shot-classification',
    'Xenova/mobilebert-uncased-mnli'
  );

  // 텍스트를 주어진 레이블로 분류
  const result = await classifier(text, labels);

  return {
    text: text,
    labels: result.labels,      // 분류된 레이블 (확률 순)
    scores: result.scores,      // 각 레이블의 확률
    topLabel: result.labels[0], // 가장 높은 확률의 레이블
    confidence: result.scores[0]
  };
}

// 사용 예시
const inquiry = "주문한 상품이 아직 도착하지 않았어요";
const categories = ["배송", "환불", "상품문의", "결제"];
classifyText(inquiry, categories).then(console.log);

김개발 씨는 새로운 도전 앞에 서 있었습니다. 감성 분석은 긍정과 부정 두 가지로 나누면 되었지만, 이번에는 여러 카테고리로 분류해야 합니다.

"예전에는 이런 걸 하려면 기계학습 모델을 직접 학습시켜야 했어요." 박시니어 씨가 말했습니다. "하지만 요즘은 사전 학습된 모델을 가져다 쓰면 돼요." 그렇다면 텍스트 분류란 정확히 무엇일까요?

쉽게 비유하자면, 텍스트 분류는 마치 도서관 사서와 같습니다. 새로 들어온 책을 살펴보고 문학, 과학, 역사 등 적절한 서가에 배치하는 것입니다.

텍스트 분류도 마찬가지로 입력된 텍스트를 분석하여 가장 적합한 카테고리에 배치합니다. 특히 zero-shot 분류라는 기술이 혁신적입니다.

이 기술을 사용하면 별도의 학습 데이터 없이도 원하는 카테고리로 분류할 수 있습니다. 마치 똑똑한 사서가 처음 보는 주제의 책도 내용을 읽어보고 적절한 위치를 찾아주는 것과 같습니다.

위의 코드에서는 Transformers.js 라이브러리를 사용합니다. 이 라이브러리는 Hugging Face의 트랜스포머 모델을 브라우저와 Node.js에서 실행할 수 있게 해줍니다.

pipeline 함수로 분류기를 생성하고, 분류하고 싶은 텍스트와 가능한 레이블 목록을 전달합니다. 모델은 각 레이블에 대한 확률을 계산하여 가장 적합한 카테고리를 찾아냅니다.

실제 현업에서는 이 기술이 매우 유용합니다. 고객 센터에 들어오는 문의를 자동으로 담당 부서에 배정하거나, 뉴스 기사를 주제별로 분류하거나, 이메일을 중요도에 따라 정렬하는 데 활용됩니다.

하지만 주의할 점이 있습니다. zero-shot 분류는 편리하지만, 도메인에 특화된 정확도가 필요하다면 직접 학습시킨 모델이 더 나을 수 있습니다.

또한 모델 로딩에 시간이 걸리므로 서버 시작 시 미리 로드해두는 것이 좋습니다. 김개발 씨는 이 기술을 적용하여 고객 문의 자동 분류 시스템을 완성했습니다.

고객 상담팀의 업무 효율이 크게 향상되었습니다.

실전 팁

💡 - 모델은 서버 시작 시 한 번만 로드하고 재사용하세요

  • 레이블은 명확하고 서로 구분되는 단어를 사용하세요
  • 분류 결과가 애매한 경우 신뢰도 점수를 확인하세요

3. 다국어 감성 분석

회사가 글로벌 서비스를 시작하면서 김개발 씨에게 새로운 요구사항이 생겼습니다. "해외 고객 리뷰도 분석해야 해요.

영어, 일본어, 중국어 리뷰가 섞여 있어요." 한국어만 처리하던 시스템을 다국어로 확장해야 했습니다.

다국어 감성 분석은 여러 언어로 작성된 텍스트의 감정을 분석하는 기술입니다. 마치 여러 나라 말을 할 줄 아는 통역사가 각 언어의 뉘앙스까지 파악하는 것과 같습니다.

글로벌 서비스에서는 필수적인 기능입니다.

다음 코드를 살펴봅시다.

const { pipeline } = require('@xenova/transformers');

// 다국어 감성 분석 클래스
class MultilingualSentiment {
  constructor() {
    this.classifier = null;
  }

  async init() {
    // 다국어 지원 감성 분석 모델 로드
    this.classifier = await pipeline(
      'sentiment-analysis',
      'Xenova/bert-base-multilingual-uncased-sentiment'
    );
  }

  async analyze(text) {
    if (!this.classifier) await this.init();

    const result = await this.classifier(text);
    return {
      text: text,
      label: result[0].label,     // POSITIVE, NEGATIVE 등
      score: result[0].score,     // 신뢰도 점수
      stars: this.labelToStars(result[0].label)
    };
  }

  labelToStars(label) {
    const map = { '1 star': 1, '2 stars': 2, '3 stars': 3, '4 stars': 4, '5 stars': 5 };
    return map[label] || 3;
  }
}

// 사용 예시
const analyzer = new MultilingualSentiment();
analyzer.analyze("この製品は素晴らしいです").then(console.log);  // 일본어
analyzer.analyze("이 제품 정말 좋아요").then(console.log);       // 한국어

김개발 씨는 글로벌 서비스 출시 소식에 걱정이 앞섰습니다. 영어는 그렇다 쳐도, 일본어와 중국어까지 처리해야 한다니요.

"언어별로 다른 모델을 써야 하나요?" 김개발 씨가 물었습니다. 박시니어 씨가 웃으며 대답했습니다.

"다행히 다국어 모델이라는 게 있어요. 하나의 모델로 여러 언어를 처리할 수 있습니다." 다국어 모델은 어떻게 가능한 걸까요?

이 모델들은 수십 개 언어의 텍스트로 동시에 학습됩니다. 마치 여러 나라에서 어린 시절을 보낸 사람이 자연스럽게 여러 언어를 구사하는 것처럼, 모델도 여러 언어의 패턴을 함께 학습합니다.

특히 BERT 기반의 다국어 모델은 104개 언어를 지원합니다. 언어를 미리 감지할 필요 없이 텍스트를 그대로 입력하면 됩니다.

위의 코드에서는 클래스 형태로 분석기를 구현했습니다. init 메서드에서 모델을 한 번 로드하고, 이후에는 재사용합니다.

이렇게 하면 매번 모델을 로드하는 오버헤드를 피할 수 있습니다. labelToStars 메서드는 모델의 출력을 별점 형태로 변환합니다.

이 특정 모델은 1점부터 5점까지의 별점을 예측하도록 학습되었기 때문입니다. 실제 글로벌 서비스에서는 이런 다국어 처리가 필수입니다.

같은 상품에 대한 각국 고객의 반응을 통합하여 분석하거나, 다국어 소셜 미디어 모니터링을 하거나, 글로벌 브랜드의 평판을 관리하는 데 활용됩니다. 주의할 점도 있습니다.

다국어 모델은 편리하지만, 특정 언어에 특화된 모델보다 정확도가 떨어질 수 있습니다. 특히 은어나 신조어, 문화적 맥락이 중요한 표현은 잘못 분석될 수 있습니다.

중요한 분석에는 해당 언어 원어민의 검토가 필요합니다. 김개발 씨는 다국어 감성 분석을 성공적으로 구현했습니다.

이제 전 세계 고객의 목소리를 한눈에 파악할 수 있게 되었습니다.

실전 팁

💡 - 다국어 모델은 메모리를 많이 사용하므로 서버 리소스를 확인하세요

  • 특정 언어의 정확도가 중요하다면 해당 언어 전용 모델을 고려하세요
  • 이모지도 감성 분석에 영향을 줄 수 있으니 전처리 여부를 결정하세요

4. 신뢰도 점수 해석

김개발 씨가 만든 시스템이 가동되자 QA팀에서 질문이 들어왔습니다. "분석 결과 옆에 나오는 0.87이라는 숫자는 뭔가요?

이 숫자가 높으면 무조건 믿어도 되는 건가요?" 김개발 씨는 신뢰도 점수에 대해 제대로 설명해야 했습니다.

신뢰도 점수는 모델이 자신의 예측에 대해 얼마나 확신하는지를 나타내는 값입니다. 0에서 1 사이의 숫자로 표현되며, 1에 가까울수록 모델이 확신한다는 의미입니다.

하지만 높은 신뢰도가 항상 정확한 예측을 보장하지는 않습니다.

다음 코드를 살펴봅시다.

// 신뢰도 점수를 해석하고 활용하는 함수들
function interpretConfidence(score) {
  if (score >= 0.9) return { level: 'high', action: 'auto_process' };
  if (score >= 0.7) return { level: 'medium', action: 'auto_with_flag' };
  if (score >= 0.5) return { level: 'low', action: 'manual_review' };
  return { level: 'very_low', action: 'manual_review' };
}

// 신뢰도 기반 분류 결과 처리
function processClassificationResult(result) {
  const { label, score } = result;
  const interpretation = interpretConfidence(score);

  return {
    prediction: label,
    confidence: score,
    confidenceLevel: interpretation.level,
    recommendedAction: interpretation.action,
    needsReview: score < 0.7,
    // 상위 2개 레이블의 점수 차이 계산 (불확실성 지표)
    isAmbiguous: result.scores &&
      (result.scores[0] - result.scores[1]) < 0.2
  };
}

// 사용 예시
const result = { label: 'positive', score: 0.65, scores: [0.65, 0.55] };
console.log(processClassificationResult(result));
// { prediction: 'positive', confidence: 0.65, confidenceLevel: 'low',
//   recommendedAction: 'manual_review', needsReview: true, isAmbiguous: true }

김개발 씨는 QA팀의 질문을 받고 잠시 생각에 잠겼습니다. 신뢰도 점수가 0.87이면 87% 확률로 맞다는 뜻일까요?

"좋은 질문이에요." 박시니어 씨가 끼어들었습니다. "신뢰도 점수는 생각보다 복잡한 개념이에요.

제대로 이해하고 사용해야 합니다." 신뢰도 점수란 무엇일까요? 쉽게 비유하자면, 신뢰도 점수는 학생이 시험 문제를 풀고 나서 느끼는 확신의 정도와 같습니다.

"이건 확실해!" 하는 문제가 있고, "글쎄, 이것 같기도 하고..." 하는 문제가 있습니다. 모델도 마찬가지입니다.

하지만 중요한 점이 있습니다. 자신감 있게 답한 학생이 항상 맞는 것은 아닙니다.

모델도 마찬가지로, 높은 신뢰도가 반드시 정확한 예측을 의미하지는 않습니다. 그렇다면 신뢰도 점수를 어떻게 활용해야 할까요?

위의 코드에서는 신뢰도 점수를 구간별로 나누어 처리 방식을 다르게 합니다. 0.9 이상이면 자동 처리, 0.7에서 0.9 사이면 자동 처리하되 표시를 남기고, 0.7 미만이면 사람이 검토하도록 합니다.

isAmbiguous 필드도 중요합니다. 이것은 상위 두 레이블의 점수 차이가 작은지를 확인합니다.

예를 들어 긍정이 0.52, 부정이 0.48이면 모델도 헷갈려하는 것입니다. 이런 경우는 점수와 관계없이 사람의 검토가 필요합니다.

실무에서는 이런 임계값을 상황에 맞게 조절합니다. 의료나 금융처럼 실수가 치명적인 분야에서는 임계값을 높게 설정합니다.

반면 SNS 댓글 분류처럼 실수해도 큰 문제가 없는 경우에는 낮게 설정할 수 있습니다. 주의할 점이 있습니다.

모델의 신뢰도 점수는 **보정(calibration)**이 되어 있지 않을 수 있습니다. 즉, 0.8이라고 해서 실제로 80%의 정확도를 보장하지 않습니다.

실제 데이터로 테스트하여 신뢰도 점수와 실제 정확도의 관계를 파악해야 합니다. 김개발 씨는 QA팀에게 이 내용을 설명했습니다.

"그래서 신뢰도가 낮은 건 저희 팀에서 따로 검토한다는 거군요!" QA팀원이 이해했다는 듯 고개를 끄덕였습니다.

실전 팁

💡 - 신뢰도 임계값은 실제 데이터로 테스트하여 결정하세요

  • 상위 레이블 간 점수 차이도 함께 확인하세요
  • 도메인의 중요도에 따라 임계값을 다르게 설정하세요

5. 배치 처리하기

시스템이 안정적으로 운영되던 어느 날, 마케팅팀에서 긴급 요청이 들어왔습니다. "지난 1년간의 리뷰 50만 건을 분석해주세요.

내일 아침 회의에서 발표해야 해요." 김개발 씨는 50만 건을 어떻게 효율적으로 처리할지 고민에 빠졌습니다.

배치 처리는 대량의 데이터를 한꺼번에 효율적으로 처리하는 방법입니다. 마치 세탁기에 빨래를 한 번에 넣고 돌리는 것처럼, 여러 텍스트를 묶어서 처리하면 훨씬 효율적입니다.

메모리 관리와 진행 상황 추적도 중요합니다.

다음 코드를 살펴봅시다.

const Sentiment = require('sentiment');
const sentiment = new Sentiment();

// 배치 감성 분석 함수
async function batchAnalyze(texts, options = {}) {
  const { batchSize = 100, onProgress } = options;
  const results = [];
  const totalBatches = Math.ceil(texts.length / batchSize);

  for (let i = 0; i < texts.length; i += batchSize) {
    const batch = texts.slice(i, i + batchSize);
    const batchNum = Math.floor(i / batchSize) + 1;

    // 배치 단위로 처리
    const batchResults = batch.map(text => {
      const result = sentiment.analyze(text);
      return {
        text: text.substring(0, 50) + '...',
        score: result.score,
        label: result.score > 0 ? 'positive' :
               result.score < 0 ? 'negative' : 'neutral'
      };
    });

    results.push(...batchResults);

    // 진행 상황 콜백
    if (onProgress) {
      onProgress({ current: batchNum, total: totalBatches,
                   processed: results.length });
    }

    // 메모리 해제를 위한 짧은 대기
    await new Promise(r => setTimeout(r, 10));
  }

  return results;
}

// 사용 예시
const reviews = Array(10000).fill("Great product!");
batchAnalyze(reviews, {
  batchSize: 500,
  onProgress: (p) => console.log(`${p.current}/${p.total} 배치 완료`)
}).then(results => console.log(`총 ${results.length}건 분석 완료`));

김개발 씨는 50만 건이라는 숫자에 당황했습니다. 한 건당 100밀리초만 걸려도 총 14시간이 걸립니다.

게다가 중간에 에러가 나면 처음부터 다시 해야 할 수도 있습니다. "대량 데이터는 배치 처리로 해야 해요." 박시니어 씨가 조언했습니다.

"한 건씩 처리하는 것보다 묶음으로 처리하는 게 훨씬 효율적입니다." 배치 처리란 무엇일까요? 마트에서 장을 볼 때를 생각해 보세요.

물건을 하나 살 때마다 계산대에 가는 것보다, 장바구니에 담아서 한 번에 계산하는 게 효율적입니다. 배치 처리도 마찬가지로, 여러 작업을 묶어서 한 번에 처리합니다.

위의 코드에서 핵심은 batchSize입니다. 100개씩 묶어서 처리하면 함수 호출 오버헤드가 줄어듭니다.

또한 배치 단위로 진행 상황을 추적할 수 있습니다. onProgress 콜백은 현재 진행 상황을 알려줍니다.

50만 건을 처리하는 동안 아무 피드백 없이 기다리면 불안하겠죠. 몇 퍼센트나 진행되었는지 알 수 있으면 마음이 놓입니다.

setTimeout을 사용한 짧은 대기도 중요합니다. Node.js의 이벤트 루프에 숨 쉴 틈을 주어 메모리가 정리될 기회를 제공합니다.

이것 없이 돌리면 메모리 사용량이 계속 올라갈 수 있습니다. 실무에서는 더 정교한 배치 처리가 필요합니다.

에러가 발생하면 해당 배치만 재시도하고, 중간 결과를 파일이나 데이터베이스에 저장하여 중단되어도 이어서 처리할 수 있게 합니다. Worker 스레드나 클러스터를 활용하여 병렬 처리를 하기도 합니다.

주의할 점도 있습니다. 배치 크기를 너무 크게 설정하면 메모리 부족이 발생할 수 있습니다.

반대로 너무 작으면 오버헤드가 커집니다. 처리하는 데이터의 크기와 서버 메모리를 고려하여 적절한 배치 크기를 찾아야 합니다.

김개발 씨는 배치 처리를 적용하여 50만 건을 3시간 만에 처리했습니다. 중간에 로그를 확인하며 커피를 마실 여유도 있었습니다.

실전 팁

💡 - 배치 크기는 100-1000 사이에서 시작하여 조절하세요

  • 중간 결과를 저장하여 장애 시 복구할 수 있게 하세요
  • 메모리 사용량을 모니터링하세요

6. 결과 시각화

분석이 끝나고 결과 데이터가 준비되었습니다. 하지만 마케팅팀에서 숫자만 가득한 JSON 파일을 보고 당황했습니다.

"이걸 보고서에 어떻게 넣죠? 그래프로 만들어주실 수 있나요?" 김개발 씨는 분석 결과를 이해하기 쉽게 시각화해야 했습니다.

결과 시각화는 분석 데이터를 그래프나 차트로 표현하여 인사이트를 쉽게 파악할 수 있게 하는 과정입니다. 마치 지도가 복잡한 지형을 한눈에 보여주듯, 시각화는 복잡한 데이터를 직관적으로 보여줍니다.

다음 코드를 살펴봅시다.

// 감성 분석 결과 시각화를 위한 데이터 준비
function prepareVisualizationData(results) {
  // 감성별 카운트
  const sentimentCounts = results.reduce((acc, r) => {
    acc[r.label] = (acc[r.label] || 0) + 1;
    return acc;
  }, {});

  // 점수 분포 (히스토그램용)
  const scoreDistribution = results.reduce((acc, r) => {
    const bucket = Math.floor(r.score / 10) * 10; // 10점 단위
    const key = `${bucket} to ${bucket + 9}`;
    acc[key] = (acc[key] || 0) + 1;
    return acc;
  }, {});

  // 시간대별 트렌드 (날짜가 있는 경우)
  const timeline = results
    .filter(r => r.date)
    .reduce((acc, r) => {
      const month = r.date.substring(0, 7); // YYYY-MM
      if (!acc[month]) acc[month] = { positive: 0, negative: 0, neutral: 0 };
      acc[month][r.label]++;
      return acc;
    }, {});

  return {
    summary: {
      total: results.length,
      positive: sentimentCounts.positive || 0,
      negative: sentimentCounts.negative || 0,
      neutral: sentimentCounts.neutral || 0,
      positiveRate: ((sentimentCounts.positive || 0) / results.length * 100).toFixed(1)
    },
    pieChartData: Object.entries(sentimentCounts).map(([k, v]) => ({ label: k, value: v })),
    histogramData: scoreDistribution,
    timelineData: timeline
  };
}

// 콘솔 기반 간단한 막대 그래프
function printBarChart(data) {
  const max = Math.max(...Object.values(data));
  console.log('\n=== 감성 분석 결과 ===\n');
  Object.entries(data).forEach(([label, count]) => {
    const bar = '█'.repeat(Math.round(count / max * 30));
    console.log(`${label.padEnd(10)} ${bar} ${count}`);
  });
}

김개발 씨는 마케팅팀의 요청에 고개를 끄덕였습니다. 숫자로 가득한 데이터는 개발자에게는 익숙하지만, 다른 팀원들에게는 그저 암호처럼 보일 수 있습니다.

"데이터를 시각화하면 누구나 쉽게 이해할 수 있어요." 박시니어 씨가 말했습니다. "잘 만든 그래프 하나가 천 마디 말보다 낫습니다." 시각화는 왜 중요할까요?

인간의 뇌는 숫자보다 그림을 훨씬 빠르게 처리합니다. "긍정 리뷰가 45,230개, 부정 리뷰가 12,450개"라고 말하는 것보다, 파이 차트로 보여주면 한눈에 비율을 파악할 수 있습니다.

위의 코드에서는 시각화에 필요한 데이터를 준비합니다. 원본 데이터를 가공하여 차트 라이브러리가 바로 사용할 수 있는 형태로 만듭니다.

sentimentCounts는 감성별 개수를 셉니다. 파이 차트나 막대 그래프에 적합합니다.

scoreDistribution은 점수를 구간별로 나누어 히스토그램을 그릴 수 있게 합니다. timeline은 시간에 따른 변화를 보여주는 라인 차트용입니다.

printBarChart 함수는 콘솔에서도 간단한 막대 그래프를 출력합니다. 개발 중에 빠르게 결과를 확인할 때 유용합니다.

실제 웹 서비스에서는 Chart.js, D3.js, Recharts 같은 라이브러리를 사용합니다. 보고서용으로는 정적인 이미지를 생성하고, 대시보드용으로는 인터랙티브한 차트를 만듭니다.

드릴다운 기능을 추가하면 전체 현황에서 세부 데이터까지 탐색할 수 있습니다. 주의할 점도 있습니다.

시각화가 데이터를 왜곡하지 않도록 주의해야 합니다. Y축을 0에서 시작하지 않거나, 3D 효과로 비율을 왜곡하는 것은 피해야 합니다.

데이터를 정확하게 전달하는 것이 시각화의 본질입니다. 김개발 씨는 분석 결과를 깔끔한 대시보드로 만들어 마케팅팀에 전달했습니다.

"와, 이렇게 보니까 바로 이해가 되네요!" 팀장님의 칭찬에 김개발 씨는 뿌듯했습니다.

실전 팁

💡 - 목적에 맞는 차트 유형을 선택하세요 (비율은 파이, 추이는 라인, 비교는 막대)

  • 색상은 직관적으로 사용하세요 (긍정은 초록, 부정은 빨강)
  • 차트에 제목과 범례를 반드시 추가하세요

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#JavaScript#NLP#SentimentAnalysis#TextClassification#MachineLearning#AI,ML,JavaScript

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.