colorchip — 작업 규칙
규칙만 둔다. 상태·이력은
handoff.md, 완료이력은archive.md(생기면). 설계 =design.md.
🆕 신규 (2026-09-29 — 프로젝트 착수 규칙)
-
⚠ [코디] P6 마무리 함정 3개(26.10.9) — ①
cycles_check --keep뒤 집PC GPU claim 을 안 풀면 실렌더 job 이 전부 GPU_BUSY 실패 → 점검 끝나면release②실패한 렌더도 직원·전체 하루 한도에 들어간다(GPU_BUSY 4건 = 429 유발, devRCNT#<날짜>수동 복구함) — 운영 전 «실패는 한도 환불» 보완 후보 ③detail.js(뷰어 형상)를 바꾸면C:\dev\colorchip\render\blender\ccgeom.py·골든·RENDER_SCENE_VERSION을 같이 올린다(P5 손잡이가 렌더에서 빠졌던 원인). -
⚠ [코디] color_check 의
color_<target>*_<preset>_<chip>.png는 «마스크 증거 그림»이지 화면 캡처가 아니다(26.10.9) — 마스크 밖을 ×0.28 로 어둡게 칠해(방 전체 어두움) 손잡이 띠·틈·휘도 이탈 픽셀(점선 구멍)이 검게 보인다. 비교판·육안 판정에 쓰지 마라(Cycles 비교판 왼쪽에 잘못 써서 «뷰어가 어둡고 구멍 난다» 오인 → 실기·dev 실주소는 정상이었다). 실기 화면 =C:\dev\colorchip\three\tools\p6_real_shots.py --link <https ?k=> --chip N515(캔버스 캡처_canvas.png) →C:\dev\colorchip\render\tools\side_by_side.py. -
⚠ [코디] P6 함정 5개(26.10.9) — ①오버레이가 열린 채 새로고침하면 history 깊이가 어긋나 닫기·closeAll 이 영영 안 끝난다(수리 =
C:\dev\colorchip\web\viewer\src\ui\overlay.js) ②DynamoDB 트랜잭션 동시 충돌은 «조건 실패»가 아니라 TransactionConflict 로 따로 와서 재시도 경로를 안 탄다 →C:\dev\colorchip\api\cc_api\repo\dynamo.py에서 짧게 재시도 ③집PC 는 Windows Home 이라query user가 없다 → 사용자 입력 시각은 /IT 예약작업 + GetLastInputInfo 로 읽는다(C:\dev\colorchip\render\worker\remote\activity.ps1) ④gpuboxoff는 라벨을 안 받는다 → 작업마다release후 끈다 ⑤렌더 이미지는 서명 URL 대신 같은 출처/render/image/{hash}로 내보낸다(CSP 준수 · 계약 1.6.1) -
⚠ [코디] P5 함정 4개(26.10.8) — ①
room_bake.py가 집PC 를 실제로 못 껐다: gpubox CLIoff는 라벨을 안 받아 자기 GPU claim 에 막힘 → claim 해제 후 끄기로 수리됨(집PC 끄기 확인은 매번) ②손잡이 띠가 도어 픽셀 ~6% 를 가려 색이 그대로여도 마스크 ΔE 가 ±0.02 움직인다 → 디테일 추가 때는 기준선 교체로 판정 ③방 조명 아래 가구 모서리에서 350mm 화분이 오른쪽 시점 도어 14,465px 를 가렸다 → 소품은 가구 모서리에서 720mm 이상 ④소품 라이브러리 빌드는 텍스처 노이즈 시드를 정렬 순서로 정한다 → 주방 GLB 를 바이트 동일로 두려면 텍스처 사전을 바꾸지 마라. -
⚠ [코디] P3b 함정 3개(26.10.8) — ①
PUT /config/presets뒤release.json은 퍼블리시 60초 디바운스 → 즉시 GET 하지 말고 폴링 ②파이썬write_text는 윈도우에서 CRLF →newline="\n"③방 마감(무드·벽·바닥)은 칩 도어 ΔE 에 영향 0(라이트맵 무채·환경 고정, 실측 0.000) — 무드 추가 때 ΔE 재측정은 확인용 1회면 충분. -
⚠ [코디] 후처리 단계 함정 5개(26.10.8 P4 · 비채택) — ①N8AO
transparencyAware자동감지는 값이 «바뀔 때만» 꺼진다 →autoDetectTransparency=false직접 ②N8AO 합성 셰이더 uniforms 를 인스턴스끼리 공유(three ShaderMaterial 은 uniforms 를 복제 안 함) → 같은 페이지 A/B 에서 앞 설정(nochip)이 다음 설정으로 샌다 ③toneMapped:false발광 재질은 OutputPass 경로에선 톤매핑된다(1.0 → 0.89) → HDR 배수 ④후처리는render()를 여러 번 불러renderer.info가 마지막 패스만 센다(콜 1) ⑤블룸은 아무리 약해도 천장 간접조명 띠 번짐이 어두운 상부장 칩에 더해져 ΔE 실패 — 칩 색 원칙과 양립 안 함. 렌더 타깃 경로 GPU = 체인만 +53MiB · N8AO +85MiB(노트20 kgsl). -
⚠ [코디] 소품 단계 함정 6개(26.10.8 P3) — ①glTF 표준 키
alphaCutoff가 누출 금칙 토큰cut에 걸린다 → 키 생략(기본 0.5) ②소품 켬/끔 비교는setView직후 궤도 감쇠가 몇 프레임 더 움직여 가장자리 가림을 오탐 → 700ms 대기 후 촬영 ③첫 렌더가ready보다 먼저라_stats().props는 처음 null = «아직»으로 기다린다 ④중성화한 어두운 HDRI 에선 metalness 1 넓은 수평면이 숯색 → 마감 금속만 env 3.0(LOOK.room.finishMetalEnv) ⑤세로 화면 기본 시점 가로 화각 ±24° — 가구 앞 동선의 펜던트가 시선 높이에서 도어를 가린다 → 다이닝은 카메라 뒤 ⑥p3_shots.py·p1_shots.py같은 태그 = 리포트 이름 충돌(덮어씀) → 태그를 다르게. -
⚠ [코디] 가구 디테일 단계 함정 4개(26.10.8 P2) — ①굽힌 조도 무릎(
ccKnee)을 벽까지 걸면 백스플래시가 회색으로 죽는다 → 천장 재질에만 ②도어 안쪽 틈 그늘 판에 polygonOffset 을 주면 비스듬히 볼 때 도어 앞면을 뚫는다 → 바이어스 없는 별도 재질 1콜 ③형상이 바뀌는 단계에선 전체 마스크 ΔE 가 마스크 구성 변화로 ±0.04 흔들린다 → 두 빌드 마스크 교집합 차분으로 판정(≤0.03 이면 색 불변) ④배열을 순회하며 상판을 싱크 컷으로 나누면 원본+조각이 같이 남는다 → 순회 끝난 뒤 분할. 설비 인식 = 박스 id 꼬리(/hood·/basin·/cooktop·/faucet) 약속(계약에 종류 필드 없음). -
⚠ [코디] 방 라이트맵 베이크 함정 5개(26.10.8 P1) — ①bmesh
faces.new()직후 법선 미계산 →normal_update()없이 방향 판정하면 다운라이트 원판이 위를 보고 컬링 ②라이트맵을 손실 WebP 로 저장하면 매끈한 조도에 8×8 블록 계단 → 무손실 ③Blender 렌더 출력 상대경로 =C:\로 샌다 → 절대경로 ④발광 원판·띠를 굽기에 넣으면 바로 위 천장을 가려 검은 점 → 굽기 땐hide_render⑤실주소 측정 페이지의 인라인 스크립트는 CSP 에 막힘 → JS 외부 파일(C:\dev\colorchip\three\sandbox\p1lab\). 재실행 =python C:\dev\colorchip\three\bake\room_bake.py(집PC gpubox, 변형당 ~65초). -
⚠ [코디] 3D 에셋·폰 측정 함정 4개(26.10.8 P0 실측) — ①현 CSP(
script-src 'self'·connect-src 'self')에서 GLTFLoader 기본 경로는 GLB 내장 이미지를 blob: 주소로 fetch →connect-src에 막혀 텍스처가 조용히 빈다 → img 로더 플러그인 경로를 쓴다(뷰어에 넣어 둠) ②meshopt ='wasm-unsafe-eval'1개면 되지만 KTX2 basis 는 트랜스코더가new Function을 써서'unsafe-eval'까지 필요 → 쓰지 않는다. [코디] 26.10.8 결정 = CSP 유지 · 무압축 GLB(KHR_mesh_quantization 가능)+WebP ③노트20 GPU 메모리 = 루트 없이/d/kgsl/proc/<크롬 GPU pid>/mem합(about:blank 대비) — dumpsys GL mtrack 은 안 변해 못 쓴다 · 도구C:\dev\colorchip\three\tools\phone_mem.py④노트20이 어두운 곳에 있으면 삼성 «실수 터치 방지» 창이 크롬·카톡을 막는다 → 측정 동안만screen_off_pocket=0, 끝나면 1 복구(도구--pocket-off). 색 측정 =C:\dev\colorchip\three\tools\color_check.py(도어 마스크 ΔE00, 기준선C:\dev\colorchip\three\test\baseline\p0-baseline.json). -
⚠ [코디] tailscale serve 뒤 파이썬 프록시 함정 2개 + 로컬 JSON 저장소 경로(26.10.6) — ①응답 전에 요청 본문을 끝까지 안 읽으면(403 조기 응답 등) serve 가 재사용한 백엔드 연결에 찌꺼기가 남아 다음 요청이 501·40초 멈춤 → 무엇을 답하든 본문부터 다 읽는다(chunked 포함) ②
ThreadingHTTPServer기본 backlog 5 = 브라우저가 ESM 모듈 15개를 동시에 받을 때 serve 가 502 →request_queue_size=128③JsonFileRepository는 키를 hex 파일 이름으로 써서 sha256 전체 같은 긴 키는 윈도우 260자 경로 한도에 걸린다 → 임시값 키는 짧게(fa:<sha256 앞 32hex>). 접속 횟수 실주소 e2e 는 devACC#<sub>를DynamoRepository.save_access로 조작(30분 경과·39·49회). 도구 =C:\dev\tools\colorchip-tailnet\proxy.py·C:\dev\colorchip\api\tools\e2e_accounts.py. -
⚠ [코디] 3D 재발행·실주소 검사 함정 4개(26.10.6) — ①
C:\dev\pncadHEAD 가 베이크 기준(9e241a9)보다 앞서면 가구 박스가 달라진다 →git clone --shared임시본을 9e241a9 로 체크아웃해PNCAD_DIR로 넘긴다 ②PUT /config/presets두 번째부터 409 「rev 가 필요합니다」 →publish.mjs --rev <currentRev>③CSP(unsafe-eval없음) 때문에 실주소에서 Playwrightwait_for_function이 EvalError →evaluate폴링 ④작업 폴더에 남의 미커밋 변경(web\shared\api등)이 있으면 뷰어는git archive HEAD web/viewer web/shared three/dist로 꺼낸 깨끗한 복사본에서 빌드·배포. 또 three 톤매핑 PBR Neutral 은 모든 채널에서 0.04 를 빼 환경광이 약한 방에선 어두운 칩이 뭉개진다(→ CustomToneMapping F=0.01). -
🔑 [코디] API Gateway HTTP API(v2) 엔 Gateway Responses 가 없다 — JWT 인가자 401 본문은
{"message":"Unauthorized"}고정이라 계약 오류 형식으로 못 바꾼다(REST API v1 전용 기능). [총괄] 결정 = 현행 유지(게이트웨이+앱 2겹 방어), 클라이언트는 상태코드로만 분기(401=재로그인). 또 CloudFront 는 S3 GetObject 만 주면 없는 키가 404 가 아니라 403 → 뷰어는 403·404 를 같게 처리. -
🔴 [코디] 폰 카톡 자동 입력은 매 단계 포커스 확인 필수(26.9.29 사고) —
phone_kakao.py가 인앱 브라우저를 연 뒤 새 메시지로 고객 채팅방(포인-오엠씨)이 앞에 오자 주소창 탭·input text가 그 방 입력창에 들어갔다(Enter 는 줄바꿈이라 전송 안 됨, uiautomator 로 입력창 text 확인 후 DEL·FORWARD_DEL 로 지움). 노트20 은 다른 세션(D 뷰어 등)과 번갈아 쓰여 잠금을 다시 잡으면 화면이 딴 데 있다 → 탭·입력·Enter 직전마다P.state()['focus']가InAppBrowserActivity인지 보고 아니면 중단. 가드 =C:\dev\colorchip\three\tools\phone_kakao.py. -
⚠ [코디] 베이크 z-파이팅 2종 — ①같은 방향을 보는 두 면이 한 평면(목찬넬 뒷판 앞면 = 측판 마구리 z570 · 신발장 좌대 EP 앞면 = 안쪽 측판 늘인 앞면 z380)이면 틈으로 몸통색이 번쩍인다 → 0.5mm 당기거나 안쪽 측판은 늘이지 않는다 ②ambientCG
PBRApproximated에셋의 NormalGL 은 평면(1K 에 2KB)이라 텍스처 슬롯만 먹는다 → 노멀은 실제 요철(타일 줄눈) 있는 것만. -
⚠ [코디] 로컬 목(8840)→E 로컬 API(8841) 프록시는
Host헤더를 바꾸지 마라(26.9.29 실측) — E 가 refresh·logout 에서 Origin 과 Host 를 대조해 교차 출처를 막는다 → Host 를 8841 로 바꾸면 로그인은 되는데 새로고침 복구·로그아웃이 403 「교차 출처 요청은 받지 않습니다」. 또 CDPRuntime.evaluatereturnByValue로 DOM 노드를 돌려받으면{}(파이썬 거짓)라 대기 조건은!!(…)로 감싼다. E 로컬 API 가 내려가 있으면(E 세션 재시작 중) 뷰어 로그인은 「잠시 후 다시 시도」 = 502 —C:\dev\colorchip\_mock\viewer-serve.log의proxy fail로 판정. -
[페페] 26.9.29 관리 로그인 칸만 브라우저 자동완성 허용(droplist·자동완성 금지 전역 규칙의 colorchip 예외).
-
🔑 [코디] 노트20 카톡 인앱에서 두 손가락 핀치를 기계로 넣는 법(26.9.29 실측) —
adb shell input은 한 손가락뿐 · 카톡 WebView 는 DevTools 소켓 없음 ·/dev/input/event3(sec_touchscreen)sendevent는 셸이 input 그룹이어도 SELinux 로 Permission denied. ⛒ 셸의 INJECT_EVENTS 권한으로CLASSPATH=<jar> app_process / Pinch …→InputManager.injectInputEvent에 2포인터 MotionEvent(scrcpy 와 같은 경로). 도구 =C:\dev\colorchip\web\viewer\tools\phone_pinch.py+android\Pinch.java(JDK17·d8 로 자동 빌드). 목 사이트에서 불변 키(c/·d/) 내용을 같은 키로 바꾸면 폰이 1년 캐시로 옛것을 보여 준다 → 목도 새 내용 = 새 해시 키. - 🔴 [코디] D 뷰어 실측 함정 4개(26.9.29) — ①오버레이 1개 = pushState 1칸 구조에서 오버레이가 열린 채
replaceState로 라우트 URL 을 바꾸면(3D 슬롯 선택) 그 URL 은 오버레이 칸에만 남아 닫을 때(뒤로) 옛 URL 로 되돌아간다 → 닫힘 popstate 에서 마지막 URL 을 다시 replaceState(web\viewer\src\ui\overlay.jsnoteRouteUrl), 같은 해시 hashchange 는 재렌더 생략 ②폰 크롬 실기에서el.click()(DevTools 평가)은 사용자 활성화가 없어 http 주소의execCommand('copy')가 실패한다 → 복사 검사는Input.dispatchTouchEvent실제 탭으로 ③Input.synthesizePinchGesture는 안드로이드 크롬에서 아무 일도 안 한다(오류도 없음) → 핀치는Input.dispatchTouchEvent2점 주입(web\viewer\tools\phone_check.py) ④Phone.awake()를 호출마다 새로 잡으면 사이에 다른 앱이 앞으로 온다(카톡 인앱이 닫히고 크롬 127.0.0.1:8445 가 뜸) → 폰 단계는 한 번의 awake 안에서 끝까지. http(테일스케일) 주소에선navigator.share가 없다(보안 컨텍스트 전용) → https 배포 뒤 다시 본다. -
⚠ [코디] D 뷰어 실데이터·배포 함정 4개(26.9.29 4차) — ①DOM 네이티브
replaceChildren·append는null을 글자 「null」로 넣는다(h()는 거름) → 조건부 자식은.filter(Boolean), 검사 =web\viewer\tests\dom-null.test.js②D3deploy.py의 immutable 판정은name.<해시>.ext모양만 —x.<해시>.min.js는 no-cache 로 올라간다(빌드가x.min.<해시>.js로 낸다) ③배포 전 빌드 폴더는 옛 해시가 쌓이니 지우지 말고site.old-*로 옮긴 뒤 새로 빌드 →--dry-run→ 실제(삭제는 훅이 막는다) ④노트20 크롬의navigator.share시트는 크롬 자체 시트라 앞 창이 크롬 그대로다(시스템 Chooser 아님) → 닫을 땐 크롬 전면 확인 후 BACK 1번, 그 전에 CDP 탭을 닫으면 시트도 같이 닫힌다. 미니PC 에서 실 도메인 이름풀이가 끊기면 Playwright 는--host-resolver-rules=MAP hyosan.poin.co.kr <DoH IP>, 목 서버--real은 자동 DoH 재시도. -
🔴 [코디] B 폰 실측 함정 3개(26.9.29) — ①
adb shell am start -d <URL>은 인자를 원격 셸 한 줄로 이어 URL 의&가 백그라운드 연산자로 먹힌다(뒤 파라미터가 조용히 사라짐) →-d '<URL>'작은따옴표 ②카톡 인앱 브라우저는kakaotalk://inappbrowser?url=…의 url 을 무시(빈 화면) → 스킴으로 열고 주소창(440,171) 탭 →input text로 URL 입력 ③카톡 인앱 WebView 는 DevTools 소켓이 없다 → 수치는 화면 오버레이 스크린샷으로 판독. 도구 =C:\dev\colorchip\three\tools\phone_check.py·phone_kakao.py. - 🔑 [코디] 베이크 누출 검사 = 금칙 토큰(pncad 아티클·CP·자재·디스크립터·현장변수 ≈2.4k) 부분일치 + 자체검사. 함정: ①현장변수 이름에
Molding·Sink같은 일반 영단어가 있어 박스 id 에 쓰면 걸린다 → id 를crown·basin으로 ②해시 키(g/<hex24>.json)가 짧은 토큰(b1d)과 우연히 겹친다 → 해시·커밋 hex 문자열은 토큰 검사에서 뺀다.C:\dev\colorchip\three\bake\leakcheck.mjs. -
⚠ [코디] pncad
skipped는 B_SD(placeholder 밴드 2)·B3D(속서랍)(텐덤 서랍통) 에서 난다 — 전부 도어 뒤 내부라 시각 영향 없음 → 계약 §8.12 #4 「skipped 아티클 피한다」의 예외로 채택(총괄 확인 대상). 하부 도어 위 찬넬 스트립(밑장_SDO_noHandle)은 도어와 같은 평면에 겹쳐 그려져 있어 베이크가 «다른 FRONT 가 통째로 덮는 FRONT» 로 제거한다. -
🔴 [페페] 0파 계약(
CONTRACT.md)이 굳기 전에는 병렬 세션(A~E)을 열지 않는다. 스키마·API·S3 키·manifest·이력·토큰이 어긋나면 5개 세션이 각자 다른 모양으로 만든다. - 🔑 [코디] S3 키·리소스 이름에 도메인·브랜드명을 넣지 않는다(
hyosan·poin금지). 도메인은 임시hyosan.poin.co.kr이고 실사용 시 효산이 별도 서버로 이관한다 — 이식성이 최우선. 원본·파생 파일은 manifest + 체크섬으로 관리한다. [코덱스] 검토 반영. - 🔑 [코디] DB = DynamoDB 이되 Repository API 로 추상화하고, 정기적으로 JSON/CSV·원본을 S3 로 내보내 이관에 대비한다. 코드가 DynamoDB 를 직접 부르지 않는다. [코덱스]
- 🔑 [코디] 칩 상태·변경자·시각·사유는 불변 이력으로 남긴다. 삭제 대신 숨김. 관리자 계정은 포인이 1~3개 발급한다([페페] Q7).
- 🔴 [코디] 고객 링크 = 추측 불가 토큰 + 링크별 브랜드 + 만료/폐기. 효산 링크는 효산 로고·연락처, 포인 링크는 포인([페페] Q3). 고객에겐 판매중만 보인다. MASTER 에 없는 312코드는 고객 숨김·직원만 「확인 필요」([페페] Q6).
- 🔑 [코디] 원자료 함정 5종을 파이프라인이 알아야 한다 — ①색공간 7종(S 시리즈 192 전부 CMYK → sRGB 변환) ②
N778.jpeg는 실체가 PSD ③._맥 찌꺼기 파일 무시 ④칩카드 48장은 HYOSAN 워터마크가 박혀 텍스처로 못 쓴다(OCR 로 코드만 뽑는다) ⑤N779 우드·패브릭 중복 + ~235코드가 여러 북에 중복. DPI 메타는 틀렸다 → 폴더 표기(1200×1500mm 등)+픽셀로 실물 크기를 계산한다. - 🔑 [코디] 대용량 업로드는 S3 multipart 후 비동기 처리한다(Lambda 동기 처리 금지). [코덱스]
- 🔴 [코디] 3D 는 수직 슬라이스 먼저 — 한 모델·한 색 묶음·옵션 on/off 로 실제 폰에서 돌려본 뒤 붙박이장·신발장으로 넓힌다. pncad 엔진(
C:\dev\pncad\schema.js) 재사용은 스파이크로 먼저 검증한다. [코덱스] - 🔴 [코디] 헤드리스 브라우저는 WebGL/GPU 버그를 못 잡는다 — 3D 검증은 실제 폰(노트20 adb) 에서 한다. iOS 실기는 수단 미확보(리스크로 남김). 카톡 인앱 브라우저 실기 검증 필수. 테스트는
localhost가 아니라 실제 사용 주소로(보안 컨텍스트 차이). - ⚠ [코디] 화면(UI) 작업은 착수 전
web-designer상담(폰트 13px 하한 · 자체 드롭리스트 —<datalist>·네이티브 select 금지). 3D 가구는furniture-expert자문. - ⛔ [코디] 외부 노출·DNS·AWS 자원 생성·삭제는 위험작업 게이트 — 지시문에 승인이 명시된 것만.
poin.co.kr존은 호스팅코코아(대행사 contentsworks)라 CNAME·ACM 검증 레코드 추가에 대행사 협조가 필요하다(BRIEF.poin-site.md). - ⚠ [코디] 백업·복구·감사로그·캐시 무효화·효산 인수테스트·운영문서를 마지막에 빠뜨리지 않는다(마무리 단계). [코덱스]