본문으로 건너뛰기

© 2026 Molayo

Dev.to헤드라인2026. 06. 15. 13:24

Play & Learn ML: 대규모 업데이트 - 5개의 신규 모듈, i18n 및 모바일 지원

요약

인터랙티브 머신러닝 학습 플랫폼인 'Play & Learn ML'이 대규모 업데이트를 통해 5개의 신규 모듈과 다국어 지원, 모바일 최적화를 도입했습니다. 로지스틱 회귀, PCA, SVM 등 핵심 ML 개념을 시각적이고 단계적인 인터랙티브 모듈로 학습할 수 있습니다.

핵심 포인트

  • 로지스틱 회귀, PCA, SVM, Naive Bayes, t-SNE 등 5개 신규 모듈 추가
  • 4개 언어 국제화(i18n) 및 반응형 모바일 레이아웃 지원
  • 총 13개의 인터랙티브 모듈과 5단계의 점진적 학습 레벨 제공
  • 시각적 피드백과 실시간 힌트를 통한 직관적인 ML 개념 학습

8개에서 13개 모듈로, 4개 언어로, 그리고 완전한 반응형 모바일 레이아웃까지 — 인터랙티브 ML 플레이그라운드가 계속해서 성장하고 있습니다.

무엇이 바뀌었나

지난 업데이트에서는 3개의 모듈(경사 하강법 (Gradient Descent), 혼동 행렬 (Confusion Matrix), 과적합 (Overfitting))이 추가되었습니다. 이번에는 더 크게 준비했습니다. 로지스틱 회귀 (Logistic Regression), PCA, SVM, 나이브 베이즈 (Naive Bayes), 그리고 t-SNE를 다루는 5개의 모듈을 추가했습니다. 여기에 더해 공통 기능으로 4개 언어 국제화 (i18n) 및 모바일 터치 지원을 도입했습니다.

이제 이 프로젝트는 13개의 인터랙티브 모듈을 보유하고 있으며, 각 모듈은 5단계의 점진적 레벨, 정의 가이드 (DefinitionGuide), 실시간 힌트 (LiveHint) 메시지, 그리고 자동 감지 완료 기능을 갖추고 있습니다.

5개의 신규 모듈

1. 확률 시소 (Probability Seesaw) — 로지스틱 회귀 (Logistic Regression)

비유: 시소가 두 클래스의 균형을 맞춥니다. 시그모이드 (Sigmoid, S-곡선) 함수는 결정 경계 (Decision Boundary)를 따라 "클래스 0"에서 "클래스 1"로 부드럽게 전환됩니다.

작동 원리: 모델은 설정 가능한 단계(step)와 학습률 (Learning Rate)을 가진 경사 하강법 (Gradient Descent)을 사용하여 로지스틱 회귀를 적합 (Fit) 시킵니다. 2D 캔버스는 다음을 보여줍니다:

  • 색상이 입혀진 확률 히트맵 (Heatmap) (파란색 = p < 0.5, 분홍색 = p ≥ 0.5)
  • 점선 형태의 노란색 선으로 표시된 시그모이드 결정 경계 (p = 0.5 등고선)
  • 결정 경계 근처에서 약간 겹쳐 있는 두 개의 덩어리 형태의 클래스

경사 하강법 (Gradient Descent) 옵티마이저는 로그 손실 (Log-loss)을 최소화합니다:

