색상 조화 원리

Color harmony wheel

보색·유사색·삼각·분할보색 같은 배색 규칙을 색상환 위 각도로 요약한 것. 규칙마다 마커 개수와 각도가 다릅니다.

다른 이름: Color wheel컬러 하모니
···
html
<div class="wrap">
  <div class="row">
    <div class="wheel" id="wheel"><div class="marker" id="m0"></div><div class="marker" id="m1"></div><div class="marker" id="m2"></div><div class="marker" id="m3"></div></div>
    <div class="swatches" id="sws"></div>
  </div>
  <div class="tag" id="tag">Complementary</div>
</div>
css
.wrap{display:grid;gap:12px;justify-items:center;width:min(600px,94%)}
.row{display:grid;grid-template-columns:auto 1fr;gap:clamp(14px,4vmin,28px);align-items:center;width:100%}
.wheel{position:relative;width:clamp(100px,30vmin,180px);height:clamp(100px,30vmin,180px);border-radius:50%;cursor:grab;touch-action:none;
  background:conic-gradient(hsl(0 80% 55%),hsl(60 80% 55%),hsl(120 80% 55%),hsl(180 80% 55%),hsl(240 80% 55%),hsl(300 80% 55%),hsl(360 80% 55%));
  box-shadow:0 0 0 1px var(--line),0 10px 26px rgba(0,0,0,.18)}
.marker{position:absolute;width:16%;height:16%;min-width:13px;min-height:13px;border-radius:50%;background:#fff;border:3px solid var(--fg);transform:translate(-50%,-50%);box-shadow:0 2px 6px rgba(0,0,0,.35)}
.swatches{display:grid;gap:6px}
.sw{height:clamp(20px,5vmin,28px);border-radius:7px;border:1px solid var(--line);display:flex;align-items:center;padding:0 9px;font:700 clamp(9px,2.4vmin,11px)/1 ui-monospace,monospace;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.4)}
.tag{font:800 clamp(11px,3vmin,14px)/1 ui-monospace,monospace;letter-spacing:.04em;color:var(--fg);padding:6px 14px;border:1px solid var(--line);border-radius:999px;background:var(--surface)}
js
const PRESETS = [
  { name: 'Complementary', offsets: [0, 180] },
  { name: 'Analogous', offsets: [-30, 0, 30] },
  { name: 'Triadic', offsets: [0, 120, 240] },
  { name: 'Split-Comp', offsets: [0, 150, 210] },
  { name: 'Tetradic', offsets: [0, 90, 180, 270] },
];
const wheel = document.getElementById('wheel');
const markers = [0, 1, 2, 3].map(i => document.getElementById('m' + i));
const sws = document.getElementById('sws'), tag = document.getElementById('tag');
let base = 210, presetIdx = 0, autoRotate = true;

function place(hue, el, R) {
  const rad = hue * Math.PI / 180;
  el.style.left = (50 + R * Math.sin(rad)) + '%';
  el.style.top = (50 - R * Math.cos(rad)) + '%';
}
function render() {
  const preset = PRESETS[presetIdx];
  tag.textContent = preset.name;
  markers.forEach((m, i) => {
    if (i < preset.offsets.length) {
      const h = (base + preset.offsets[i] + 360) % 360;
      place(h, m, 40);
      m.style.background = 'hsl(' + h + ', 78%, 52%)';
      m.style.display = 'block';
    } else {
      m.style.display = 'none';
    }
  });
  sws.innerHTML = preset.offsets.map(off => {
    const h = (base + off + 360) % 360;
    return '<div class="sw" style="background:hsl(' + h + ',78%,52%)">' + Math.round(h) + '°</div>';
  }).join('');
}
function angleFromEvent(e) {
  const r = wheel.getBoundingClientRect();
  const cx = r.left + r.width / 2, cy = r.top + r.height / 2;
  const deg = Math.atan2(e.clientX - cx, -(e.clientY - cy)) * 180 / Math.PI;
  return (deg + 360) % 360;
}
wheel.addEventListener('pointerdown', e => { autoRotate = false; wheel.setPointerCapture(e.pointerId); base = angleFromEvent(e); render(); });
wheel.addEventListener('pointermove', e => { if (e.buttons) { base = angleFromEvent(e); render(); } });
tag.addEventListener('click', () => { presetIdx = (presetIdx + 1) % PRESETS.length; render(); });

let lastSwitch = 0;
(function tick(t) {
  if (autoRotate) base = (base + 0.25) % 360;
  if (t - lastSwitch > 2600) { presetIdx = (presetIdx + 1) % PRESETS.length; lastSwitch = t; }
  render();
  requestAnimationFrame(tick);
})(0);

색상환은 색상(hue) 0~360°를 원으로 배치한 것뿐입니다. "조화"는 그 원 위에 몇 개의 점을 어떤 각도로 찍느냐의 문제로 단순화됩니다 — 보색은 2점(180°), 유사색은 3점(±30°), 삼각은 3점(120°씩), 분할보색은 3점(0°, 150°, 210°).

색상환 자체는 채도·명도를 담지 못한다는 한계가 있습니다. 두 색이 각도상으론 "조화"로워도 한쪽만 쨍하고 한쪽은 탁하면 균형이 깨집니다. 그래서 실무에서는 각을 먼저 정하고, 그 다음 채도·명도로 미세 조정합니다.

기준 색상을 하나 정한 뒤 이 규칙들 중 무엇을 적용할지 고르는 게 배색을 시작하는 가장 빠른 방법입니다.

언제 쓰나

배색을 처음부터 설계할 때, 어떤 규칙으로 시작할지 감을 잡는 용도로 씁니다.