2025-09-02 09:37:51 +09:00
|
|
|
# WACE 솔루션 (PLM)
|
2025-08-21 09:41:46 +09:00
|
|
|
|
|
|
|
|
## 프로젝트 개요
|
|
|
|
|
|
|
|
|
|
본 프로젝트는 제품 수명 주기 관리(PLM - Product Lifecycle Management) 솔루션입니다.
|
|
|
|
|
**기존 JSP 기반 프론트엔드를 Next.js 14로 완전 전환**하여 현대적이고 사용자 친화적인 웹 애플리케이션을 제공합니다.
|
|
|
|
|
|
|
|
|
|
## 🚀 주요 특징
|
|
|
|
|
|
|
|
|
|
- **모던 프론트엔드**: Next.js 14 + TypeScript + shadcn/ui
|
|
|
|
|
- **반응형 디자인**: 데스크톱, 태블릿, 모바일 모든 기기 지원
|
|
|
|
|
- **안정적인 백엔드**: 검증된 Java Spring + MyBatis 기반 API
|
|
|
|
|
- **Docker 기반 배포**: 개발/운영 환경 일관성 보장
|
|
|
|
|
- **타입 안전성**: TypeScript로 런타임 에러 방지
|
|
|
|
|
|
|
|
|
|
## 🛠️ 기술 스택
|
|
|
|
|
|
|
|
|
|
### Frontend (Next.js 14)
|
|
|
|
|
|
|
|
|
|
- **프레임워크**: Next.js 14 (App Router)
|
|
|
|
|
- **언어**: TypeScript
|
|
|
|
|
- **UI 라이브러리**: shadcn/ui + Radix UI
|
|
|
|
|
- **스타일링**: Tailwind CSS
|
|
|
|
|
- **폼 처리**: React Hook Form + Zod
|
|
|
|
|
- **상태 관리**: React Context + Hooks
|
|
|
|
|
- **아이콘**: Lucide React
|
|
|
|
|
|
|
|
|
|
### Backend (기존 유지)
|
|
|
|
|
|
|
|
|
|
- **언어**: Java 7
|
|
|
|
|
- **프레임워크**: Spring Framework 3.2.4
|
|
|
|
|
- **ORM**: MyBatis 3.2.3
|
|
|
|
|
- **데이터베이스**: PostgreSQL
|
|
|
|
|
- **WAS**: Apache Tomcat 7.0
|
|
|
|
|
|
|
|
|
|
### 개발 도구
|
|
|
|
|
|
|
|
|
|
- **컨테이너화**: Docker + Docker Compose
|
|
|
|
|
- **코드 품질**: ESLint + TypeScript
|
|
|
|
|
- **패키지 관리**: npm
|
|
|
|
|
|
|
|
|
|
## 📁 프로젝트 구조
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
new_ph/
|
|
|
|
|
├── frontend/ # Next.js 프론트엔드
|
|
|
|
|
│ ├── app/ # Next.js App Router
|
|
|
|
|
│ │ ├── (auth)/ # 인증 관련 페이지
|
|
|
|
|
│ │ │ └── login/ # 로그인 페이지
|
|
|
|
|
│ │ ├── dashboard/ # 대시보드
|
|
|
|
|
│ │ └── layout.tsx # 루트 레이아웃
|
|
|
|
|
│ ├── components/ # 재사용 컴포넌트
|
|
|
|
|
│ │ ├── ui/ # shadcn/ui 기본 컴포넌트
|
|
|
|
|
│ │ └── layout/ # 레이아웃 컴포넌트
|
|
|
|
|
│ ├── lib/ # 유틸리티 함수
|
|
|
|
|
│ └── types/ # TypeScript 타입 정의
|
|
|
|
|
├── src/ # Java 백엔드 소스
|
|
|
|
|
│ └── com/pms/ # 패키지 구조
|
|
|
|
|
├── WebContent/ # 레거시 JSP (사용 중단)
|
|
|
|
|
├── db/ # 데이터베이스 스크립트
|
|
|
|
|
└── docker-compose.win.yml # Windows 환경 설정
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 🚀 빠른 시작
|
|
|
|
|
|
|
|
|
|
### 1. 필수 요구사항
|
|
|
|
|
|
|
|
|
|
- **Docker Desktop** (Windows/Mac) 또는 **Docker + Docker Compose** (Linux)
|
|
|
|
|
- **Git** (소스 코드 관리)
|
|
|
|
|
|
|
|
|
|
### 2. Windows 환경에서 실행
|
|
|
|
|
|
|
|
|
|
#### 자동 실행 (권장)
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# 프로젝트 시작
|
|
|
|
|
./run-windows.bat
|
|
|
|
|
|
|
|
|
|
# 서비스 상태 확인
|
|
|
|
|
./status-windows.bat
|
|
|
|
|
|
|
|
|
|
# 서비스 중지
|
|
|
|
|
./stop-windows.bat
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 수동 실행
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Docker 컨테이너 실행
|
|
|
|
|
docker-compose -f docker-compose.win.yml up --build -d
|
|
|
|
|
|
|
|
|
|
# 로그 확인
|
|
|
|
|
docker-compose -f docker-compose.win.yml logs -f
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 3. 서비스 접속
|
|
|
|
|
|
|
|
|
|
| 서비스 | URL | 설명 |
|
|
|
|
|
| -------------- | --------------------- | ------------------------------ |
|
|
|
|
|
| **프론트엔드** | http://localhost:9771 | Next.js 기반 사용자 인터페이스 |
|
|
|
|
|
| **백엔드 API** | http://localhost:9090 | Spring 기반 REST API |
|
|
|
|
|
|
|
|
|
|
> **주의**: 기존 JSP 화면(`localhost:9090`)은 더 이상 사용하지 않습니다.
|
|
|
|
|
> 모든 사용자는 **Next.js 프론트엔드(`localhost:9771`)**를 사용해주세요.
|
|
|
|
|
|
|
|
|
|
## 🎨 UI/UX 디자인 시스템
|
|
|
|
|
|
|
|
|
|
### shadcn/ui 컴포넌트 라이브러리
|
|
|
|
|
|
|
|
|
|
- **일관된 디자인**: 전체 애플리케이션에서 통일된 UI 컴포넌트
|
|
|
|
|
- **접근성**: WCAG 가이드라인 준수
|
|
|
|
|
- **커스터마이징**: Tailwind CSS로 쉬운 스타일 변경
|
|
|
|
|
- **다크모드**: 자동 테마 전환 지원
|
|
|
|
|
|
|
|
|
|
### 공통 스타일 가이드
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// 색상 팔레트
|
|
|
|
|
const colors = {
|
|
|
|
|
primary: "hsl(222.2 47.4% 11.2%)", // 네이비 블루
|
|
|
|
|
secondary: "hsl(210 40% 96%)", // 연한 그레이
|
|
|
|
|
accent: "hsl(210 40% 98%)", // 거의 화이트
|
|
|
|
|
destructive: "hsl(0 62.8% 30.6%)", // 레드
|
|
|
|
|
muted: "hsl(210 40% 96%)", // 음소거된 그레이
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// 타이포그래피
|
|
|
|
|
const typography = {
|
|
|
|
|
fontFamily: "Inter, system-ui, sans-serif",
|
|
|
|
|
fontSize: {
|
|
|
|
|
xs: "0.75rem", // 12px
|
|
|
|
|
sm: "0.875rem", // 14px
|
|
|
|
|
base: "1rem", // 16px
|
|
|
|
|
lg: "1.125rem", // 18px
|
|
|
|
|
xl: "1.25rem", // 20px
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 🔧 개발 가이드
|
|
|
|
|
|
|
|
|
|
### 컴포넌트 개발 원칙
|
|
|
|
|
|
|
|
|
|
#### 1. 재사용 가능한 컴포넌트
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// components/ui/button.tsx
|
|
|
|
|
interface ButtonProps {
|
|
|
|
|
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost";
|
|
|
|
|
size?: "default" | "sm" | "lg" | "icon";
|
|
|
|
|
children: React.ReactNode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function Button({
|
|
|
|
|
variant = "default",
|
|
|
|
|
size = "default",
|
|
|
|
|
children,
|
|
|
|
|
...props
|
|
|
|
|
}: ButtonProps) {
|
|
|
|
|
return (
|
|
|
|
|
<button className={cn(buttonVariants({ variant, size }))} {...props}>
|
|
|
|
|
{children}
|
|
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 2. 폼 컴포넌트
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// React Hook Form + Zod 사용
|
|
|
|
|
import { useForm } from "react-hook-form";
|
|
|
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
|
|
|
import * as z from "zod";
|
|
|
|
|
|
|
|
|
|
const loginSchema = z.object({
|
|
|
|
|
userId: z.string().min(1, "사용자 ID를 입력해주세요"),
|
|
|
|
|
password: z.string().min(1, "비밀번호를 입력해주세요"),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
export function LoginForm() {
|
|
|
|
|
const form = useForm<z.infer<typeof loginSchema>>({
|
|
|
|
|
resolver: zodResolver(loginSchema),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 폼 처리 로직
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 3. API 연동
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// lib/api.ts
|
|
|
|
|
class ApiClient {
|
|
|
|
|
private baseURL = process.env.NEXT_PUBLIC_API_URL || "http://localhost:9090";
|
|
|
|
|
|
|
|
|
|
async login(credentials: LoginCredentials): Promise<LoginResponse> {
|
|
|
|
|
const response = await fetch(`${this.baseURL}/api/auth/login`, {
|
|
|
|
|
method: "POST",
|
|
|
|
|
headers: { "Content-Type": "application/json" },
|
|
|
|
|
body: JSON.stringify(credentials),
|
|
|
|
|
credentials: "include", // 세션 쿠키 포함
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!response.ok) throw new Error("로그인 실패");
|
|
|
|
|
return response.json();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 스타일링 가이드
|
|
|
|
|
|
|
|
|
|
#### 1. Tailwind CSS 클래스
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// 일반적인 레이아웃
|
|
|
|
|
<div className="flex items-center justify-center min-h-screen bg-slate-50">
|
|
|
|
|
<div className="w-full max-w-md space-y-6">
|
|
|
|
|
{/* 컨텐츠 */}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
// 카드 컴포넌트
|
|
|
|
|
<div className="bg-white rounded-lg shadow-lg border border-slate-200 p-6">
|
|
|
|
|
{/* 카드 내용 */}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
// 반응형 그리드
|
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
|
|
|
{/* 그리드 아이템 */}
|
|
|
|
|
</div>
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 2. CSS 변수 활용
|
|
|
|
|
|
|
|
|
|
```css
|
|
|
|
|
/* globals.css */
|
|
|
|
|
:root {
|
|
|
|
|
--background: 0 0% 100%;
|
|
|
|
|
--foreground: 222.2 84% 4.9%;
|
|
|
|
|
--primary: 222.2 47.4% 11.2%;
|
|
|
|
|
--primary-foreground: 210 40% 98%;
|
|
|
|
|
--secondary: 210 40% 96%;
|
|
|
|
|
--secondary-foreground: 222.2 84% 4.9%;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 🔐 인증 시스템
|
|
|
|
|
|
|
|
|
|
### 세션 기반 인증 (기존 백엔드 호환)
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// 로그인 프로세스
|
|
|
|
|
1. 사용자가 로그인 폼 제출
|
|
|
|
|
2. Next.js에서 백엔드 API 호출
|
|
|
|
|
3. 백엔드에서 세션 생성 (기존 로직 사용)
|
|
|
|
|
4. 프론트엔드에서 인증 상태 관리
|
|
|
|
|
5. 보호된 라우트 접근 제어
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 라우트 보호
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
// middleware.ts
|
|
|
|
|
export function middleware(request: NextRequest) {
|
|
|
|
|
const { pathname } = request.nextUrl;
|
|
|
|
|
|
|
|
|
|
// 공개 페이지
|
|
|
|
|
const publicPaths = ["/login", "/"];
|
|
|
|
|
if (publicPaths.includes(pathname)) return NextResponse.next();
|
|
|
|
|
|
|
|
|
|
// 인증 확인
|
|
|
|
|
const sessionCookie = request.cookies.get("JSESSIONID");
|
|
|
|
|
if (!sessionCookie) {
|
|
|
|
|
return NextResponse.redirect(new URL("/login", request.url));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NextResponse.next();
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 📊 주요 기능
|
|
|
|
|
|
|
|
|
|
### 1. 대시보드
|
|
|
|
|
|
|
|
|
|
- **프로젝트 현황**: 진행 중인 프로젝트 상태 모니터링
|
|
|
|
|
- **작업 요약**: 개인별 할당된 작업 목록
|
|
|
|
|
- **알림 센터**: 중요한 업데이트 및 알림
|
|
|
|
|
- **차트 및 그래프**: 프로젝트 진척도 시각화
|
|
|
|
|
|
|
|
|
|
### 2. 프로젝트 관리
|
|
|
|
|
|
|
|
|
|
- **프로젝트 생성/수정**: 새 프로젝트 등록 및 정보 관리
|
|
|
|
|
- **팀 구성**: 프로젝트 멤버 할당 및 역할 관리
|
|
|
|
|
- **마일스톤**: 주요 일정 및 목표 설정
|
|
|
|
|
- **진행 상황 추적**: 실시간 프로젝트 진척도 모니터링
|
|
|
|
|
|
|
|
|
|
### 3. 제품 관리
|
|
|
|
|
|
|
|
|
|
- **제품 카탈로그**: 제품 정보 및 사양 관리
|
|
|
|
|
- **BOM 관리**: Bill of Materials 구성 및 버전 관리
|
|
|
|
|
- **설계 변경**: ECO/ECR 프로세스 관리
|
|
|
|
|
- **문서 관리**: 기술 문서 및 도면 버전 제어
|
|
|
|
|
|
|
|
|
|
### 4. 사용자 관리
|
|
|
|
|
|
|
|
|
|
- **사용자 계정**: 계정 생성/수정/비활성화
|
|
|
|
|
- **권한 관리**: 역할 기반 접근 제어 (RBAC)
|
|
|
|
|
- **부서 관리**: 조직 구조 및 부서별 권한 설정
|
|
|
|
|
- **감사 로그**: 사용자 활동 추적 및 보안 모니터링
|
|
|
|
|
|
|
|
|
|
## 🚢 배포 가이드
|
|
|
|
|
|
|
|
|
|
### 개발 환경
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# 프론트엔드 개발 서버
|
|
|
|
|
cd frontend && npm run dev
|
|
|
|
|
|
|
|
|
|
# 백엔드 (Docker)
|
|
|
|
|
docker-compose -f docker-compose.win.yml up -d plm-app
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 운영 환경
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# 전체 서비스 배포
|
|
|
|
|
docker-compose -f docker-compose.prod.yml up -d
|
|
|
|
|
|
|
|
|
|
# 무중단 배포 (blue-green)
|
|
|
|
|
./deploy-production.sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 환경 변수 설정
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# .env.local (Next.js)
|
|
|
|
|
NEXT_PUBLIC_API_URL=http://localhost:9090
|
|
|
|
|
NEXT_PUBLIC_APP_ENV=development
|
|
|
|
|
|
|
|
|
|
# docker-compose.win.yml (백엔드)
|
|
|
|
|
DB_URL=jdbc:postgresql://db:5432/plm
|
|
|
|
|
DB_USERNAME=postgres
|
|
|
|
|
DB_PASSWORD=secure_password
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 🔧 문제 해결
|
|
|
|
|
|
|
|
|
|
### 자주 발생하는 문제
|
|
|
|
|
|
|
|
|
|
#### 1. 로그인 화면이 업데이트되지 않는 경우
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# 브라우저 캐시 클리어 후 다음 확인:
|
|
|
|
|
# - Next.js 서버 재시작
|
|
|
|
|
npm run dev
|
|
|
|
|
|
|
|
|
|
# - 올바른 URL 접속 확인
|
|
|
|
|
# 올바름: http://localhost:9771/login
|
|
|
|
|
# 잘못됨: http://localhost:9090/login.jsp
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 2. Docker 컨테이너 실행 오류
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# 포트 충돌 확인
|
|
|
|
|
netstat -ano | findstr :9771
|
|
|
|
|
netstat -ano | findstr :9090
|
|
|
|
|
|
|
|
|
|
# Docker 시스템 정리
|
|
|
|
|
docker system prune -a
|
|
|
|
|
docker-compose -f docker-compose.win.yml down --volumes
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### 3. API 연결 오류
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# 백엔드 컨테이너 로그 확인
|
|
|
|
|
docker-compose -f docker-compose.win.yml logs plm-app
|
|
|
|
|
|
|
|
|
|
# 네트워크 연결 확인
|
|
|
|
|
curl http://localhost:9090/api/health
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 개발자 도구
|
|
|
|
|
|
|
|
|
|
#### 브라우저 개발자 도구
|
|
|
|
|
|
|
|
|
|
- **Console**: JavaScript 오류 확인
|
|
|
|
|
- **Network**: API 요청/응답 모니터링
|
|
|
|
|
- **Application**: 세션 쿠키 확인
|
|
|
|
|
|
|
|
|
|
#### 로그 확인
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Next.js 개발 서버 로그
|
|
|
|
|
npm run dev
|
|
|
|
|
|
|
|
|
|
# 백엔드 애플리케이션 로그
|
|
|
|
|
docker-compose -f docker-compose.win.yml logs -f plm-app
|
|
|
|
|
|
|
|
|
|
# 데이터베이스 로그
|
|
|
|
|
docker-compose -f docker-compose.win.yml logs -f db
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 📈 성능 최적화
|
|
|
|
|
|
|
|
|
|
### Next.js 최적화
|
|
|
|
|
|
|
|
|
|
- **이미지 최적화**: Next.js Image 컴포넌트 사용
|
|
|
|
|
- **코드 분할**: 동적 임포트로 번들 크기 최소화
|
|
|
|
|
- **서버 사이드 렌더링**: 초기 로딩 속도 개선
|
|
|
|
|
- **정적 생성**: 변경되지 않는 페이지 사전 생성
|
|
|
|
|
|
|
|
|
|
### 백엔드 최적화
|
|
|
|
|
|
|
|
|
|
- **데이터베이스 인덱스**: 자주 조회되는 필드 인덱싱
|
|
|
|
|
- **쿼리 최적화**: N+1 문제 해결
|
|
|
|
|
- **캐싱**: Redis를 통한 세션 및 데이터 캐싱
|
|
|
|
|
- **리소스 최적화**: JVM 메모리 튜닝
|
|
|
|
|
|
|
|
|
|
## 🤝 기여 가이드
|
|
|
|
|
|
|
|
|
|
### 코드 컨벤션
|
|
|
|
|
|
|
|
|
|
- **TypeScript**: 엄격한 타입 정의 사용
|
|
|
|
|
- **ESLint**: 코드 품질 유지.
|
|
|
|
|
- **Prettier**: 일관된 코드 포맷팅
|
|
|
|
|
- **커밋 메시지**: Conventional Commits 규칙 준수
|
|
|
|
|
|
|
|
|
|
### 브랜치 전략
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
main # 운영 환경 배포 브랜치
|
|
|
|
|
develop # 개발 환경 통합 브랜치
|
|
|
|
|
feature/* # 기능 개발 브랜치
|
|
|
|
|
hotfix/* # 긴급 수정 브랜치
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Pull Request 프로세스
|
|
|
|
|
|
|
|
|
|
1. 기능 브랜치에서 개발
|
|
|
|
|
2. 테스트 코드 작성
|
|
|
|
|
3. PR 생성 및 코드 리뷰
|
|
|
|
|
4. 승인 후 develop 브랜치에 병합
|
|
|
|
|
|
|
|
|
|
## 📞 지원 및 문의
|
|
|
|
|
|
|
|
|
|
- **개발팀 문의**: 내부 Slack 채널 `#plm-support`
|
|
|
|
|
- **버그 리포트**: GitHub Issues
|
|
|
|
|
- **기능 요청**: Product Owner와 협의
|
|
|
|
|
- **긴급 상황**: 개발팀 직접 연락
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## 📝 변경 이력
|
|
|
|
|
|
|
|
|
|
### v2.0.0 (2025년 1월)
|
|
|
|
|
|
|
|
|
|
- ✅ JSP → Next.js 14 완전 전환
|
|
|
|
|
- ✅ shadcn/ui 디자인 시스템 도입
|
|
|
|
|
- ✅ TypeScript 타입 안전성 강화
|
|
|
|
|
- ✅ 반응형 디자인 적용
|
|
|
|
|
- ✅ WACE 브랜딩 적용
|
|
|
|
|
|
|
|
|
|
### v1.x (레거시)
|
|
|
|
|
|
|
|
|
|
- ❌ JSP + jQuery 기반 (사용 중단)
|
|
|
|
|
- ❌ 데스크톱 전용 UI
|
|
|
|
|
- ❌ 제한적인 확장성
|
|
|
|
|
|
|
|
|
|
**🎉 현재 버전 2.0.0에서는 완전히 새로운 사용자 경험을 제공합니다!**
|