---
title: "작업보고 — 토글 정렬 근본수정 + 전역 모서리 2px + 스튜디오 신토큰 및 라이브 1클릭 커밋·푸시 워커 (PR#83)"
category: "workreport"
document_type: "작업보고"
source_status: "generated"
knowledge_group: "03_history"
priority: "Medium"
purpose: "PR#83의 세 갈래 작업(① 구독관리 토글이 깨지던 전역 input width:100% 근본 원인 수정, ② 사장님 지시에 따른 전역 모서리 2px 통일과 원형·토글 트랙 예외, ③ /studio의 1클릭 커밋·푸시를 dev 전용에서 studio-publish 워커 경유로 라이브 어디서든 동작하도록 확장)을 풀 깊이로 복원해, 무엇을·왜·어떻게 바꿨고 어떤 판단과 Codex 회귀검수를 거쳤는지 추적 가능하게 한다. UI 디자인시스템·스튜디오 발행 파이프라인·최신 상태 복구의 기준 기록으로 쓴다."
read_when: ["UI","디자인시스템","토글정렬","모서리2px","스튜디오","studio-publish워커","최신상태복구"]
updated: "2026-06-11"
work_timestamp: "20260611_151500"
context: "달록본레포CC (D:\\dallog\\dallog_git) — 토글정렬·전역2px·스튜디오 라이브 커밋푸시 워커(PR#83) 작업보고"
source_of_truth: "https://dallog-tools.hansbridge.co.kr/knowledge/"
---

# 작업보고 — 토글 정렬 근본수정 + 전역 모서리 2px + 스튜디오 라이브 1클릭 커밋·푸시 워커 (PR#83)

> **이 문서가 무엇인가 (비개발자용 한 줄 설명)**
> 구독관리 화면의 켜고/끄는 토글(스위치)이 화면을 비뚤게 밀어내던 진짜 원인을 찾아 고치고, 사장님 지시대로 앱 전체의 둥근 모서리를 거의 각진 2px로 통일했으며, 마스터 전용 디자인 편집 도구(/studio)의 "한 번 눌러 바로 반영" 버튼이 사장님 PC의 개발 모드에서만 되던 것을 실제 서비스(dallog.kr)에서도 어디서든 작동하도록 작은 서버(워커, worker = 클라우드에서 돌아가는 작은 프로그램)를 새로 만들어 붙인 작업이다.

---

## 0. 요약

| 항목 | 내용 |
|---|---|
| 커밋 | `906889a` (2026-06-11 15:15:15 KST) |
| PR | #83 |
| 제목 | style+feat: 토글 정렬 근본수정·전역 모서리 2px·스튜디오 신토큰+라이브 1클릭 커밋푸시 워커 |
| 변경 규모 | 8파일, +322 / −136 |
| 성격 | 스타일(디자인시스템) + 기능(발행 파이프라인) 혼합 |
| Codex 회귀검수 | 반영 완료 (High 1·Medium 2·권고 1) |

이번 PR은 성격이 다른 세 갈래가 한 커밋에 묶였다. 세 갈래 모두 "이미 깨진 것을 근본부터 고치거나, 안 되던 것을 되게 만드는" 수정이라 서로 독립적이지만 같은 날 사장님 지시(전역 모서리)·라이브 검증 흐름에서 함께 처리됐다.

---

## 1. 갈래 A — 구독관리 토글 정렬 "근본 원인" 수정

### 무엇을
`src/index.css`에 체크박스·라디오 버튼 전용 예외 규칙을 추가했다.

```css
/* 체크박스·라디오는 텍스트 입력이 아니다 — 위 전역 width:100%·패딩이 먹으면 체크박스가 한 줄을
   통째로 차지하며 라벨을 밀어낸다(구독관리 토글 정렬 깨짐 원인 — 2026.06.11 근본 수정). */
input[type="checkbox"], input[type="radio"] {
  width: auto;
  padding: 0;
  flex: none;
}
```

### 왜 / 문제
구독관리 화면 등에서 토글(스위치형 체크박스)이 라벨 텍스트를 오른쪽으로 밀어내며 한 줄을 통째로 차지하는 정렬 깨짐이 있었다. 그동안은 개별 화면에서 그때그때 폭을 눌러주는 식의 대증요법(증상만 가리는 처치)으로 넘어갔을 가능성이 큰 문제다.

