Skip to content

[ARCHIVED 2026-08-19] 역사 자료 — 현행 규범이 아니다. 아카이브 사유와 대체 문서는 docs/README.md의 Archive 섹션을 참조.

소프트웨어 아키텍처

한국어 번역본

이 문서는 원문(영어)의 한국어 번역이다. 정본은 원문이며, 계약·게이트 판단이 갈리면 원문을 따른다. 원문: docs/archive/software-architecture-patterns.md

갱신: 2026-07-27

Barbelic은 이제 React 앱을 유일한 프런트엔드 소스로 사용한다.

이전의 바닐라(vanilla) 프런트엔드 계층은 제거되었다. src/app, src/core, src/features, src/mobile, src/desktop, src/dom, 최상위 css, 최상위 app.js를 구현 참조로 사용하지 않는다.

현재 런타임

txt
index.html
  -> src/react/vite/main.tsx
  -> src/react/app.tsx
  -> src/react/appController.tsx
  -> src/react/mobileApp.tsx / src/react/desktopApp.tsx
  -> src/react/services/*
  -> src/react/ui/mobile/* / src/react/ui/desktop/*

정적 웹 앱 래퍼는 그대로 남아 있다:

  • public/manifest.webmanifest
  • Vite dev/build 설정
  • api/auth/test-admin/session

오프라인 서비스 워커 지원은 현재 제거되어 있으며, 오프라인 지원 복원은 별도 작업이다. 앱 셸은 React다.

소유권 모델

Claude Design이 UI 표면을 소유한다:

  • 화면 구성(composition)
  • 플로우 연출(choreography)
  • 프레젠테이션 컴포넌트
  • CSS
  • 로컬 UI 상태
  • 독립 실행형 디자인 프리뷰용 fixture

Codex가 기능 브리지를 소유한다:

  • Supabase 인증·데이터 접근
  • 카카오, 구글, 애플 프로바이더 모듈과 공용 PKCE 콜백 배선
  • 데이터 정규화와 영속화
  • 앱 통합 콜백
  • 계약 테스트
  • 배포와 검증

의도된 분리는 컨테이너/프레젠테이셔널 React 구조다:

txt
src/react/
  app.tsx                  composition and current integration root
  services/                data/auth/Supabase bridge
  contracts/               living integration contracts
  ui/                      future Claude-owned presentational screens

디자인 계약

src/react/contracts/designContract.ts는 의미론적 data-lg-* 마커의 살아 있는 정본(source of truth)이다.

규칙:

  • Claude는 레이아웃, 클래스, 태그, 래퍼, 시각적 위계를 자유롭게 바꿀 수 있다.
  • Codex는 CSS 클래스를 숨은 기능 계약으로 사용해서는 안 된다.
  • DOM 수준의 통합 마커가 필요하면 data-lg-*를 통한다.
  • Claude가 마커를 추가하면 Codex가 designContract.ts에 등록한다.
  • React 소스가 미등록 마커를 사용하거나, 등록된 마커가 src/react에 더 이상 존재하지 않으면 테스트가 실패한다.

이 계약은 통합 표면을 보호한다. 디자인 시스템이 아니다.

데이터 경계

src/react/services/barbelicApi.ts는 앱 셸이 소비하는 타입 있는 데이터 파사드(facade)다. 구현은 목적이 좁은 도메인 서비스 모듈들에 위임한다:

  • src/react/services/supabaseAuth.ts: Supabase 클라이언트 생성, 프로바이더 중립 PKCE 완료 처리, 로그인 리다이렉트, 로그아웃
  • src/react/services/auth/providers/*: 카카오, 구글, 애플의 독립적인 메타데이터/에러 모듈
  • src/react/services/auth/socialAuthFlow.ts: 웹/iOS 공용 OAuth 시작과 code-only 콜백 파싱
  • src/react/services/domains/authProfileDomain.ts: 인증 상태, 현재 프로필, 온보딩 프로필 데이터
  • src/react/services/domains/workoutDomain.ts: 운동, 세션, 계획, 일일 컨디션 변경(mutation)
  • src/react/services/domains/catalogDomain.ts: 종목 카탈로그, 아키타입(archetype), 상세, 별칭(alias), 외부 매핑
  • src/react/services/domains/importDomain.ts: Wodup JSONL 업로드, 인입 시작, 인입 폴링
  • src/react/services/domains/statsDomain.ts: 화면 RPC 패키지와 구체화된(materialized) 통계 read model
  • src/react/services/domains/adminDomain.ts: 관리자/디버그/내보내기 작업
  • src/react/services/barbelicRepository.ts: 현행 단일 Supabase 계약을 위한 엄격한 어댑터
  • src/react/services/barbelicMappers.ts: 현행 RPC 행 → 뷰 모델 매핑과 현행 쓰기 DTO 구성
  • src/react/services/barbelicShared.ts: 공용 상수, 날짜 헬퍼, 표시 정규화

UI 파일은 Supabase나 리포지토리 모듈을 직접 임포트하는 대신, 여전히 props/콜백으로 데이터를 받아야 한다.

세션 위계

앱은 운동 데이터를 다음과 같이 저장하고 렌더링한다:

txt
day
  sessions[]
    exercises[]
      sets[]

완료된 기록은 sessions > session_exercises > exercise_sets에서 온다.

계획되었거나 놓친 기록은 planned_sessions > planned_sets에서 온다.

삭제나 편집에서 어느 테이블이 그 행을 소유하는지 알아야 할 때, UI는 source: "sessions" | "planned_sessions"를 유지해야 한다.

사용 중인 패턴

  • 컨테이너 / 프레젠테이셔널 컴포넌트(Container / Presentational Components): src/react/ui/**에 대해 계획된 방향.
  • 도메인 서비스 / 리포지토리 어댑터(Domain Service / Repository Adapter): 앱 코드는 barbelicApi.ts를 호출하고, 이는 도메인 서비스에 위임하며, Supabase 읽기/쓰기는 엄격한 리포지토리 어댑터 뒤에 머문다.
  • 계약 모듈(Contract Module): designContract.tsdata-lg-* 마커를 실행 가능하고 테스트 가능한 상태로 유지한다.
  • fixture 주도 디자인(Fixture-Driven Design): Claude는 src/react/ui/fixtures/** 아래에 프리뷰 데이터를 둘 수 있다.
  • 점진적 추출(Progressive Extraction): 기존 screens-*.jsx 파일은 화면 단위로 하나씩 추출할 수 있다.

새 화면 추가하기

  1. 가능하면 Claude가 src/react/ui/screens/** 아래에 프레젠테이셔널 화면을 만들거나 갱신한다.
  2. Claude는 독립 실행형 프리뷰를 위해 src/react/ui/fixtures/** 아래의 fixture를 사용한다.
  3. Claude는 새로 필요한 data-lg-* 마커를 PR 노트에서 요청한다.
  4. Codex가 src/react/contracts/designContract.ts에 마커를 등록한다.
  5. Codex가 src/react/app.tsx 또는 목적이 좁은 컨트롤러에서 실제 데이터와 콜백을 배선한다.
  6. Codex가 테스트를 갱신하고 Supabase 플로우를 검증한다.

Claude 핸드오프 규칙

Claude에게 작업을 넘길 때, Codex는 다음을 기술해야 한다:

  • 화면의 목적
  • 상태들
  • 데이터 형태
  • 필요한 콜백
  • 스트레스 케이스
  • 필요하다면 요구되는 의미론적 마커

사용자가 그 세부를 명시적으로 결정하지 않은 한, Codex는 간격, 팔레트, 카드 형태, DOM 중첩, 클래스 이름을 지정해서는 안 된다.