38 lines
9.8 KiB
HTML
38 lines
9.8 KiB
HTML
<!doctype html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/>
|
|
<title>Hyeonworks — Signal Trace direction</title>
|
|
<style>
|
|
:root{--bg:#eef2f2;--panel:#f9fbfa;--ink:#102b31;--muted:#52686c;--line:#9bb0b2;--a:#176c8a;--b:#a24a3f;--merge:#165f54;--soft:#dcebea;--focus:#7b2e95}
|
|
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font-family:Arial,Helvetica,sans-serif;line-height:1.45}a{color:inherit}.skip{position:absolute;top:-5rem;left:1rem;background:var(--ink);color:white;padding:.7rem 1rem;z-index:5}.skip:focus{top:1rem}:focus-visible{outline:3px solid var(--focus);outline-offset:4px}
|
|
header{min-height:64px;display:grid;grid-template-columns:1fr auto 1fr;align-items:center;padding:0 clamp(1rem,4vw,4rem);border-bottom:1px solid var(--line);font-size:.72rem;text-transform:uppercase;letter-spacing:.1em}.brand{font-weight:900}.status{justify-self:center;display:flex;align-items:center;gap:.5rem}.status:before{content:"";width:.55rem;height:.55rem;border-radius:50%;background:var(--merge)}.scope{justify-self:end;color:var(--muted)}
|
|
main{max-width:1500px;margin:auto;padding:clamp(1.2rem,4vw,4rem)}.path{font:700 .72rem ui-monospace,monospace;color:var(--muted);letter-spacing:.06em;text-transform:uppercase}.path b{color:var(--ink)}
|
|
.intro{display:grid;grid-template-columns:1.15fr .85fr;gap:3rem;align-items:end;padding:clamp(2rem,5vw,5rem) 0 2rem}.intro h1{font-size:clamp(3rem,7vw,7.2rem);line-height:.86;letter-spacing:-.065em;margin:.8rem 0 1.4rem;font-weight:800;max-width:9ch}.intro p{max-width:58ch;color:#334e53;font-size:1.04rem}.readout{background:var(--ink);color:white;padding:1rem 1.1rem;display:grid;grid-template-columns:auto 1fr;gap:.8rem;font:600 .78rem ui-monospace,monospace}.readout b{color:#9fe0d5}.readout p{margin:0;color:#d7e2e1;font:400 .8rem/1.5 Arial,sans-serif}
|
|
.entry-label{display:flex;justify-content:space-between;gap:1rem;align-items:end;margin:2.2rem 0 .8rem}.entry-label h2{font-size:1rem;text-transform:uppercase;letter-spacing:.13em;margin:0}.entry-label span{font:700 .7rem ui-monospace,monospace;color:var(--muted)}
|
|
.bands{display:grid;grid-template-columns:1fr 1fr;gap:1rem}.band{position:relative;display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:1rem;background:var(--panel);border:1px solid var(--ink);padding:1.2rem;text-decoration:none;min-height:150px;overflow:hidden}.band:before{content:"";position:absolute;left:0;top:0;bottom:0;width:7px;background:var(--a)}.band.symptom:before{background:repeating-linear-gradient(135deg,var(--b) 0 5px,#f4c3bb 5px 10px)}.band:hover{background:var(--soft)}.code{font:800 .72rem ui-monospace,monospace;writing-mode:vertical-rl;transform:rotate(180deg);color:var(--a)}.symptom .code{color:var(--b)}.band h3{font-size:clamp(1.5rem,3vw,2.7rem);line-height:1;margin:.35rem 0}.band p{margin:.7rem 0 0;color:var(--muted);max-width:38ch}.go{font:800 1.5rem ui-monospace,monospace}
|
|
.bus{position:relative;height:110px;margin:0 12%;border-left:2px solid var(--a);border-right:2px solid var(--b)}.bus:before,.bus:after{content:"";position:absolute;top:54px;width:50%;border-top:2px solid}.bus:before{left:0;border-color:var(--a);transform:skewY(8deg);transform-origin:left}.bus:after{right:0;border-color:var(--b);transform:skewY(-8deg);transform-origin:right}.merge{position:absolute;left:50%;top:40px;transform:translateX(-50%);background:var(--merge);color:white;padding:.6rem .85rem;font:800 .7rem ui-monospace,monospace;letter-spacing:.08em;text-transform:uppercase;white-space:nowrap}
|
|
.lab{background:var(--panel);border:2px solid var(--ink);display:grid;grid-template-columns:minmax(240px,.65fr) 1.35fr}.lab-meta{padding:1.4rem;border-right:1px solid var(--line)}.lab-meta .id{font:700 .7rem ui-monospace,monospace;color:var(--merge)}.lab-meta h2{font-size:clamp(2rem,4vw,4rem);letter-spacing:-.04em;line-height:.95;margin:1rem 0}.measure{display:grid;grid-template-columns:repeat(3,1fr);gap:.5rem;margin-top:1.4rem}.probe{padding:.7rem;background:var(--bg);font:700 .68rem ui-monospace,monospace;text-transform:uppercase}.probe strong{display:block;font-size:1.45rem;color:var(--ink);margin-top:.2rem}.probe.alert strong{color:var(--b)}
|
|
.trace{padding:1.5rem;overflow:hidden}.trace-head{display:flex;justify-content:space-between;gap:1rem;font:700 .7rem ui-monospace,monospace;text-transform:uppercase;color:var(--muted);margin-bottom:1.2rem}.rail{display:grid;grid-template-columns:3.4rem 1fr 1fr;align-items:stretch;min-width:0}.rail>*{padding:.75rem .65rem;border-top:1px solid var(--line)}.rail .n{font:700 .7rem ui-monospace,monospace;color:var(--muted)}.cell{position:relative;font:700 .82rem ui-monospace,monospace}.cell:before{content:"";display:inline-block;width:.65rem;height:.65rem;border-radius:50%;background:var(--a);margin-right:.55rem}.cell.b:before{background:var(--b);border-radius:0;transform:rotate(45deg)}.cell.off{color:#879597}.cell.off:before{background:#b7c1c1}.rail.conflict{background:repeating-linear-gradient(135deg,transparent 0 8px,#f3e0dd 8px 16px)}
|
|
.loop{display:flex;gap:.55rem;flex-wrap:wrap;margin-top:1rem}.loop span{flex:1;min-width:120px;border:1px solid var(--line);padding:.75rem;font:700 .7rem ui-monospace,monospace;text-transform:uppercase}.loop b{color:var(--merge);margin-right:.4rem}
|
|
.boundary{display:flex;gap:1rem;margin-top:1rem;padding:.8rem 1rem;border-left:7px solid var(--merge);background:#d9e5df;font-size:.85rem}.boundary b{white-space:nowrap;text-transform:uppercase;font-size:.7rem;letter-spacing:.06em}
|
|
@media(max-width:800px){header{grid-template-columns:1fr auto}.status{display:none}.intro{grid-template-columns:1fr}.bands{grid-template-columns:1fr}.bus{height:80px;margin:0 20%;border-right:0}.bus:after{display:none}.merge{top:27px}.lab{grid-template-columns:1fr}.lab-meta{border-right:0;border-bottom:1px solid var(--line)}.measure{grid-template-columns:repeat(3,1fr)}.rail{grid-template-columns:2.5rem 1fr}.rail .cell:nth-child(3){grid-column:2}.rail .cell:nth-child(3){border-top:0;padding-top:0}.boundary{display:block}.boundary b{display:block;margin-bottom:.3rem}}
|
|
@media(max-width:420px){.scope{display:none}header{grid-template-columns:1fr}.measure{grid-template-columns:1fr}.intro h1{font-size:3.3rem}}
|
|
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
|
|
</style>
|
|
</head>
|
|
<body><a href="#entry" class="skip">출발 신호로 건너뛰기</a>
|
|
<header><div class="brand">Hyeonworks / Signal Trace</div><div class="status">Shared core online</div><div class="scope">Scenario 01 / Lost Update</div></header>
|
|
<main><div class="path">Concurrency / Transaction Isolation / <b>Lost Update</b></div>
|
|
<section class="intro" aria-labelledby="title"><div><h1 id="title">두 단서가 하나의 원인으로 수렴합니다.</h1><p>개념을 추적하거나 증상을 추적하세요. 입구의 신호만 다르고, 두 경로는 같은 Lost Update 실험과 상태 전이에서 합류합니다.</p></div><aside class="readout"><b>GUIDED<br/>SCENARIO</b><p>운영 로그를 분석하거나 장애 원인을 확정하지 않습니다. 고정된 증상에서 검증할 메커니즘 후보를 배우는 시나리오입니다.</p></aside></section>
|
|
<section id="entry" aria-labelledby="entry-title"><div class="entry-label"><h2 id="entry-title">Input channels</h2><span>choose one · merge before experiment</span></div><div class="bands">
|
|
<a class="band" href="#shared"><span class="code">CONCEPT</span><span><strong>개념을 알고 있어요</strong><h3>Isolation → conflict</h3><p>격리와 읽기·쓰기 충돌의 관계를 따라갑니다.</p></span><span class="go">→</span></a>
|
|
<a class="band symptom" href="#shared"><span class="code">SYMPTOM</span><span><strong>증상만 알고 있어요</strong><h3>Expected 120 → got 70</h3><p>성공한 두 요청과 예상 밖의 최종값에서 단서를 좁힙니다.</p></span><span class="go">→</span></a>
|
|
</div><div class="bus" aria-hidden="true"><span class="merge">same lab · tx-lost-update-01</span></div></section>
|
|
<section id="shared" class="lab" aria-labelledby="lab-title"><div class="lab-meta"><div class="id">SHARED LAB / TX-LOST-UPDATE-01</div><h2 id="lab-title">값의 경로를 추적하세요.</h2><p>두 세션은 모두 성공했습니다. 같은 초기값을 읽은 뒤 각자 계산하고 순서대로 썼습니다.</p><div class="measure"><div class="probe">Initial<strong>100</strong></div><div class="probe">Expected<strong>120</strong></div><div class="probe alert">Observed<strong>70</strong></div></div></div>
|
|
<div class="trace"><div class="trace-head"><span>execution rail</span><span>A = circle · B = diamond</span></div><div role="table" aria-label="두 세션 실행 순서"><div class="rail" role="row"><div class="n" role="cell">01</div><div class="cell" role="cell">A reads 100</div><div class="cell off" role="cell">B waiting</div></div><div class="rail" role="row"><div class="n" role="cell">02</div><div class="cell off" role="cell">A holds 100</div><div class="cell b" role="cell">B reads 100</div></div><div class="rail" role="row"><div class="n" role="cell">03</div><div class="cell" role="cell">A writes 150</div><div class="cell off" role="cell">B computes 70</div></div><div class="rail conflict" role="row"><div class="n" role="cell">04</div><div class="cell off" role="cell">150 overwritten</div><div class="cell b" role="cell">B writes 70</div></div></div></div></section>
|
|
<section class="loop" aria-label="공통 학습 단계"><span><b>01</b>Predict</span><span><b>02</b>Observe</span><span><b>03</b>Compare</span><span><b>04</b>Explain</span><span><b>05</b>Transfer</span></section>
|
|
<aside class="boundary"><b>Learning boundary</b><span>이 trace는 결정론적 교육 모델이며 실제 데이터베이스의 모든 스케줄과 격리 구현을 대표하지 않습니다.</span></aside>
|
|
</main>
|
|
</body></html>
|