desmos 그래프 도구의 클론을 만들어 보았습니다
뭔가 험난할 것 같았는데 거의 한번에 원하는 뷰가 만들어졌네요.

사인코사인과 다항함수만 지원되는 상태인데, 뷰는 거의 완벽하다는 게 놀랍습니다.
사용한 프롬프트 (spec.md) 는 다음과 같습니다.
Desmos와 유사한 '다중 수식 그래프 계산기'를 만들기 위한 **Technical Specification(기술 명세서)** 입니다.
이 문서는 **Mathlive**(수식 입력)와 그래프 렌더링 라이브러리를 결합하여 웹 애플리케이션을 구축하는 구조를 정의합니다.
---
# Technical Specification: Math Graphing Calculator App
## 1. 개요 (Overview)
본 프로젝트는 사용자가 여러 개의 수학 함수를 입력하면, 이를 실시간으로 해석하여 직교 좌표계(Cartesian Coordinate System) 상에 그래프로 시각화하는 웹 애플리케이션입니다. Mathlive 라이브러리를 통해 LaTeX 기반의 수식 입력을 처리하고, 별도의 플로팅 엔진을 통해 그래프를 그립니다.
## 2. 기술 스택 (Tech Stack)
### 2.1 Frontend Framework
* **React (v18+)**: 상태 관리 및 컴포넌트 기반 UI 구성을 위해 사용. (Vue나 Svelte로 대체 가능하나, 생태계 및 Mathlive 래퍼 가용성 측면에서 추천)
* **TypeScript**: 수식 데이터 타입 및 Props의 안정성 보장.
### 2.2 Core Libraries
1. **Input Engine: [Mathlive**](https://www.google.com/search?q=https://cortexjs.io/mathlive/)
* 역할: 사용자로부터 수학 수식을 입력받는 Web Component (`<math-field>`).
* 특징: 가상 키보드 지원, LaTeX 포맷 출력.
2. **Logic Engine: [CortexJS Compute Engine**](https://www.google.com/search?q=https://cortexjs.io/compute-engine/) (선택 사항이나 강력 추천)
* 역할: Mathlive에서 출력된 LaTeX 문자열을 파싱하고, 수치 계산 가능한 함수 형태로 변환하거나 단순화.
* 대안: `mathjs`를 사용하여 LaTeX 문자열을 파싱.
3. **Rendering Engine: [function-plot**](https://github.com/mauriciopoppe/function-plot)
* 역할: D3.js 기반의 경량 그래프 라이브러리. Desmos와 유사한 2D 함수 플로팅에 최적화됨.
* 이유: 성능이 우수하고 줌(Zoom), 팬(Pan) 기능을 기본 지원함.
---
## 3. 데이터 구조 (Data Structure)
애플리케이션의 상태(State)는 수식 객체들의 배열로 관리됩니다.
```typescript
// 수식 항목 하나의 인터페이스
interface MathExpression {
id: string; // 고유 ID (UUID)
latex: string; // Mathlive에서 입력받은 Raw LaTeX (예: "x^2 + 1")
color: string; // 그래프 색상 (예: "#FF5733")
isVisible: boolean; // 그래프 표시 여부 토글
error: string | null;// 파싱 에러 메시지 (유효하지 않은 수식일 경우)
}
// 전체 상태
interface AppState {
expressions: MathExpression[];
}
```
---
## 4. 아키텍처 및 컴포넌트 설계 (Architecture)
화면은 크게 **Left Panel (수식 입력)**과 **Right Panel (그래프 영역)**으로 나뉩니다.
### 4.1 Component Tree
```text
App
├── Sidebar (Left Panel)
│ ├── ActionToolbar (수식 추가, 모두 지우기 버튼)
│ └── ExpressionList
│ └── ExpressionItem (반복)
│ ├── ColorPicker
│ ├── MathField (Mathlive Component)
│ └── DeleteButton
└── GraphBoard (Right Panel)
└── FunctionPlotInstance (div ref)
```
### 4.2 주요 컴포넌트 상세
#### A. ExpressionItem (수식 입력 컴포넌트)
* **Mathlive 연동**: `<math-field>` 태그를 래핑하여 사용.
* **이벤트 처리**: `input` 이벤트 발생 시 `latex` 값을 상위 컴포넌트(`App`)로 전달하여 상태 업데이트.
* **UX**: 포커스 시 가상 키보드 활성화 제어.
#### B. GraphBoard (그래프 렌더링 컴포넌트)
* **Rendering Loop**: `AppState.expressions`가 변경될 때마다 `function-plot` 인스턴스를 갱신하지 않고, `data` 속성만 업데이트하여 성능 최적화 (Re-render 최소화).
* **Responsive**: 윈도우 리사이즈 시 그래프 크기 자동 조절.
---
## 5. 핵심 로직 및 워크플로우 (Core Workflows)
가장 중요한 부분은 **LaTeX(표현)를 JavaScript 함수(계산)로 변환**하는 파이프라인입니다.
### 5.1 LaTeX Parsing & Conversion Flow
1. **User Input**: 사용자가 Mathlive에 `y = \sin(x)` 입력.
2. **State Update**: React State의 `latex` 값이 `\sin(x)`로 업데이트.
3. **Sanitization (전처리)**:
* `function-plot`은 순수 LaTeX를 완벽히 이해하지 못할 수 있음.
* `Compute Engine`이나 `mathjs`를 사용하여 LaTeX를 'Plotting Engine'이 이해할 수 있는 텍스트 포맷으로 변환.
* *예시 변환*: `\frac{1}{2}x` (LaTeX) → `(1/2)*x` (String)
4. **Plotting**: 변환된 문자열을 `function-plot`의 `fn` 속성에 주입.
### 5.2 구현 예시 코드 (Logic Snippet)
```javascript
import functionPlot from 'function-plot';
// Compute Engine 인스턴스 (LaTeX 파싱용)
import { ComputeEngine } from "@cortex-js/compute-engine";
const ce = new ComputeEngine();
function updateGraph(expressions, rootElement) {
// 1. 유효한 수식만 필터링 및 변환
const data = expressions
.filter(exp => exp.isVisible && exp.latex)
.map(exp => {
// 2. Mathlive LaTeX -> Plotter String 변환
// Compute Engine을 사용하여 파싱 후 식을 단순화
const parsed = ce.parse(exp.latex);
// 변수 'y'가 포함된 등식(예: y=x^2)인지 확인하거나 단순 식(x^2)인지 처리
// function-plot은 'fn: "x^2"' 형태를 원함
return {
fn: parsed.json, // 또는 변환된 문자열
color: exp.color,
graphType: 'polyline'
};
});
// 3. 그래프 그리기
functionPlot({
target: rootElement,
width: 800,
height: 600,
grid: true,
data: data
});
}
```
---
## 6. 기능 요구사항 (Functional Requirements)
### 6.1 수식 입력 (Input)
* [ ] "수식 추가" 버튼을 누르면 새로운 입력 필드가 생성되어야 한다.
* [ ] 각 입력 필드 앞에는 해당 그래프의 색상이 표시된 아이콘이 있어야 한다.
* [ ] `x` 변수에 대한 식을 입력하면 자동으로 인식해야 한다 (예: `2x + 5`).
### 6.2 그래프 출력 (Output)
* [ ] 입력된 수식의 문법이 올바르지 않을 경우 그래프를 그리지 않고, 입력창에 에러 표시를 해야 한다 (선택 사항).
* [ ] 마우스 드래그로 좌표 평면 이동(Pan)이 가능해야 한다.
* [ ] 마우스 휠로 줌인/줌아웃(Zoom)이 가능해야 한다.
### 6.3 상호작용 (Interaction)
* [ ] 그래프 위의 점을 호버(Hover)하면 해당 좌표(x, y)가 툴팁으로 표시되어야 한다 (`function-plot` 기본 기능).
* [ ] 입력창 왼쪽의 아이콘을 클릭하여 그래프를 숨기거나 보일 수 있어야 한다 (Toggle).
---
## 7. 잠재적 이슈 및 해결 방안 (Challenges)
1. **LaTeX 파싱 복잡도**:
* *문제*: Mathlive는 매우 복잡한 LaTeX를 출력할 수 있습니다 (예: 분수, 적분 기호 등). 일반적인 플로팅 라이브러리는 이를 해석하지 못합니다.
* *해결*: `compute-engine`을 사용하여 LaTeX를 표준 수학 표현식으로 정규화(Normalize)하거나, MVP 단계에서는 기본적인 다항함수, 삼각함수, 지수/로그 함수만 지원하도록 범위를 제한합니다.
2. **성능 (Performance)**:
* *문제*: 사용자가 타이핑할 때마다(`onInput`) 그래프를 다시 그리면 렉이 발생할 수 있습니다.
* *해결*: `Debounce` (디바운스) 기술을 적용하여, 사용자가 입력을 멈춘 후 300ms 뒤에 그래프를 갱신하도록 처리합니다.
