User flow

사용자 흐름

A flowchart of the screens and decision points a user passes through to complete one task, start to finish.

Also known as: Flow diagram유저 플로우
···
html
<div class="stage">
  <svg viewBox="0 0 420 120" class="flow">
    <g id="edges"></g>
    <g id="nodes"></g>
    <circle id="ball" r="5" class="ball" />
  </svg>
</div>
css
.stage{width:96%;height:88%}
.flow{width:100%;height:100%}
.box{fill:var(--surface);stroke:var(--line);stroke-width:1.5}
.box.diamond{fill:var(--surface)}
.edge{stroke:var(--muted);stroke-width:1.4;fill:none;marker-end:url(#arrow)}
text{font:700 8.5px sans-serif;fill:var(--fg);text-anchor:middle}
.ball{fill:var(--accent)}
js
const NS = 'http://www.w3.org/2000/svg';
const svg = document.querySelector('.flow');
const defs = document.createElementNS(NS, 'defs');
defs.innerHTML = '<marker id="arrow" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"><path d="M0 0 L8 4 L0 8 Z" fill="var(--muted)"/></marker>';
svg.prepend(defs);
const edgesG = document.getElementById('edges');
const nodesG = document.getElementById('nodes');
const nodes = [
  { x: 30, y: 60, w: 46, h: 30, t: 'Start' },
  { x: 130, y: 60, w: 58, h: 30, t: 'Login' },
  { x: 250, y: 30, w: 50, h: 28, t: 'Error', diamond: true },
  { x: 250, y: 90, w: 58, h: 30, t: 'Home' },
  { x: 380, y: 90, w: 30, h: 30, t: 'Done', circle: true },
];
const edges = [[0, 1], [1, 2], [1, 3], [3, 4]];
function drawNode(n) {
  if (n.circle) {
    const c = document.createElementNS(NS, 'circle');
    c.setAttribute('cx', n.x); c.setAttribute('cy', n.y); c.setAttribute('r', 15);
    c.setAttribute('class', 'box');
    nodesG.appendChild(c);
  } else {
    const r = document.createElementNS(NS, 'rect');
    r.setAttribute('x', n.x - n.w / 2); r.setAttribute('y', n.y - n.h / 2);
    r.setAttribute('width', n.w); r.setAttribute('height', n.h);
    r.setAttribute('rx', n.diamond ? 14 : 5);
    r.setAttribute('class', 'box');
    nodesG.appendChild(r);
  }
  const t = document.createElementNS(NS, 'text');
  t.setAttribute('x', n.x); t.setAttribute('y', n.y + 3);
  t.textContent = n.t;
  nodesG.appendChild(t);
}
nodes.forEach(drawNode);
edges.forEach(([a, b]) => {
  const p = document.createElementNS(NS, 'path');
  const A = nodes[a], B = nodes[b];
  p.setAttribute('d', 'M' + (A.x + (A.w || 30) / 2) + ' ' + A.y + ' L' + (B.x - (B.w || 30) / 2) + ' ' + B.y);
  p.setAttribute('class', 'edge');
  edgesG.appendChild(p);
});
const ball = document.getElementById('ball');
const path = [0, 1, 3, 4];
let i = 0;
function step() {
  const n = nodes[path[i % path.length]];
  const above = n.circle ? 22 : (n.h || 30) / 2 + 12;
  ball.setAttribute('cx', n.x);
  ball.setAttribute('cy', n.y - above);
  i++;
}
step();
setInterval(step, 900);

A user flow picks one concrete task — "sign up," say — and diagrams every screen from start to finish along with every branch point (success/failure, logged in or not) as boxes, arrows, and decision diamonds. The content of the diagram is the path between screens, not the detailed design of any one of them.

If information architecture is the map of a site's entire content hierarchy, a user flow is one specific path a person actually walks across that map. The same IA can produce several different user flows depending on the task — a logged-in user's checkout looks different from a guest's.

Draw it before development starts and it quickly exposes where the team silently disagreed about what comes after a given screen. Error states and edge branches (wrong password, out of stock) are the easiest thing to leave out — and exactly the part that gets forgotten most often in the real build.

When to use

Use it before development starts, whenever the team needs to agree on the exact path — and every exception branch — between screens.