9148c358d0
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를 Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류. - 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로 자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거, 동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거. - 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming, Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business, Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로, 나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는 title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백). 원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지. - 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서. - 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는 지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지. - Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경. - 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
6.9 KiB
6.9 KiB
id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
| id | title | category | status | canonical_id | aliases | duplicate_of | source_trust_level | confidence_score | verification_status | tags | raw_sources | last_reinforced | github_commit | tech_stack | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| wiki-2026-0508-마이크로-인터랙션-micro-interactions | 마이크로 인터랙션(Micro-interactions) | 10_Wiki/Topics | verified | self |
|
none | A | 0.9 | applied |
|
2026-05-10 | pending |
|
마이크로 인터랙션(Micro-interactions)
매 한 줄
"매 작은 반응이 매 신뢰를 만든다". 매 single-purpose UI feedback (clicked button squish, toggle slide, validation tick) 의 사용자 의도 confirm + 시스템 상태 communicate. Dan Saffer (2013)이 명명, 매 modern design system (Material 3, Apple HIG 2026)의 backbone.
매 핵심
매 4단계 구조 (Saffer)
- Trigger: user action (click, hover, scroll) or system event.
- Rules: what happens (state machine).
- Feedback: visual/audio/haptic response.
- Loops & Modes: long-term behavior (meta-rules).
매 4가지 기능
- Status communication — loading spinner, progress bar.
- Feedback — button press depression, form 검증 shake.
- Demonstrate result — like 의 heart fill animation.
- Visualize state changes — toggle on/off, theme switch.
매 응용
- Form validation — inline feedback (real-time check).
- Loading states — skeleton, spinner, progress.
- Notifications — toast slide-in/out.
- Gestures — swipe to delete (iOS Mail).
- Empty states — illustration + CTA.
💻 패턴
1. Button press feedback (Framer Motion)
import { motion } from 'framer-motion';
export function PressableButton({ children, onClick }: { children: React.ReactNode; onClick: () => void }) {
return (
<motion.button
whileTap={{ scale: 0.95 }}
whileHover={{ scale: 1.02 }}
transition={{ type: 'spring', stiffness: 400, damping: 17 }}
onClick={onClick}
className="px-4 py-2 bg-blue-600 text-white rounded-lg"
>
{children}
</motion.button>
);
}
2. Toggle switch (state visualization)
import { motion } from 'framer-motion';
import { useState } from 'react';
export function Toggle() {
const [on, setOn] = useState(false);
return (
<button
onClick={() => setOn(!on)}
className={`w-14 h-8 rounded-full p-1 ${on ? 'bg-green-500' : 'bg-gray-300'}`}
aria-pressed={on}
>
<motion.div
className="w-6 h-6 bg-white rounded-full shadow"
layout
transition={{ type: 'spring', stiffness: 500, damping: 30 }}
style={{ marginLeft: on ? 'auto' : 0 }}
/>
</button>
);
}
3. Like heart burst (demonstrate result)
import { motion, AnimatePresence } from 'framer-motion';
export function LikeButton({ liked, onToggle }: { liked: boolean; onToggle: () => void }) {
return (
<button onClick={onToggle} aria-label={liked ? 'Unlike' : 'Like'}>
<AnimatePresence mode="wait">
<motion.svg
key={String(liked)}
initial={{ scale: 0.5, opacity: 0 }}
animate={{ scale: liked ? [1, 1.4, 1] : 1, opacity: 1 }}
transition={{ duration: 0.3 }}
fill={liked ? '#ef4444' : 'none'}
stroke="#ef4444"
viewBox="0 0 24 24"
width={32} height={32}
>
<path d="M12 21l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.18L12 21z" strokeWidth="2"/>
</motion.svg>
</AnimatePresence>
</button>
);
}
4. Toast notification (status)
import { motion, AnimatePresence } from 'framer-motion';
export function Toast({ message, show }: { message: string; show: boolean }) {
return (
<AnimatePresence>
{show && (
<motion.div
initial={{ y: 100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 100, opacity: 0 }}
transition={{ type: 'spring', stiffness: 300, damping: 30 }}
className="fixed bottom-4 right-4 bg-gray-900 text-white px-4 py-2 rounded shadow-lg"
role="status"
>
{message}
</motion.div>
)}
</AnimatePresence>
);
}
5. Form validation inline shake
import { motion } from 'framer-motion';
export function ShakeInput({ error, ...props }: { error: boolean } & React.InputHTMLAttributes<HTMLInputElement>) {
return (
<motion.input
animate={error ? { x: [0, -8, 8, -8, 8, 0] } : { x: 0 }}
transition={{ duration: 0.4 }}
className={`border rounded px-3 py-2 ${error ? 'border-red-500' : 'border-gray-300'}`}
aria-invalid={error}
{...props}
/>
);
}
6. Loading skeleton (status)
export function Skeleton({ className }: { className?: string }) {
return (
<div
className={`animate-pulse bg-gray-200 rounded ${className}`}
aria-busy="true"
aria-live="polite"
/>
);
}
// usage: <Skeleton className="h-4 w-32" />
7. Reduced-motion respect
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
매 결정 기준
| 상황 | Approach |
|---|---|
| 단순 hover/press | CSS transition 충분. |
| State change (toggle, modal) | Framer Motion layout + spring. |
| Complex sequence (onboarding) | Lottie (After Effects export) 또는 Rive. |
| Performance-critical (60fps mobile) | Web Animations API + GPU-only props (transform, opacity). |
| Accessibility | prefers-reduced-motion 매 항상 respect. |
기본값: Framer Motion + spring 매 React 매 default. Tailwind animate utilities 매 simple cases.
🔗 Graph
- 변형: Framer Motion
- Adjacent: 디자인 시스템 · Web Animations API
🤖 LLM 활용
언제: state change confirmation, status communication, delight moments, error recovery. 언제 X: 매 사용자 critical path 막는 long animation, accessibility 무시 의 flashy effects, 매 30fps 떨어지는 micro interaction.
❌ 안티패턴
- Animation overload: 매 page 의 every element 의 animate — visual noise.
- Slow durations: >400ms 의 micro interaction — feels sluggish (sweet spot 100-300ms).
- Ignoring reduced-motion: 매 vestibular disorder 사용자 unusable.
- Layout-triggering animation:
width/heightanimate — paint thrash. Usetransform: scale. - Decorative-only: feedback 없이 매 just for show — 매 noise.
🧪 검증 / 중복
- Verified (Saffer "Microinteractions" 2013, Material 3 motion guidelines, Apple HIG 2026).
- 신뢰도 A.
🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — full content with 4-stage structure + 7 Framer Motion patterns |