Study Builder는 로컬 학습서와 실제 코드 Workspace를 한 화면에서 연결하는 Electron 기반 학습 애플리케이션입니다. 사용자는 배포된 학습서를 읽고, 빈 폴더에 실행 가능한 Spring Boot 실습 템플릿을 생성해 제한된 Gradle 검증을 직접 실행할 수 있습니다.
AI는 선택 기능입니다. AI를 사용하지 않아도 위키, 파일 편집, 실습 환경 생성, 환경 진단과 터미널 실행이 작동합니다. AI를 사용할 때는 OpenAI, Gemini, OpenAI-compatible 서버 또는 이미 로그인된 Codex CLI 중 하나를 사용자가 직접 설정합니다.
현재 MVP의 원칙은 로컬 우선, 사용자 승인, 기존 파일 비파괴, **BYOP(Bring Your Own Provider)**입니다. 클라우드 계정, 동기화, 협업, 결제와 자동 업데이트는 포함하지 않습니다.
- 홈, 위키 문서, 실습 화면을 누적하는 커스텀 Electron 상단 탭 Bar
- Notion 기반 16개 읽기 전용 Spring Boot 문서와 15개 경제학 문서의 계층 목차·본문 검색
- 위키형·실습형 학습서 분리, 브라우저식 화면 탭과 앱 재시작 후 학습 위치 복원
- 학습 위치, 열린 화면, 패널 크기, 최근 실행 결과와 마지막 Workspace의 로컬 저장·복원
- 사용자가 선택한 Workspace의 파일 트리, 생성, 읽기, 수정, revision 충돌 감지, 이름 변경과 휴지통 이동
- 빈 폴더에 Spring Boot REST API 실습 템플릿을 안전하게 생성
- Java Runtime,
javac, Python 3, Git, Homebrew, Codex CLI와 Gradle 실습 프로젝트 진단 - Java 21과 Study Builder 템플릿이 준비됐을 때만 Gradle 테스트 실행
- OpenAI, Gemini, OpenAI-compatible, Codex CLI Auth Provider 설정
- Provider가 제공하는 모델 목록 조회와 OpenAI 계열 추론 강도 설정
- API Key 암호화 저장 또는 명시적인 세션 전용 사용
- 승인 전 AI Context 미리보기, 스트리밍 취소, 수정안 검토·적용과 위키 노트 저장
- 브라우저 fallback에서 privileged 데스크톱 기능을 가짜 성공으로 표시하지 않고 Electron 실행 필요 상태를 표시
Renderer (React)
│ window.studyBuilder: 제한된 도메인 API
▼
Preload (contextBridge)
│ 고정 IPC 채널, payload/event 검증, listener 소유권 관리
▼
Electron Main
├─ Local Repository ─ 위키·화면 상태 JSON 원자적 저장과 복구
├─ Workspace Filesystem ─ 승인된 root 내부 파일 CRUD·watch
├─ Workspace Template ─ 검증된 Spring Boot ZIP의 비파괴 압축 해제
├─ Environment Service ─ JDK·Python·Gradle·Codex 실행 파일 진단
├─ PTY Terminal ─ 일회용 승인 토큰·node-pty·프로세스 정리
├─ Provider Adapter ─ OpenAI·Gemini·Custom SSE·Codex JSONL
└─ Assistant Context Builder ─ 사용자가 승인한 최소 문맥만 구성
창 생성, 커스텀 Title Bar, 보안 WebPreferences, navigation·popup·download 차단, CSP, IPC 등록, 서비스 수명주기와 종료 정리를 담당합니다. 창이 닫힐 때 watcher, AI stream, Codex login process, 승인 토큰과 PTY를 정리합니다.
contextBridge로 window.studyBuilder만 노출합니다. Renderer에는 Node.js, Electron 객체와 raw ipcRenderer가 노출되지 않습니다. 각 메서드는 고정 IPC 채널에 연결되며 요청과 이벤트 payload를 다시 검증합니다.
React UI가 Home, Wiki, Learning Mode, 커스텀 상단 탭, Provider 설정과 환경 진단 Dialog를 구성합니다. Monaco Editor와 xterm UI는 Renderer에 있지만 실제 파일·프로세스 권한은 Main의 검증된 IPC만 사용합니다.
위키 문서, 학습 위치, 열린 화면, 패널 배치, Workspace 메타데이터와 최근 실행 요약을 JSON으로 원자적 저장합니다. 저장 전 정상 파일을 백업하고, 손상된 primary 파일은 이름을 바꾸어 보존한 뒤 backup 또는 seed 데이터로 복구합니다.
사용자가 폴더 선택기에서 승인한 하나의 canonical root만 접근합니다. .., 절대 경로, root 이탈, 심볼릭 링크, 무시 디렉터리, 비밀 파일, 바이너리와 과대 파일을 차단합니다. 파일 저장과 이름 변경은 revision 기반 충돌 검사를 거치며 삭제는 OS 휴지통을 사용합니다.
resources/templates/spring-boot-rest.zip을 선택한 빈 폴더에만 생성합니다. .DS_Store 이외의 기존 항목이 있으면 중단하며 기존 파일을 덮어쓰지 않습니다. ZIP entry의 절대 경로, 경로 탈출, 심볼릭 링크, 중복 이름, 암호화, 지원하지 않는 압축 방식, CRC32 불일치와 크기 제한을 검증합니다. 실패하면 이번 작업으로 생성한 파일만 롤백합니다.
템플릿은 완성 예제가 아니라 Spring Initializr 수준의 시작 프로젝트입니다.
- Java 21 Toolchain
- Spring Boot, Spring Web, Spring Data JPA, Validation, H2
- Gradle Wrapper, Application 시작 클래스와 Context Test
- Chapter별 관련 파일 버튼이 필요한 패키지 경로와 빈 구현 파일 생성
- 학습 가이드
docs/LEARNING.md - Gradle Wrapper 배포 ZIP SHA-256 검증
완성된 Studymate 예제는 빌드 입력과 분리된 prototype/resources/reference-sources/studymate-complete/에 보존하며 사용자 Workspace에는 복사하지 않습니다. 강의 자료 제작 방법은 course-authoring.md를 참고합니다.
Java Runtime과 javac 21 이상, Python 3, Git, Homebrew, Codex CLI, 템플릿 marker와 gradlew 실행 권한을 실제 executable 경로 기준으로 검사합니다. JDK나 Python을 사용자 모르게 설치하지 않습니다. 설치가 필요하면 설명과 검토 가능한 명령을 보여주고 사용자가 직접 결정하도록 합니다.
Python은 Gradle ZIP 압축 해제의 보조 수단이며 unzip이 있으면 필수가 아닙니다. Spring Boot 빌드와 테스트에는 Java 21 JDK가 필수입니다.
현재 18개 실습별로 등록된 Gradle 검증 명령만 실행할 수 있습니다. UI의 표시 문자열, executable과 인자 배열이 allowlist와 일치할 때만 Main이 60초 유효한 일회용 승인 토큰을 발급합니다. 실행 직전 Workspace와 gradlew를 다시 검사하며, 취소와 앱 종료 시 자식 프로세스까지 정리합니다.
- OpenAI: 앱이 공식 Base URL을 관리하고 사용자는 API Key와 model을 입력합니다.
- Gemini: Gemini 전용
streamGenerateContentSSE 요청과 응답을 별도 Adapter가 처리합니다. - OpenAI-compatible: 사용자가 HTTPS Base URL 또는 loopback HTTP URL, API Key와 model을 지정합니다.
- Codex CLI Auth: 설치된
codex의 로그인 상태를 재사용하고codex exec --json --ephemeral --sandbox read-only를 격리된 임시 디렉터리에서 실행합니다.
내부 Provider type은 openai, gemini, openai-compatible, codex를 사용합니다. Codex 인증 파일이나 access token은 Study Builder가 읽거나 복사해 저장하지 않습니다.
API 기반 Provider는 지원하는 경우 /models에서 모델 목록을 가져옵니다. OpenAI와 OpenAI-compatible Provider에는 기본값, low, medium, high 추론 강도를 저장할 수 있으며, 기본값이 아닌 경우에만 요청에 reasoning_effort를 포함합니다.
Monaco에 Java·Spring snippet, 기본 hover, package 생성 quick action과 Java 21 편집 설정을 제공합니다. 생성된 Workspace의 .vscode/extensions.json에는 Red Hat Java, Java Debug/Test, Gradle과 Spring 도구 권장을 포함합니다. 앱 내부에는 아직 classpath를 읽는 Eclipse JDT Language Server가 없으므로 프로젝트 전체 진단·자동 import·정확한 symbol 탐색은 VS Code 확장으로 보완해야 합니다. 향후 번들 도입 시에는 공식 milestone 배포본의 버전·checksum·패키지 크기를 고정해 검증해야 합니다.
AI 요청 전 사용자가 Context manifest를 확인하고 승인해야 합니다. 승인된 질문, 현재 학습 페이지·단계, 사용자가 선택한 한 개의 텍스트 파일과 revision, 제한된 터미널 요약만 포함합니다. Workspace 전체, 다른 파일, Provider key, 앱 내부 저장소와 환경 변수는 포함하지 않습니다. 승인 후 revision 또는 snapshot이 바뀌면 요청을 중단합니다.
- macOS
- Node.js
22.23.1(prototype/.nvmrc,>=22.23.1 <23) - npm
- Git
- Xcode Command Line Tools
- Python 3,
make, C/C++ toolchain:node-ptynative build용 - Spring Boot 실습 실행 시 Java 21 JDK
- 최초 Gradle·Spring dependency 다운로드를 위한 네트워크
- Codex Provider 사용 시 별도로 설치되고 로그인된 Codex CLI
현재 배포 검증 대상은 macOS unsigned current-architecture build입니다. Windows와 Linux 패키지는 지원 대상으로 인증하지 않습니다.
cd prototype
npm cipostinstall에서 Electron ABI에 맞춰 native dependency를 준비합니다. 다른 운영체제나 architecture에서 생성된 node_modules를 복사해 사용하지 마십시오.
cd prototype
npm run dev:desktopVite 개발 서버, Electron Main·Preload build와 실제 Electron 창을 실행합니다.
cd prototype
npm run dev브라우저 fallback은 레이아웃과 읽기 흐름 검토용입니다. 실제 Workspace, 템플릿 생성, native PTY, Provider key 저장과 Electron IPC는 사용할 수 없으며 가짜 파일이나 가짜 실행 성공을 만들지 않습니다.
현재 상용 UI의 배포 학습서는 읽기 전용입니다. 앱 안에서 새 문서를 만들거나 Markdown을 가져오고 원문을 수정하지 않습니다. 콘텐츠 저자는 prototype/resources/course-sources/ 아래 Markdown과 manifest를 수정한 뒤 npm run build:course로 Renderer 콘텐츠와 Electron seed를 함께 생성합니다.
실습 계약은 practice-manifest.json, 시작 프로젝트는 prototype/resources/template-sources/spring-boot-rest/에서 관리합니다. 자세한 스키마와 생성물 경계는 강의 자료 제작 방법을 참고하십시오.
- Electron 앱에서 학습 화면을 엽니다.
- 실습 환경 또는 실습 폴더 선택을 누릅니다.
- 새 빈 폴더를 선택합니다.
- 환경 점검에서 Java Runtime과
javac가 모두 21 이상인지 확인합니다. - Spring Boot 환경 만들기를 누르고 비파괴 생성 확인에 동의합니다.
- 생성이 끝나면
StudymateApplication.java또는docs/LEARNING.md를 엽니다. - 챕터의 바로 실습하기 버튼으로 빈 구현 파일과 상위 폴더를 만든 뒤 직접 코드를 작성·저장하고, 승인 Dialog에서 해당 Gradle 검증을 실행합니다.
첫 실행에서 Gradle 8.14.4와 Maven Central 의존성을 다운로드할 수 있습니다. Gradle 배포 ZIP은 템플릿에 기록된 SHA-256과 일치할 때만 사용합니다.
cd prototype
npm run build:templates
npm run build:course
npm run typecheck
npm run test
npm run test:sites
npm run test:e2e
npm run build
npm run build:desktopbuild:templates: Spring Boot source tree에서 결정적인 template ZIP 생성build:course: 원문·문서 구조·18개 실습 manifest에서 앱 콘텐츠와 명령 allowlist 생성typecheck: Renderer TypeScript 검사test: Unit·Integration Vitesttest:sites: Sites worker 계약 검사test:e2e: retry 0인 실제 Electron Playwright 검사build: production Renderer와 Sites fallback buildbuild:desktop: Renderer build 후 Main·Preload TypeScript build
별도 lint script는 없습니다. TypeScript, 테스트, git diff --check와 보안 검색을 사용합니다.
cd prototype
npm run package:dir
npm run package:mac
npm run inspect:package
npm run test:packagedpackage:dir: unsigned.app생성package:mac: DMG와 ZIP 생성inspect:package: ASAR 필수 파일, template ZIP, 금지 파일, credential pattern과node-ptyABI 검사test:packaged: 임시 userData와 Workspace로 설치본을 직접 실행하고 재시작 복원 검사
패키징 산출물은 Git에 커밋하지 않습니다. 현재 앱은 서명되지 않았고 공증되지 않았습니다.
Electron userData 아래 다음 suffix를 사용합니다.
study-builder/app-data.json
study-builder/app-data.json.bak
study-builder/app-data.json.corrupt-<timestamp>-<id>
study-builder/recent-workspace.json
study-builder/providers/provider-profiles.json
study-builder/providers/provider-<id>.key
app-data.json: 위키, 내비게이션, UI 배치와 최근 실행 요약.bak: 마지막 정상 저장본.corrupt-*: schema 또는 JSON 검증에 실패한 원본 보존본provider-profiles.json: 이름, Provider type, endpoint, model과 기본 Provider 등 비밀이 아닌 metadataprovider-<id>.key: macOSsafeStorage로 암호화된 API Keyrecent-workspace.json: Main Process만 읽는 최근 승인 Workspace 절대 경로. Renderer에는 opaque ID와 폴더 이름만 전달
Codex Provider는 key 파일을 만들지 않습니다. Codex CLI 자체의 공식 로그인 상태만 확인합니다.
| 구분 | 위치 | 내용 | 앱의 권한 |
|---|---|---|---|
| 앱 내부 데이터 | Electron userData의 study-builder/ |
위키, 화면 상태, Provider metadata와 암호화 key | 앱이 원자적으로 저장·복구 |
| Workspace | 사용자가 선택한 외부 폴더 | 실제 Spring Boot 프로젝트와 사용자 코드 | 승인된 root 내부의 허용 파일만 |
Workspace를 선택해도 폴더 전체를 앱 내부 저장소로 복사하지 않습니다. 템플릿은 사용자가 확인한 빈 폴더에만 생성합니다.
API Key 원문은 Provider metadata, Renderer용 metadata, AI Context와 로그에 저장하지 않습니다.
- 영구 저장: macOS
safeStorage를 사용할 수 있을 때만 암호화 파일로 저장합니다. - 세션 전용: 사용자가 명시적으로 확인하면 Main 메모리에만 보관하고 앱 종료 시 제거합니다.
safeStorage를 사용할 수 없을 때 평문 영구 저장으로 자동 전환하지 않습니다.- Renderer와 IPC에는
hasKey와 마스킹 문자열만 반환합니다. - Codex Auth는 Study Builder key 저장소를 사용하지 않습니다.
실제 API Key를 Git fixture, 테스트 환경 변수, 스크린샷과 패키지에 넣지 마십시오.
- 앱에서 AI 제공자 설정을 엽니다.
- 유형을 OpenAI, Gemini, OpenAI-compatible 또는 Codex CLI Auth로 선택합니다.
- OpenAI·Gemini는 API Key와 model을 입력하고, 연결 가능한 경우 모델 목록을 새로고침합니다.
- OpenAI-compatible은 Base URL, API Key와 model을 입력하고 필요한 경우 추론 강도를 선택합니다.
- Codex는 상태 새로고침으로 설치와 로그인 여부를 확인하고, 필요할 때 명시적으로 로그인 흐름을 시작합니다.
- 연결 검사를 실행하고 사용할 Provider를 기본값으로 지정합니다.
| 유형 | 인증 | Endpoint 관리 | Streaming |
|---|---|---|---|
| OpenAI | Bearer API Key | 앱 고정 Base URL | Chat Completions SSE |
| Gemini | x-goog-api-key |
앱 고정 Gemini API | streamGenerateContent SSE |
| OpenAI-compatible | Bearer API Key | 사용자 HTTPS 또는 loopback HTTP | Chat Completions SSE |
| Codex CLI Auth | 설치된 CLI 로그인 | Codex CLI가 관리 | codex exec --json JSONL |
Anthropic 전용 Messages API, 이미지 입력, tool calling, Provider 자동 탐색과 OAuth token 직접 보관은 현재 범위 밖입니다.
포함
- 사용자가 입력한 질문
- 현재 학습 페이지와 단계
- 사용자가 선택한 한 개의 허용된 텍스트 파일과 revision
- 제한된 최근 터미널 요약
- 전송 전에 표시되는 파일 경로·크기·revision manifest
제외
- Workspace 전체 또는 임의의 다른 파일
.git,node_modules, build 산출물과 비밀 파일- Provider API Key와 Codex credential
- 환경 변수, 앱 내부 JSON과 다른 학습서
- 승인 후 변경된 파일 snapshot
AI 응답은 명령을 직접 실행할 수 없습니다. 수정안도 사용자가 검토·적용·저장해야 Workspace에 반영됩니다.
- 표시 문자열, 실행 파일과 인자 배열이 allowlist와 정확히 일치해야 합니다.
- 현재 allowlist는 18개 실습 manifest에 등록된
./gradlew test --tests '<검증 클래스>'또는 Gradle task의 정확한 tuple입니다. - 승인 토큰은 WebContents owner와 현재 Workspace에 묶인 60초 유효 일회용 값입니다.
- 실행 직전에
gradlew가 일반 파일이며 심볼릭 링크가 아닌지 재검사합니다. - shell 문자열 실행과 AI가 만든 임의 명령은 허용하지 않습니다.
- 창 종료, navigation과 취소 시 PTY와 listener를 정리합니다.
contextIsolation: true,sandbox: true,nodeIntegration: false- 고정 preload bridge와 고정 IPC capability만 사용
- sender origin, owner WebContents, payload schema와 크기 검증
- 외부 navigation, popup과 download 차단
- 개발 CSP는 Vite React Refresh preamble의 정확한 hash만 허용
- 패키징 CSP는
script-src 'self'유지 - Workspace canonical path·symlink·secret·binary·size 정책 적용
- template ZIP entry와 CRC32·SHA-256 검증
- 파일 저장, rename과 외부 변경에 revision 충돌 검사
- Provider endpoint는 HTTPS 또는 loopback HTTP만 허용
- Codex 실행은 read-only sandbox, ephemeral session과 격리된 빈 cwd 사용
- 테스트 주입은 Main의
NODE_ENV=test분기에서만 활성화되고 Renderer API로 노출되지 않음
현재 .app, DMG와 ZIP은 개발·검증용이며 서명되지 않았고 공증되지 않았습니다. macOS가 최초 실행을 차단할 수 있습니다. 출처와 checksum을 확인한 로컬 산출물만 Finder의 열기 동작 또는 시스템 설정의 보안 안내를 통해 실행하십시오. Developer ID 서명, hardened runtime, notarization은 MVP 이후 작업입니다.
개인정보와 외부 전송 범위는 개인정보 처리 기준, 버전·패키징·서명 전환 절차는 릴리스 운영 가이드를 참고하십시오.
다른 Vite 프로세스를 종료한 뒤 npm run dev:desktop을 다시 실행합니다. 기본 포트를 임의로 바꾸면 Electron 개발 URL 계약과 E2E가 달라질 수 있습니다.
터미널의 Vite와 Electron 오류를 확인하고 npm run build:desktop을 실행합니다. 개발 HTML의 React Refresh preamble과 CSP hash를 함께 유지해야 하며 script-src 'unsafe-inline'을 추가해 우회하지 않습니다.
Node.js 22.23.1, Xcode Command Line Tools와 Python 3를 확인한 뒤 현재 macOS architecture에서 다시 설치합니다.
cd prototype
npm ci
npm rebuild node-pty폴더 선택 여부, 승인된 root 내부 경로, 심볼릭 링크, .git·node_modules·dist와 비밀 파일 정책을 확인합니다. 외부 변경 충돌이 발생하면 편집 내용은 유지되므로 reload 또는 충돌 해결 흐름을 사용합니다.
선택한 폴더가 비어 있는지 확인합니다. 기존 프로젝트는 덮어쓰지 않으므로 .DS_Store 이외의 파일이 있으면 생성이 중단됩니다. Java와 javac가 모두 21 이상인지, gradlew 실행 권한이 있는지 환경 점검에서 확인합니다. 첫 Gradle 실행에는 네트워크가 필요합니다.
OpenAI·Gemini API Key, model과 기본 Provider를 확인합니다. OpenAI-compatible Base URL은 HTTPS를 사용하고 로컬 서버만 loopback HTTP를 사용할 수 있습니다. query, fragment와 URL 내 credential은 허용하지 않습니다. 인증, rate limit, server, timeout, network와 protocol 오류를 구분해 표시합니다.
환경 점검에서 Codex CLI 경로와 버전을 확인하고 Provider 설정의 상태 새로고침을 실행합니다. 로그인되지 않았다면 명시적으로 Codex 로그인을 시작하고 완료 후 다시 확인합니다. Study Builder는 Codex 인증 파일을 읽거나 대신 수정하지 않습니다.
Unit, Integration, Electron E2E와 패키지 Smoke Test는 로컬 fake Provider와 임시 userData·Workspace를 사용하므로 실제 API Key가 필요하지 않습니다.
- unsigned, not-notarized macOS current-architecture package만 대상
- Windows·Linux package 인증 없음
- Spring Boot 템플릿은 Java 21과 최초 Gradle·Maven dependency 다운로드 필요
- 터미널은 18개 실습 manifest의 Gradle allowlist 외 명령 실행 불가
- 시작 템플릿에는 Context Test만 포함되어 있어 manifest의 후반 실습 검증 클래스는 강의 자료와 함께 추가 제공해야 함
- Git GUI, classpath 기반 language server, debugger와 plugin marketplace 없음
- 로그인, cloud sync, collaboration, telemetry와 auto-update 없음
- 브라우저 fallback은 privileged desktop 기능을 제공하지 않음
- AI 수정은 한 파일의 replacement 제안이며 자동 실행되지 않음
study-builder/
├─ README.md
├─ design.md
├─ docs/
│ └─ development-plan.md
└─ prototype/
├─ electron/
│ ├─ main.mts
│ ├─ preload.cts
│ ├─ ipc/
│ ├─ storage/
│ ├─ workspace/
│ ├─ environment/
│ ├─ terminal/
│ ├─ provider/
│ └─ assistant/
├─ resources/
│ ├─ template-sources/spring-boot-rest/
│ └─ templates/spring-boot-rest.zip
├─ src/
├─ tests/
│ ├─ unit/
│ ├─ integration/
│ ├─ e2e/
│ └─ docs/
├─ worker/
├─ scripts/
├─ electron-builder.yml
├─ package.json
└─ .nvmrc