function logisticGradient(points, w0, w1, b) {
  let dw0 = 0, dw1 = 0, db = 0;
  for (const p of points) {
...

학습 내용: 정확도 (Accuracy)만으로는 충분하지 않습니다. 로그 손실 (Log-loss)은 확률 보정 (Probability Calibration)을 측정합니다. 레벨 5에서는 완벽한 분류와 동시에 로그 손실이 0에 가까워야 하며, 이는 확률이 잘 보정되었음을 의미합니다.

2. 그림자 인형극 (Shadow Puppets) — PCA

비유: 각 데이터 포인트는 선 위에 "그림자" (수직 투영)를 드리웁니다. 선을 회전시킴에 따라 그림자들이 퍼지거나 뭉칩니다. 가장 많이 퍼지는 방향이 제1 주성분 (First Principal Component)입니다.

작동 원리: PCA는 공분산 행렬 (Covariance Matrix)을 통해 분석적으로 계산됩니다:

function computePCA(points) {
  // 데이터 중심화, 2x2 공분산 행렬 계산
  // 고유값 분해 (Eigen-decompose): θ = 0.5 * atan2(2*vxy, vxx - vyy)
...

사용자가 PC 선 위의 노란색 핸들을 드래그하여 회전시킵니다. 실시간 피드백:

  • 투영선 (Projection lines) (녹색 점선)이 각 점을 그림자와 연결합니다.
  • 투영된 점 (Projected points) (녹색 원)이 선을 따라 미끄러집니다.
  • **분산 바 (Variance bar)**는 사용자가 실제 PC1에 가까워질수록 채워집니다.
  • **오차 각도 (Error angle)**는 최적의 방향으로부터 떨어진 각도를 도(degrees) 단위로 보여줍니다.

학습 내용: PCA는 최대 분산 (maximum variance) 방향을 찾습니다. "그림자" 시각화는 차원 축소 (dimensionality reduction)를 구체화합니다. 즉, 2D 점이 어떻게 하나의 숫자(투영 좌표)로 표현될 수 있는지 문자 그대로 눈으로 확인하게 됩니다.

3. 줄다리기 — SVM

비유: 결정 경계 (decision boundary)는 줄다리기에서의 밧줄과 같습니다. 가장 바깥쪽에 있는 점들(서포트 벡터, support vectors)은 밧줄을 당기는 팀이며, 이들이 경계가 어디에 위치할지를 결정합니다. 서포트 벡터를 제거하면 선이 이동합니다. 경계 근처에 점을 추가하면 마진 (margin)이 줄어듭니다.

작동 원리: SVM 솔버 (solver)는 서로 반대되는 클래스에서 점 쌍을 무작위로 샘플링하고, 수직 이등분선 (perpendicular bisector)이 모든 데이터를 분리하는지 확인합니다. 모든 분리선 중에서 마진이 최대인 선을 선택합니다:

function computeSVM(points) {
  // 후보 경계로서 {class0, class1} 쌍을 무작위로 샘플링
  // 각 쌍에 대해: 수직 이등분선 계산
...

이는 실제 하드 마진 (hard-margin) SVM의 무작위 근사 (randomized approximation) 방식이지만, 작은 2D 데이터셋의 경우 수백 번의 반복 (iterations) 내에 최적의 솔루션으로 수렴합니다.

서포트 벡터는 마진 거리의 1.15배 이내에 있는 점들로 식별되며, 시각적으로 눈에 띄도록 노란색 링으로 빛납니다.

대화형 기능:

  • 빈 공간 클릭 → 점 추가 (균형을 위해 클래스가 교대로 추가됨)
  • 점 클릭 → 점 제거
  • 마진과 서포트 벡터 개수가 즉시 업데이트됨

학습 내용: 결정 경계에는 오직 서포트 벡터만이 중요합니다. 서포트 벡터가 아닌 점들은 분류에 영향을 주지 않고 자유롭게 이동할 수 있습니다.

4. 스팸인가 아닌가 — 나이브 베이즈 (Naive Bayes)

4. 스팸인가 아닌가 — 나이브 베이즈 (Naive Bayes)

비유: 당신은 우편물 분류원입니다. 각 이메일에는 몇 개의 단어가 적혀 있습니다. 당신은 그것을 '스팸' 또는 '스팸 아님' 통으로 끌어다 놓습니다(drag). 이메일을 분류할 때마다, 스팸/스팸 아님이라는 조건 하에 각 단어의 확률이 업데이트되는데 — 이것이 베이즈 정리(Bayes' Theorem)가 작동하는 방식입니다.

작동 원리: 각 이메일은 12개의 어휘집(vocabulary)에서 2~5개의 단어를 조합하여 생성됩니다 (예: 'free', 'win', 'cash' 같은 스팸성 단어와 'hello', 'meeting', 'report' 같은 정상적인 단어의 혼합). 사용자는 D3 드래그 앤 드롭을 사용하여 카드를 통에 넣습니다.

단어 확률은 라플라스 평활화(Laplace smoothing)를 사용합니다:

wordProbs[word] = {
  givenSpam: (countInSpam + 1) / (totalSpam + 2),
  givenNot:  (countInNot  + 1) / (totalNot  + 2),
...

사이드바에는 P(word|spam) / P(word|not-spam) 비율에 따라 순위가 매겨진 상위 '스팸 단어'들이 표시됩니다. 이 비율이 나이브 베이즈의 핵심입니다 — 높은 비율을 가진 단어는 강력한 스팸 지표입니다.

배우는 것: 나이브 베이즈는 단어 독립성(word independence)을 가정합니다 (이는 순진한 가정이며, 'free'와 'win'은 종종 함께 나타납니다). 그럼에도 불구하고 이 분류기는 작동하는데, 정확한 보정(calibration)이 필요하기보다는 확률의 상대적 순서만 알면 되기 때문입니다.

5. 오리가미 펼치기 — t-SNE / UMAP

비유: 고차원 데이터는 구겨진 오리가미 종이와 같습니다. t-SNE은 이를 2D로 펼쳐 숨겨진 구조를 드러내지만, 어떻게 잡느냐(퍼플렉시티 매개변수, perplexity parameter)에 따라 펼쳐지는 모습이 다르게 보일 수 있습니다.

작동 원리: 이것은 브라우저에서 실행되는 완전한 (단순화된) t-SNE 구현입니다:

  1. 4개의 뚜렷한 클러스터를 가진 6D 데이터 생성
  2. 모든 포인트 간의 쌍별 유클리드 거리(Euclidean distances) 계산
  3. 목표 퍼플렉시티를 달성하기 위해 각 포인트당 $\sigma$에 대한 이진 탐색(Binary search) 수행 (가우시안 커널)
  4. 랜덤 2D 위치 초기화
  5. 모멘텀을 사용한 경사 하강법(gradient descent)을 통해 KL 발산(KL divergence) 최적화

KL 발산의 기울기(gradient):

// 각 쌍 (i, j)에 대해:
//   p_ij = 고차원 유사도 (Gaussian, 정규화)
//   q_ij = 저차원 유사도 (Cauchy, 정규화)
...

애니메이션은 requestAnimationFrame을 사용하여 반복당 약 20ms 속도로 실행되며, 약 6초 동안 300회의 반복을 완료합니다. 사용자는 perplexity (혼란도)를 5에서 50 사이로 조정하며 임베딩 (embedding)이 어떻게 변하는지 관찰할 수 있습니다.

학습 내용: Perplexity (혼란도)는 국소적 구조 (local structure)와 전역적 구조 (global structure) 사이의 균형을 조절합니다. 낮은 perplexity (5)는 세밀한 클러스터 (clusters)를 보여줍니다. 높은 perplexity (50)는 전체적인 레이아웃 (layout)을 보여줍니다. 단 하나의 "정답"인 t-SNE는 존재하지 않습니다. 서로 다른 perplexity 값은 데이터의 서로 다른 측면을 드러냅니다.

공통 기능 (Cross-Cutting Features)

다국어 i18n 지원 (4개 언어)

이제 프로젝트에서 영어, 스페인어, 프랑스어, 중국어를 지원합니다. 구현 방식은 다음과 같습니다:

  1. src/utils/i18n.js — 네임스페이스(nav.*, levels.*, guide.*, controls.*)별로 정리된 번역 문자열 사전입니다. t(key, locale) 함수는 점 표기법 (dot-notation) 조회를 수행하며, 조회가 불가능할 경우 해당 키 자체를 반환하는 유연한 폴백 (fallback) 기능을 갖추고 있습니다.

  2. src/utils/LanguageContext.jsx — 현재 로케일 (locale)을 저장하고 이를 localStorage와 동기화하는 React 컨텍스트 (context)입니다. App.jsx에서 전체 앱 트리를 감쌉니다.

  3. src/components/LanguageSwitcher.jsx — 사이드바 하단에 위치한 4개의 필 버튼 (pill-buttons: EN, ES, FR, 中文)입니다. 활성화된 언어는 강조 색상으로 표시됩니다.

  4. 컴포넌트 통합LevelSystem.jsxDefinitionGuide.jsxuseLanguage()를 사용하여 레이블을 번역합니다. 13개의 모든 워크벤치 (workbenches)는 공유 컴포넌트를 통해 t("levels.title") 등을 전달받습니다.

각 로케일별 번역 작업에는 약 30분이 소요되었습니다. 주로 각 언어에서 기술적인 ML 용어("support vectors", "decision boundary", "overfitting")를 정확하게 맞추는 작업이었습니다.

모바일 터치 지원

기존의 고정 너비 700×500 캔버스 (canvas) 레이아웃은 모바일에서 사용할 수 없었습니다. 변경 사항은 다음과 같습니다:

  1. 반응형 사이드바 (Responsive sidebar) — 고정된 왼쪽 패널에서 햄버거 아이콘으로 실행되는 슬라이드 오버 드로어 (slide-over drawer) 방식으로 전환되었습니다. 반투명한 백드롭 오버레이 (backdrop overlay)를 탭하면 사이드바가 닫힙니다.

  2. 터치 액션 (Touch-action) CSS — SVG 요소에 touch-action: none을 적용하여 브라우저의 기본 제스처 (스크롤, 확대/축소)가 드래그 상호작용 (drag interactions)을 방해하지 않도록 방지합니다.

  3. 레인지 슬라이더 (Range slider) 스타일링 — 손가락으로 조작하기 쉽도록 더 큰 썸 (thumb) 타겟 (16px)을 가진 커스텀 -webkit-appearance: none 스타일을 적용했습니다.

  4. 오버플로 (Overflow) 처리 — 모바일에서 캔버스 컨테이너는 overflow-x: auto를 사용하며, SVG에는 max-width: 100%를 적용합니다. 캔버스가 뷰포트 (viewport)를 초과할 경우 사용자가 가로로 스크롤할 수 있습니다.

D3의 d3.drag()는 이미 네이티브하게 터치 이벤트를 처리합니다. 이는 터치 좌표를 마우스 좌표와 동일한 이벤트 형식으로 변환하므로, 기존의 모든 드래그 상호작용 (PCA 회전, 정렬 기계 카드, K-Means 자석 배치)이 수정 없이 그대로 작동합니다.

13개 모듈의 모습

workbenches/
├── LinearRegression/      Stretchy Rope         (D3 + OLS)
├── KMeans/                Magnetic Clusters     (D3 drag + forces)
...

모든 모듈은 동일한 구조적 패턴을 따릅니다: 단일 독립형 JSX 파일, 렌더링을 위한 D3, 진행도를 위한 useLevelSystem, 인라인 교육을 위한 DefinitionGuide + LiveHint를 사용합니다.

회고 (Reflections)

잘된 점 (What Worked)

  1. t-SNE 모듈이 가장 어려웠지만 가장 보람찼습니다. 브라우저에서 KL 발산 (KL divergence) 최적화를 처음부터 구현하는 것은 진정으로 도전적인 작업이었습니다. 포인트별 σ(시그마)에 대한 이진 탐색 (binary searching), 그래디언트 (gradient)의 수치적 안정성 (numerical stability) 처리, 50fps에서 애니메이션을 부드럽게 만드는 작업 등이 포함되었습니다. 하지만 실제 6D → 2D 전개가 실시간으로 펼쳐지는 것을 보는 것은 장관입니다.

  2. SVM의 "클릭하여 추가/제거" 상호작용은 놀라울 정도로 중독성이 있습니다. 포인트를 마진 경계 (margin boundary) 바로 위에 배치하고 선이 튕겨 나가는 것을 지켜보는 데는 묘한 만족감이 있습니다. 이는 정적인 다이어그램이 결코 할 수 없는 방식으로 서포트 벡터 (support vectors)의 개념을 직관적으로 느끼게 해줍니다.

  3. i18n (국제화)이 번들 크기를 거의 늘리지 않았습니다. 번역 사전 (translation dictionaries)은 gzip 압축 시 약 3KB를 추가합니다. LanguageContextLanguageSwitcher가 추가하는 오버헤드는 무시할 수 있는 수준입니다. 초기에 수행할 가치가 있는 작업입니다.

개선하고 싶은 점 (What I'd Improve)

  1. t-SNE 성능. 48개의 포인트와 300번의 반복 (iterations) 시, 최적화에 약 6초가 소요됩니다. 프로덕션 품질의 경험을 위해서는 2초 이내에 100개 이상의 포인트를 처리하고 싶습니다. 최적화 루프에 웹 워커 (Web Worker)를 사용하면 UI의 응답성을 유지할 수 있을 것입니다.

  2. 모바일 캔버스 크기 조정. 고정된 700×500 캔버스는 데스크톱에서는 잘 작동하지만, 휴대폰에서는 가로 스크롤이 필요합니다. 더 나은 접근 방식은 뷰포트 (viewport)에 맞춰 크기가 조절되는 반응형 너비/높이를 가진 SVG viewBox를 사용하는 것입니다.

  3. SVM 솔버 (solver)의 견고함. 무작위 솔버 (randomized solver)는 잘 분리된 데이터에는 작동하지만, 클래스가 겹치는 경우(완벽한 선형 분리기가 존재하지 않는 경우) 실패할 수 있습니다. 소프트 마진 (soft-margin) 공식으로 폴백 (fallback) 기능을 구현하면 더 견고해질 것입니다.

다음 단계는? (What's Next?)

README의 "새로운 기능 아이디어 (Ideas for New Features)" 테이블에 이제 13개의 새로운 제안이 추가되었습니다:

  • K-Nearest Neighbors (K-최근접 이웃) — 점을 클릭하여 가장 가까운 K개의 이웃이 투표하는 것을 확인합니다.
  • DBSCAN — 밀도 반경 (density radius)을 조절하며 클러스터가 형성되는 과정을 관찰합니다.
  • Random Forest (랜덤 포레스트) — 스텀프 (stumps)들이 모여 함께 투표하는 숲입니다.
  • Gradient Boosting (그래디언트 부스팅) — 각 트리가 이전 트리의 실수를 수정합니다.
  • Reinforcement Learning (강화학습 (RL)) — 미로를 학습하는 쥐
  • Attention Mechanism (어텐션 메커니즘) — 단어들에 스포트라이트를 비춥니다.
  • GANs (생성적 적대 신경망) — 위조범 vs 탐정

여기에 활성화 함수 (activation functions), 규제화 (regularization), 교차 검증 (cross-validation), 특성 공학 (feature engineering), 배치 정규화 (batch normalization), 그리고 협업 필터링 (collaborative filtering)이 추가될 예정입니다.

기여를 위한 문은 언제나 열려 있습니다.

직접 해보기

git clone https://github.com/harishkotra/play-learn-ml.git
cd play-learn-ml
npm install && npm run dev

이 프로젝트는 무료이며 오픈 소스이고, 완전히 브라우저 내에서 실행됩니다. 백엔드도, API 키도, 회원가입도 필요 없습니다.

스크린샷

Play & Learn ML - 1

Play & Learn ML - 2

AI 자동 생성 콘텐츠

본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.

원문 바로가기
0

댓글

0