### 원인
달록 디자인시스템은 폼 입력칸을 보기 좋게 만들려고 `input`·`textarea`에 **전역으로** `width: 100%`와 패딩을 건다. 그런데 CSS의 `input` 셀렉터(선택자)는 텍스트 입력뿐 아니라 **체크박스·라디오까지 전부 포함**한다. 그 결과 본래 작은 사각형이어야 할 체크박스가 부모 폭 100%로 늘어나면서 옆의 라벨을 밀어내고 줄을 독차지했다. 즉 "토글 컴포넌트 버그"가 아니라 **전역 입력칸 규칙이 체크박스에까지 새어 들어간 것**이 근본 원인이다.

### 해결 / 판단근거
- 화면별로 토글 폭을 덮어쓰는 땜질 대신, `input[type="checkbox"]`·`input[type="radio"]`에만 `width:auto; padding:0; flex:none`을 돌려주는 **단일 전역 예외**로 처리했다.
- 이 한 곳을 고치면 현재 깨진 구독관리뿐 아니라 같은 패턴을 쓰는 모든 체크박스·라디오가 일괄 정상화된다. 단순함 우선·외과수술 원칙에 맞는 최소 변경이다.

### 결과
체크박스·라디오가 원래 크기를 회복하며 라벨과 같은 줄에 정렬된다. 텍스트 입력칸의 전역 `width:100%`는 그대로 유지된다(텍스트 입력에는 의도된 동작이므로 건드리지 않음).

---

## 2. 갈래 B — 전역 모서리 2px 통일 (사장님 지시)

### 무엇을
앱 전반의 둥근 모서리(border-radius)를 **2px 이하**로 통일했다. 디자인 토큰 3종과 곳곳에 하드코딩된 픽셀값·pill(둥근 알약 모양) 값을 일괄로 내렸다.

**(1) 모서리 토큰 3종 — `src/index.css`**

| 토큰 | 변경 전 | 변경 후 |
|---|---|---|
| `--radius` (카드 등 대) | `14px` | `2px` |
| `--radius-md` (모달·셀 등 중) | `10px` | `2px` |
| `--radius-sm` (입력칸·작은 버튼 등 소) | `6px` | `2px` |

**(2) 하드코딩·pill 일괄** — `index.css` 192줄, `admin.css` 44줄, `studio.css` 10줄, 대시보드 차트 2개에 걸쳐 `4px`/`6px`/`7px`/`8px`/`12px`/`14px`/`16px`/`20px`/`99px`/`999px` 등으로 박혀 있던 값을 전부 `2px`로 내렸다. 예시.
  - `.btn` `7px→2px`, `.badge`·`.pill`·`.adm-status`·`.adm-plan` 등 알약형 `99px`/`999px`/`20px → 2px`
  - 어드민 카드·KPI·모달·진행바·트렌드바, 히스토리 상세 타일·칩·폼·컨텍스트 메뉴 등 `var(--space-N)`/하드코딩 라운드 다수 `→ 2px`
  - 대시보드 차트 막대 모서리(`BodySection.tsx`·`RunningSection.tsx`)의 `borderRadius: 4 → 2`

**(3) 예외 (의도적으로 둥글게 유지)**
- **원형(50%)**: 토글 손잡이(`.coach-consent-knob` 등) 같은 동그란 노브는 원형 그대로 둔다.
- **토글 스위치 트랙(pill)**: 스위치 바깥 트랙(`.coach-consent-switch`)은 `border-radius: 999px`(알약형)를 **유지**한다. 트랙은 둥근 노브와 짝을 이루는 기능적 외관이라 각지게 만들면 토글로 안 보인다. 코드에 예외 사유 주석을 남겼다.

```css
.coach-consent-switch {
  width: 48px; height: 28px;
  border-radius: 999px; /* 토글 트랙=pill(기능성 외관 — 2px 정책 예외, 원형 knob 짝) */
  ...
}
```

### 왜
사장님이 전역 모서리를 거의 각지게(2px 이하) 통일하라고 지시했다. 달록의 룩앤필을 더 또렷하고 단단한 인상으로 맞추기 위한 디자인 방향 결정이다.

### 판단근거
- **토큰만 바꿔서는 부족**했다. 디자인시스템 토큰화가 아직 진행 중이라([[project_inline_to_css_migration]]) 모서리 값이 토큰을 안 거치고 하드코딩된 곳이 많기 때문이다. 토큰 3종만 내리면 어드민·pill·차트 등은 여전히 둥글게 남아 화면별로 불일치가 생긴다. 그래서 하드코딩·pill까지 함께 훑었다.
- 동시에 **/studio에 모서리 토큰 3종을 모두 편집 가능**하게 노출해(아래 갈래 C 참조), 앞으로 모서리 정책을 코드 수정 없이 스튜디오에서 조정할 수 있게 기본값을 동기화했다.

