요청: mediahub-parity
- 날짜: 2026-06-15 10:42:43
- 작업 경로: /Users/ef/CrownyOS/crownyc
요청 본문
한선씨 미디어허브 정본을 그림자로 라이브 가동하고 server.js JS 브릿지와 패리티 검증. 컷오버 절차 문서화.
관련 산출
그림자 기동 (완료)
- PID: crownyc 65413, LISTEN :9888
- 컴파일:
CROWNY_STD=/Users/ef/CrownyOS/crownyc/libs ./hanseonc_high /Users/ef/crowny-tiomta/미디어허브.한선 > /tmp/미디어허브.toau 2>/dev/null - 기동:
CROWNY_STD=/Users/ef/CrownyOS/crownyc/libs /Users/ef/CrownyOS/crownyc/crownyc run /tmp/미디어허브.toau > /tmp/미디어허브.log 2>&1 & - 포트 등록:
crowny-ports.sh set media-hub 9888→ SSOT 갱신 완료
패리티 표
| 엔드포인트 | :9888 (한선씨) 상태 | :9878 (JS) 상태 | 패리티 | 불일치 내용 |
|---|---|---|---|---|
| /api/media/health | 200 + Content-Length:55 | 404 (라우트 없음) | N/A | health는 한선씨 전용 신규 |
| /api/media/tube/list | 200 + Content-Length:732, 즉시종료 | 200 | 데이터 일치, 포맷 불일치 | 9888=raw {total,videos:[{id,title}]} / 9878={items:[{id,title,author,source,icon}]} norm 래핑 |
| /api/media/song/tracks | 200 + Content-Length:696, 즉시종료 | 200 | 데이터 일치, 포맷 불일치 | 9888=raw {total,tracks:[{id,title}]} / 9878={items:[...norm]} |
| /api/media/tok/timeline | 200 + Content-Length:1136, 즉시종료 | 200 | 데이터 일치, 포맷 불일치 | 9888=raw {total,posts:[{id,text}]} / 9878={items:[{id,title,...norm}]} text→title 필드명 변환 |
| /api/media/song/curation?type=5 | 200 + Content-Length:467, 즉시종료 | 200 | PASS (구조 동일) | 둘 다 {curation:[...]} 그대로 패스스루 |
| /api/media/youtube?url=... | 200 + Content-Length:868, 즉시종료 | 200 | 데이터 일치, 포맷 불일치 | 9888=raw oembed 전체 / 9878={title,author,thumb,html,source} 추출 |
발견/수정한 한선씨 함정
없음. 미디어허브.한선은 이미 올바른 패턴을 사용 중:
체계()+> 임시파일+읽기()패턴 (stdout 캡처 우회)_바이트수()함수로 UTF-8 Content-Length 정확 계산 (한글 잘림 방지)- 경로에서
?이후 쿼리스트링 제거 (포함(경로,"?")가드) Connection: close+ Content-Length 명시 → 즉시 종료 확인됨
컷오버 절차 권고
**방법: server.js의 /api/media/* 핸들러를 :9888 프록시로 교체
server.js에서 /api/media/ 블록(1914~1961줄)을 아래 스니펫으로 대체:
jsif (url.pathname.startsWith('/api/media/')) {
// 한선씨 미디어허브 :9888으로 프록시 (정본 이전 완료)
const target = 'http://127.0.0.1:9888' + url.pathname + (url.search || '');
try {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), 8000);
const upstream = await fetch(target, { method: req.method, signal: ctrl.signal });
clearTimeout(t);
const body = await upstream.arrayBuffer();
res.writeHead(upstream.status, {
'Content-Type': upstream.headers.get('Content-Type') || 'application/json',
'Content-Length': body.byteLength,
'Access-Control-Allow-Origin': '*',
});
return res.end(Buffer.from(body));
} catch(e) {
return jsonRes(res, 502, { error: 'media_hub_unavailable', detail: String(e) });
}
}
주의: 프런트(tmCard)가 { items: [...norm] } 형태를 기대하고 있으면, 컷오버 전에:
추천**: 미디어허브.한선을 수정해 norm 래핑 추가 (프런트 코드 불변). 컷오버 작업은 gateway/main 세션에 위임.videos/tracks/posts 키)로 수정
파일 위치
- 정본:
/Users/ef/crowny-tiomta/미디어허브.한선 - 그림자 toau:
/tmp/미디어허브.toau - 로그:
/tmp/미디어허브.log - 포트 SSOT:
~/.claude/knowledge/PORTS.md→ media-hub:9888