### 결과
카드·모달·버튼·배지·입력칸·어드민·차트 막대까지 모서리가 2px로 통일됐고, 토글 스위치와 원형 노브만 의도적으로 둥글게 남았다.

---

## 3. 갈래 C — 스튜디오 신토큰 + 라이브 1클릭 커밋·푸시 워커

`/studio`는 마스터 전용 UI 토큰 편집 툴이다([[project_inline_to_css_migration]]의 스튜디오, [[reference_studio_publish_worker]]).

### 3-1. 스튜디오 신토큰 추가 (`src/pages/Studio.tsx`)

신규 화면(코치 구독관리·어드민·동의 등)이 공통으로 쓰는 토큰을 편집 대상에 추가했다.

| 그룹 | 추가/변경 토큰 |
|---|---|
| 형태 | `--radius`(카드·대) 라벨 명확화, **`--radius-md`(중)·`--radius-sm`(소) 신규 노출** — 모서리 3종 전부 편집 가능, 기본값 2px 동기화 |
| 버튼 | `--btn-radius` 기본값 `6px → 2px` 동기화 |
| 테두리·상태(신규 그룹) | `--border`(기본 테두리)·`--border2`(입력칸 테두리)·`--amber`(경고 게이지 70%+)·`--danger`(위험·소진·삭제) |

그룹 안내 문구도 보강해, "형태"·"테두리·상태" 토큰이 코치 구독관리·어드민·동의 등 전 화면에 공통 반영된다는 점을 마스터가 알 수 있게 했다.

### 3-2. 1클릭 커밋·푸시 — dev 한정 → 라이브 워커 경유

#### 무엇을 / 문제
스튜디오 "직접 적용 & 커밋·푸시" 버튼은 그동안 **vite 개발 서버 전용 엔드포인트(`/__studio/apply`, vite 플러그인)** 만 호출했다. 그래서 라이브(dallog.kr)에서 누르면 "엔드포인트 연결 실패 — npm run dev 개발 서버에서만 동작합니다"만 떴다. 사장님이 자기 PC에서 `npm run dev`를 띄운 상태에서만 1클릭 발행이 됐다.

#### 해결 — `workers/studio-publish/` 신설 (127줄 워커 + wrangler.toml)
어디서든(라이브 포함) 동작하도록, GitHub Contents API로 직접 커밋하는 Cloudflare Worker를 새로 만들었다.

처리 흐름.
```
마스터가 /studio 에서 "직접 적용 & 커밋·푸시" 클릭
  → (라이브) studio-publish 워커 POST /publish (Supabase JWT 첨부)
     → ① 마스터 검증  ② CSS 검증  ③ GitHub에 src/studio-overrides.css 커밋(main)
  → CF Pages 자동 배포 → 1~2분 내 전 사용자 반영
```

프런트(`Studio.tsx`)는 환경에 따라 분기한다.
- **dev** (`import.meta.env.DEV`): 기존 vite 플러그인 `/__studio/apply` 그대로(로컬 git 직접 커밋) — 기존 동작 유지.
- **라이브**: Supabase 세션 토큰을 얻어 `VITE_STUDIO_PUBLISH_URL`(기본 `https://dallog-studio-publish.ccy4848.workers.dev`)의 `/publish`로 `Authorization: Bearer` 헤더와 함께 CSS·커밋 메시지를 전송. 성공 시 단축 커밋 SHA를 안내.

#### 워커의 안전장치 (판단근거)
이 워커는 GitHub에 직접 커밋하는 권한을 갖기 때문에 오남용 방지가 핵심이다.

1. **마스터 검증** — `Authorization`의 Supabase JWT를 `/auth/v1/user`로 검증하고, 이메일이 `OWNER_EMAILS` allowlist에 있어야만 통과(`ccy8215@gmail.com` 등). 그 외엔 403 "마스터 권한이 필요해요".
2. **대상 파일 고정** — 커밋 경로를 `src/studio-overrides.css` **한 곳으로 못박았다**(`TARGET_PATH`). 임의 경로·임의 코드 커밋이 구조적으로 불가능하다.
3. **크기 상한** — CSS 64KB 초과 시 413 거절.
4. **시크릿 분리** — `GITHUB_TOKEN`은 wrangler secret(코드·파일 비노출). fine-grained 토큰(dallog 레포 Contents RW 한정·Revoke 가능)을 쓴다([[reference_studio_publish_worker]]).
5. **불필요 커밋 방지** — 기존 파일과 본문이 같으면(자동 생성 헤더의 날짜만 다른 경우 포함) `committed:false`로 커밋을 건너뛴다.
6. **UTF-8 안전 base64** — GitHub Contents API 형식에 맞춰 한글 깨짐 없이 인코딩/디코딩.

#### 검증
실제 커밋이 워커 경유로 생성되는 것을 확인했다(실커밋 검증됨).

---

## 4. 변경 파일 정리 (8파일, +322 / −136)

| 파일 | 줄수 | 핵심 변경 |
|---|---|---|
| `src/index.css` | 192 | 모서리 토큰 3종 2px화 + 하드코딩·pill 일괄 2px + 체크박스/라디오 예외 추가 + 스위치 트랙 pill 예외 주석 |
| `src/pages/Studio.tsx` | 61 | 모서리 3종·테두리·상태 토큰 추가, 기본값 동기화, applyAndCommit 라이브 분기, DEV 게이트 제거 |
| `src/pages/studio.css` | 10 | studio·uix 배지·하이라이트·스와치 라운드 2px화 |
| `src/pages/admin.css` | 44 | 어드민 KPI·카드·모달·진행바·트렌드바·칩·티켓·상태배지 라운드 2px화 |
| `src/components/dashboard/BodySection.tsx` | 2 | 차트 막대 `borderRadius 4 → 2` |
| `src/components/dashboard/RunningSection.tsx` | 4 | 차트 막대 `borderRadius 4 → 2` (3곳) |
| `workers/studio-publish/index.js` | 127 (신규) | 마스터 검증·경로 고정·64KB 한도·409 재시도 커밋 워커 |
| `workers/studio-publish/wrangler.toml` | 18 (신규) | 워커 설정(vars: SUPABASE_URL·GITHUB_REPO·GITHUB_BRANCH·OWNER_EMAILS·SUPABASE_ANON_KEY 공개키) |

---

## 5. Codex 검토 반영 결과

회귀 위주로 Codex 검수를 받았고, 다음을 반영했다.

| 심각도 | 지적 | 반영 |
|---|---|---|
| **High** | 라이브에서 "직접 적용 & 커밋·푸시" 버튼이 **미렌더**된다 — 기존 `{import.meta.env.DEV && (<button .../>)}` 게이트 때문에 워커를 만들어도 라이브에선 버튼 자체가 안 보임 | `Studio.tsx`의 DEV 게이트 제거. 버튼을 항상 렌더하고 `applyAndCommit` 안에서 dev/라이브를 분기 → [즉시반영] |
| **Medium** | 스위치 **트랙이 2px화**되면 토글로 안 보임 | `.coach-consent-switch` 트랙을 `border-radius:999px`(pill)로 되돌리고 "2px 정책 예외·원형 knob 짝" 주석 명시 → [즉시반영] |
| **Medium** | 동시 발행 시 GitHub **409 충돌**(sha 불일치) 가능 | 워커에서 PUT이 409면 sha 재조회 후 1회 자동 재시도 → [즉시반영] |
| **권고** | **CORS 403** — 미허용 Origin은 명시 거절해야 안전 | `ALLOWED_ORIGINS`(dallog.kr·www·localhost)만 허용, 그 외 Origin 403. 서버 간 호출(Origin 없음)은 허용 → [검토후반영] |

---

## 6. 미해결 / 후속

- **`studio-overrides.css` 발행 검증의 상시 모니터링**은 아직 수동이다. 라이브 1클릭 발행이 실패하는 케이스(토큰 만료·GitHub rate limit 등)에 대한 알림은 없다 — 향후 필요 시 추가.
- 모서리 **2px 일괄 적용이 토큰을 안 거친 하드코딩까지 훑었지만**, 인라인 스타일 마이그레이션이 진행 중이라([[project_inline_to_css_migration]]) 아직 발견 못 한 둥근 모서리 잔여가 있을 수 있다. 신규 화면 추가 시 2px 정책 준수 확인 필요.
- 워커 배포는 `cd workers/studio-publish && wrangler deploy`로 수행한다. 시크릿(`GITHUB_TOKEN`)·vars는 wrangler에 설정돼 있어야 동작한다([[reference_studio_publish_worker]]).

---

## 작업 리드타임

- 시작: 2026-06-11 (PR#83 작업 착수)
- 완료: 2026-06-11 15:15 (KST) — 커밋 `906889a`
- 기준: 커밋 타임스탬프 기준 단일 작업일 내 완료

---
