From cbc7e26d8f7e10602dcf5f58402e27991d300a8c Mon Sep 17 00:00:00 2001 From: Emithen <86219540+Emithen@users.noreply.github.com> Date: Sun, 14 Jun 2026 22:11:52 +0900 Subject: [PATCH 1/2] =?UTF-8?q?chore:=20tree-request=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=20=ED=98=95=EC=8B=9D=20=EC=A1=B0=EC=A0=95=20=EB=B0=8F=20mock?= =?UTF-8?q?=20=EC=8B=9C=EB=82=98=EB=A6=AC=EC=98=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat/controller/ChatController.java | 21 +-- src/main/resources/mocks/chat/tree-empty.json | 2 +- src/main/resources/mocks/chat/tree-large.json | 102 ++++++------- src/main/resources/mocks/chat/tree-max.json | 134 ++++++++++++++++++ src/main/resources/mocks/chat/tree-small.json | 12 +- 5 files changed, 203 insertions(+), 68 deletions(-) create mode 100644 src/main/resources/mocks/chat/tree-max.json diff --git a/src/main/java/com/tree/twig_tree/domain/chat/controller/ChatController.java b/src/main/java/com/tree/twig_tree/domain/chat/controller/ChatController.java index e66fe5d..2a0b5b4 100644 --- a/src/main/java/com/tree/twig_tree/domain/chat/controller/ChatController.java +++ b/src/main/java/com/tree/twig_tree/domain/chat/controller/ChatController.java @@ -47,6 +47,7 @@ public class ChatController { - `small` (기본): 노드 5개 - `empty`: 노드 0개 - `large`: 노드 50개 + - `max`: 노드 100개 """ ) @ApiResponses(value = { @@ -64,13 +65,13 @@ public class ChatController { "code": "CHAT201-1", "message": "트리가 성공적으로 생성되었습니다.", "data": { - "tree_id": 12, + "treeId": 12, "nodes": [ - { "node_id": 1, "title": "자료구조", "memo": "데이터를 조직하고 저장하는 방법", "parent_id": null, "order_id": 1 }, - { "node_id": 2, "title": "알고리즘", "parent_id": null, "order_id": 2 }, - { "node_id": 3, "title": "배열", "memo": "연속된 메모리 공간", "parent_id": 1, "order_id": 1 }, - { "node_id": 4, "title": "스택", "memo": "LIFO 자료구조", "parent_id": 1, "order_id": 2 }, - { "node_id": 5, "title": "정렬", "parent_id": 2, "order_id": 1 } + { "nodeId": 1, "name": "자료구조", "memo": "데이터를 조직하고 저장하는 방법", "parentId": null, "orderId": 1 }, + { "nodeId": 2, "name": "알고리즘", "parentId": null, "orderId": 2 }, + { "nodeId": 3, "name": "배열", "memo": "연속된 메모리 공간", "parentId": 1, "orderId": 1 }, + { "nodeId": 4, "name": "스택", "memo": "LIFO 자료구조", "parentId": 1, "orderId": 2 }, + { "nodeId": 5, "name": "정렬", "parentId": 2, "orderId": 1 } ] } } @@ -83,7 +84,7 @@ public class ChatController { "isSuccess": true, "code": "CHAT201-1", "message": "트리가 성공적으로 생성되었습니다.", - "data": { "tree_id": 99, "nodes": [] } + "data": { "treeId": 99, "nodes": [] } } """ ), @@ -95,9 +96,9 @@ public class ChatController { "code": "CHAT201-1", "message": "트리가 성공적으로 생성되었습니다.", "data": { - "tree_id": 34, + "treeId": 34, "nodes": [ - { "node_id": 1, "title": "자료구조", "parent_id": null, "order_id": 1 }, + { "nodeId": 1, "name": "자료구조", "parentId": null, "orderId": 1 }, "... (총 50개 노드, 깊이 3)" ] } @@ -113,7 +114,7 @@ public ApiResponse chat( @RequestBody(required = false) ChatReqDTO req, @Parameter( description = "Mock 시나리오 선택", - schema = @Schema(allowableValues = {"empty", "small", "large"}, defaultValue = "small"), + schema = @Schema(allowableValues = {"empty", "small", "large", "max"}, defaultValue = "small"), example = "small" ) @RequestParam(defaultValue = "small") String scenario diff --git a/src/main/resources/mocks/chat/tree-empty.json b/src/main/resources/mocks/chat/tree-empty.json index 4bc6ab2..0ce340c 100644 --- a/src/main/resources/mocks/chat/tree-empty.json +++ b/src/main/resources/mocks/chat/tree-empty.json @@ -1,4 +1,4 @@ { - "tree_id": 99, + "treeId": 99, "nodes": [] } diff --git a/src/main/resources/mocks/chat/tree-large.json b/src/main/resources/mocks/chat/tree-large.json index 5bf80cb..deda508 100644 --- a/src/main/resources/mocks/chat/tree-large.json +++ b/src/main/resources/mocks/chat/tree-large.json @@ -1,66 +1,66 @@ { - "tree_id": 34, + "treeId": 34, "nodes": [ - { "node_id": 1, "title": "자료구조", "memo": "데이터를 조직하고 저장하는 방법", "parent_id": null, "order_id": 1 }, - { "node_id": 2, "title": "알고리즘", "memo": "문제 해결을 위한 절차", "parent_id": null, "order_id": 2 }, - { "node_id": 3, "title": "운영체제", "memo": "하드웨어와 응용 프로그램 사이의 인터페이스", "parent_id": null, "order_id": 3 }, - { "node_id": 4, "title": "네트워크", "parent_id": null, "order_id": 4 }, - { "node_id": 5, "title": "데이터베이스", "memo": "구조화된 데이터의 저장소", "parent_id": null, "order_id": 5 }, + { "nodeId": 1, "name": "자료구조", "memo": "데이터를 조직하고 저장하는 방법", "parentId": null, "orderId": 1 }, + { "nodeId": 2, "name": "알고리즘", "memo": "문제 해결을 위한 절차", "parentId": null, "orderId": 2 }, + { "nodeId": 3, "name": "운영체제", "memo": "하드웨어와 응용 프로그램 사이의 인터페이스", "parentId": null, "orderId": 3 }, + { "nodeId": 4, "name": "네트워크", "parentId": null, "orderId": 4 }, + { "nodeId": 5, "name": "데이터베이스", "memo": "구조화된 데이터의 저장소", "parentId": null, "orderId": 5 }, - { "node_id": 6, "title": "배열", "memo": "연속된 메모리 공간", "parent_id": 1, "order_id": 1 }, - { "node_id": 7, "title": "연결리스트", "parent_id": 1, "order_id": 2 }, - { "node_id": 8, "title": "스택", "memo": "LIFO 자료구조", "parent_id": 1, "order_id": 3 }, - { "node_id": 9, "title": "큐", "memo": "FIFO 자료구조", "parent_id": 1, "order_id": 4 }, - { "node_id": 10, "title": "트리", "memo": "계층적 자료구조", "parent_id": 1, "order_id": 5 }, - { "node_id": 11, "title": "그래프", "parent_id": 1, "order_id": 6 }, - { "node_id": 12, "title": "해시테이블", "memo": "키-값 매핑 자료구조", "parent_id": 1, "order_id": 7 }, + { "nodeId": 6, "name": "배열", "memo": "연속된 메모리 공간", "parentId": 1, "orderId": 1 }, + { "nodeId": 7, "name": "연결리스트", "parentId": 1, "orderId": 2 }, + { "nodeId": 8, "name": "스택", "memo": "LIFO 자료구조", "parentId": 1, "orderId": 3 }, + { "nodeId": 9, "name": "큐", "memo": "FIFO 자료구조", "parentId": 1, "orderId": 4 }, + { "nodeId": 10, "name": "트리", "memo": "계층적 자료구조", "parentId": 1, "orderId": 5 }, + { "nodeId": 11, "name": "그래프", "parentId": 1, "orderId": 6 }, + { "nodeId": 12, "name": "해시테이블", "memo": "키-값 매핑 자료구조", "parentId": 1, "orderId": 7 }, - { "node_id": 13, "title": "이진트리", "memo": "각 노드가 최대 2개의 자식", "parent_id": 10, "order_id": 1 }, - { "node_id": 14, "title": "BST", "memo": "왼쪽 < 부모 < 오른쪽", "parent_id": 10, "order_id": 2 }, - { "node_id": 15, "title": "AVL 트리", "parent_id": 10, "order_id": 3 }, - { "node_id": 16, "title": "힙", "memo": "우선순위 큐 구현용", "parent_id": 10, "order_id": 4 }, + { "nodeId": 13, "name": "이진트리", "memo": "각 노드가 최대 2개의 자식", "parentId": 10, "orderId": 1 }, + { "nodeId": 14, "name": "BST", "memo": "왼쪽 < 부모 < 오른쪽", "parentId": 10, "orderId": 2 }, + { "nodeId": 15, "name": "AVL 트리", "parentId": 10, "orderId": 3 }, + { "nodeId": 16, "name": "힙", "memo": "우선순위 큐 구현용", "parentId": 10, "orderId": 4 }, - { "node_id": 17, "title": "DFS", "memo": "깊이 우선 탐색", "parent_id": 11, "order_id": 1 }, - { "node_id": 18, "title": "BFS", "memo": "너비 우선 탐색", "parent_id": 11, "order_id": 2 }, + { "nodeId": 17, "name": "DFS", "memo": "깊이 우선 탐색", "parentId": 11, "orderId": 1 }, + { "nodeId": 18, "name": "BFS", "memo": "너비 우선 탐색", "parentId": 11, "orderId": 2 }, - { "node_id": 19, "title": "정렬", "parent_id": 2, "order_id": 1 }, - { "node_id": 20, "title": "탐색", "memo": "이진 탐색, 선형 탐색 등", "parent_id": 2, "order_id": 2 }, - { "node_id": 21, "title": "동적계획법", "memo": "부분 문제 결과 재사용", "parent_id": 2, "order_id": 3 }, - { "node_id": 22, "title": "그리디", "parent_id": 2, "order_id": 4 }, - { "node_id": 23, "title": "분할정복", "memo": "문제를 나눠 푼다", "parent_id": 2, "order_id": 5 }, - { "node_id": 24, "title": "백트래킹", "parent_id": 2, "order_id": 6 }, + { "nodeId": 19, "name": "정렬", "parentId": 2, "orderId": 1 }, + { "nodeId": 20, "name": "탐색", "memo": "이진 탐색, 선형 탐색 등", "parentId": 2, "orderId": 2 }, + { "nodeId": 21, "name": "동적계획법", "memo": "부분 문제 결과 재사용", "parentId": 2, "orderId": 3 }, + { "nodeId": 22, "name": "그리디", "parentId": 2, "orderId": 4 }, + { "nodeId": 23, "name": "분할정복", "memo": "문제를 나눠 푼다", "parentId": 2, "orderId": 5 }, + { "nodeId": 24, "name": "백트래킹", "parentId": 2, "orderId": 6 }, - { "node_id": 25, "title": "버블 정렬", "memo": "O(n²)", "parent_id": 19, "order_id": 1 }, - { "node_id": 26, "title": "퀵 정렬", "memo": "평균 O(n log n)", "parent_id": 19, "order_id": 2 }, - { "node_id": 27, "title": "병합 정렬", "memo": "안정 정렬, O(n log n)", "parent_id": 19, "order_id": 3 }, - { "node_id": 28, "title": "힙 정렬", "parent_id": 19, "order_id": 4 }, + { "nodeId": 25, "name": "버블 정렬", "memo": "O(n²)", "parentId": 19, "orderId": 1 }, + { "nodeId": 26, "name": "퀵 정렬", "memo": "평균 O(n log n)", "parentId": 19, "orderId": 2 }, + { "nodeId": 27, "name": "병합 정렬", "memo": "안정 정렬, O(n log n)", "parentId": 19, "orderId": 3 }, + { "nodeId": 28, "name": "힙 정렬", "parentId": 19, "orderId": 4 }, - { "node_id": 29, "title": "메모이제이션", "memo": "Top-down 방식", "parent_id": 21, "order_id": 1 }, - { "node_id": 30, "title": "타뷸레이션", "memo": "Bottom-up 방식", "parent_id": 21, "order_id": 2 }, + { "nodeId": 29, "name": "메모이제이션", "memo": "Top-down 방식", "parentId": 21, "orderId": 1 }, + { "nodeId": 30, "name": "타뷸레이션", "memo": "Bottom-up 방식", "parentId": 21, "orderId": 2 }, - { "node_id": 31, "title": "프로세스", "memo": "실행 중인 프로그램", "parent_id": 3, "order_id": 1 }, - { "node_id": 32, "title": "스레드", "parent_id": 3, "order_id": 2 }, - { "node_id": 33, "title": "스케줄링", "memo": "CPU 할당 순서 결정", "parent_id": 3, "order_id": 3 }, - { "node_id": 34, "title": "메모리 관리", "parent_id": 3, "order_id": 4 }, - { "node_id": 35, "title": "파일시스템", "memo": "데이터의 영구 저장 구조", "parent_id": 3, "order_id": 5 }, + { "nodeId": 31, "name": "프로세스", "memo": "실행 중인 프로그램", "parentId": 3, "orderId": 1 }, + { "nodeId": 32, "name": "스레드", "parentId": 3, "orderId": 2 }, + { "nodeId": 33, "name": "스케줄링", "memo": "CPU 할당 순서 결정", "parentId": 3, "orderId": 3 }, + { "nodeId": 34, "name": "메모리 관리", "parentId": 3, "orderId": 4 }, + { "nodeId": 35, "name": "파일시스템", "memo": "데이터의 영구 저장 구조", "parentId": 3, "orderId": 5 }, - { "node_id": 36, "title": "FCFS", "memo": "First Come First Served", "parent_id": 33, "order_id": 1 }, - { "node_id": 37, "title": "SJF", "memo": "Shortest Job First", "parent_id": 33, "order_id": 2 }, - { "node_id": 38, "title": "라운드 로빈", "parent_id": 33, "order_id": 3 }, + { "nodeId": 36, "name": "FCFS", "memo": "First Come First Served", "parentId": 33, "orderId": 1 }, + { "nodeId": 37, "name": "SJF", "memo": "Shortest Job First", "parentId": 33, "orderId": 2 }, + { "nodeId": 38, "name": "라운드 로빈", "parentId": 33, "orderId": 3 }, - { "node_id": 39, "title": "OSI 7계층", "memo": "물리/데이터링크/네트워크/전송/세션/표현/응용", "parent_id": 4, "order_id": 1 }, - { "node_id": 40, "title": "TCP/IP", "parent_id": 4, "order_id": 2 }, - { "node_id": 41, "title": "HTTP", "memo": "웹의 기본 프로토콜", "parent_id": 4, "order_id": 3 }, - { "node_id": 42, "title": "DNS", "memo": "도메인 → IP 변환", "parent_id": 4, "order_id": 4 }, + { "nodeId": 39, "name": "OSI 7계층", "memo": "물리/데이터링크/네트워크/전송/세션/표현/응용", "parentId": 4, "orderId": 1 }, + { "nodeId": 40, "name": "TCP/IP", "parentId": 4, "orderId": 2 }, + { "nodeId": 41, "name": "HTTP", "memo": "웹의 기본 프로토콜", "parentId": 4, "orderId": 3 }, + { "nodeId": 42, "name": "DNS", "memo": "도메인 → IP 변환", "parentId": 4, "orderId": 4 }, - { "node_id": 43, "title": "HTTP/1.1", "memo": "Keep-Alive 도입", "parent_id": 41, "order_id": 1 }, - { "node_id": 44, "title": "HTTP/2", "memo": "멀티플렉싱 지원", "parent_id": 41, "order_id": 2 }, - { "node_id": 45, "title": "HTTPS", "parent_id": 41, "order_id": 3 }, + { "nodeId": 43, "name": "HTTP/1.1", "memo": "Keep-Alive 도입", "parentId": 41, "orderId": 1 }, + { "nodeId": 44, "name": "HTTP/2", "memo": "멀티플렉싱 지원", "parentId": 41, "orderId": 2 }, + { "nodeId": 45, "name": "HTTPS", "parentId": 41, "orderId": 3 }, - { "node_id": 46, "title": "관계형 DB", "memo": "테이블 기반, ACID 보장", "parent_id": 5, "order_id": 1 }, - { "node_id": 47, "title": "NoSQL", "parent_id": 5, "order_id": 2 }, - { "node_id": 48, "title": "인덱스", "memo": "검색 성능 향상", "parent_id": 5, "order_id": 3 }, - { "node_id": 49, "title": "트랜잭션", "memo": "ACID 속성", "parent_id": 5, "order_id": 4 }, - { "node_id": 50, "title": "정규화", "memo": "중복 제거와 무결성", "parent_id": 5, "order_id": 5 } + { "nodeId": 46, "name": "관계형 DB", "memo": "테이블 기반, ACID 보장", "parentId": 5, "orderId": 1 }, + { "nodeId": 47, "name": "NoSQL", "parentId": 5, "orderId": 2 }, + { "nodeId": 48, "name": "인덱스", "memo": "검색 성능 향상", "parentId": 5, "orderId": 3 }, + { "nodeId": 49, "name": "트랜잭션", "memo": "ACID 속성", "parentId": 5, "orderId": 4 }, + { "nodeId": 50, "name": "정규화", "memo": "중복 제거와 무결성", "parentId": 5, "orderId": 5 } ] } diff --git a/src/main/resources/mocks/chat/tree-max.json b/src/main/resources/mocks/chat/tree-max.json new file mode 100644 index 0000000..53f4c34 --- /dev/null +++ b/src/main/resources/mocks/chat/tree-max.json @@ -0,0 +1,134 @@ +{ + "treeId": 55, + "nodes": [ + { "nodeId": 1, "name": "프론트엔드", "memo": "사용자와 직접 상호작용하는 클라이언트 영역", "parentId": null, "orderId": 1 }, + { "nodeId": 2, "name": "백엔드", "memo": "서버 측 비즈니스 로직과 데이터 처리", "parentId": null, "orderId": 2 }, + { "nodeId": 3, "name": "데이터베이스", "memo": "데이터의 저장, 조회, 관리", "parentId": null, "orderId": 3 }, + { "nodeId": 4, "name": "DevOps", "memo": "개발과 운영의 통합, 자동화 파이프라인", "parentId": null, "orderId": 4 }, + { "nodeId": 5, "name": "보안", "memo": "웹 애플리케이션 보안 위협과 대응", "parentId": null, "orderId": 5 }, + + { "nodeId": 6, "name": "HTML", "memo": "웹 페이지의 구조와 의미", "parentId": 1, "orderId": 1 }, + { "nodeId": 7, "name": "CSS", "memo": "스타일링과 레이아웃", "parentId": 1, "orderId": 2 }, + { "nodeId": 8, "name": "JavaScript", "memo": "웹의 동작을 담당하는 프로그래밍 언어", "parentId": 1, "orderId": 3 }, + { "nodeId": 9, "name": "React", "memo": "컴포넌트 기반 UI 라이브러리", "parentId": 1, "orderId": 4 }, + { "nodeId": 10, "name": "상태관리", "memo": "클라이언트 데이터의 흐름 제어", "parentId": 1, "orderId": 5 }, + + { "nodeId": 11, "name": "Node.js", "memo": "JS 런타임 기반 서버 플랫폼", "parentId": 2, "orderId": 1 }, + { "nodeId": 12, "name": "Spring Boot", "memo": "Java 기반 엔터프라이즈 백엔드 프레임워크", "parentId": 2, "orderId": 2 }, + { "nodeId": 13, "name": "REST API", "memo": "자원 중심의 HTTP 기반 인터페이스 설계", "parentId": 2, "orderId": 3 }, + { "nodeId": 14, "name": "인증/인가", "memo": "사용자 식별과 권한 제어", "parentId": 2, "orderId": 4 }, + + { "nodeId": 15, "name": "관계형 DB", "memo": "테이블 기반, ACID 보장", "parentId": 3, "orderId": 1 }, + { "nodeId": 16, "name": "NoSQL", "memo": "비정형 데이터에 유연한 DB", "parentId": 3, "orderId": 2 }, + { "nodeId": 17, "name": "ORM", "memo": "객체와 DB 테이블을 매핑하는 기술", "parentId": 3, "orderId": 3 }, + { "nodeId": 18, "name": "캐싱", "memo": "반복 조회 성능 향상을 위한 임시 저장", "parentId": 3, "orderId": 4 }, + + { "nodeId": 19, "name": "Docker", "memo": "컨테이너 기반 애플리케이션 패키징", "parentId": 4, "orderId": 1 }, + { "nodeId": 20, "name": "CI/CD", "memo": "지속적 통합과 배포 자동화", "parentId": 4, "orderId": 2 }, + { "nodeId": 21, "name": "클라우드", "memo": "온디맨드 인프라 서비스", "parentId": 4, "orderId": 3 }, + { "nodeId": 22, "name": "모니터링", "memo": "서비스 상태와 성능 추적", "parentId": 4, "orderId": 4 }, + + { "nodeId": 23, "name": "웹 보안", "memo": "OWASP Top 10 등 주요 취약점", "parentId": 5, "orderId": 1 }, + { "nodeId": 24, "name": "HTTPS/TLS", "memo": "전송 계층 암호화", "parentId": 5, "orderId": 2 }, + { "nodeId": 25, "name": "인증 프로토콜", "memo": "표준 인증/인가 프로토콜", "parentId": 5, "orderId": 3 }, + + { "nodeId": 26, "name": "시맨틱 태그", "memo": "의미 있는 태그로 구조화된 마크업", "parentId": 6, "orderId": 1 }, + { "nodeId": 27, "name": "폼과 입력", "memo": "사용자 입력 수집과 유효성 검사", "parentId": 6, "orderId": 2 }, + { "nodeId": 28, "name": "웹 접근성", "memo": "장애인 포함 모든 사용자를 위한 설계", "parentId": 6, "orderId": 3 }, + + { "nodeId": 29, "name": "박스 모델", "memo": "margin/border/padding/content 구조", "parentId": 7, "orderId": 1 }, + { "nodeId": 30, "name": "Flexbox", "memo": "1차원 유연한 레이아웃", "parentId": 7, "orderId": 2 }, + { "nodeId": 31, "name": "Grid", "memo": "2차원 격자 레이아웃", "parentId": 7, "orderId": 3 }, + { "nodeId": 32, "name": "반응형 디자인", "memo": "미디어 쿼리로 다양한 화면 대응", "parentId": 7, "orderId": 4 }, + { "nodeId": 33, "name": "애니메이션", "memo": "transition, keyframe 기반 동적 효과", "parentId": 7, "orderId": 5 }, + + { "nodeId": 34, "name": "ES6+", "memo": "모던 자바스크립트 문법과 기능", "parentId": 8, "orderId": 1 }, + { "nodeId": 35, "name": "DOM 조작", "memo": "HTML 요소를 JS로 동적 제어", "parentId": 8, "orderId": 2 }, + { "nodeId": 36, "name": "비동기 처리", "memo": "콜백, Promise, async/await", "parentId": 8, "orderId": 3 }, + { "nodeId": 37, "name": "모듈 시스템", "memo": "ESM과 CommonJS 모듈 분리", "parentId": 8, "orderId": 4 }, + + { "nodeId": 38, "name": "컴포넌트", "memo": "UI를 재사용 가능한 단위로 분리", "parentId": 9, "orderId": 1 }, + { "nodeId": 39, "name": "Hook", "memo": "함수형 컴포넌트에서 상태/사이드이펙트 관리","parentId": 9, "orderId": 2 }, + { "nodeId": 40, "name": "라우팅", "memo": "React Router로 SPA 페이지 전환", "parentId": 9, "orderId": 3 }, + { "nodeId": 41, "name": "성능 최적화", "memo": "렌더링 최소화, 코드 분할", "parentId": 9, "orderId": 4 }, + + { "nodeId": 42, "name": "Redux", "memo": "단방향 데이터 흐름의 전역 상태 컨테이너", "parentId": 10, "orderId": 1 }, + { "nodeId": 43, "name": "Recoil", "memo": "atom/selector 기반 React 상태 라이브러리", "parentId": 10, "orderId": 2 }, + { "nodeId": 44, "name": "Context API", "memo": "React 내장 전역 상태 공유 메커니즘", "parentId": 10, "orderId": 3 }, + + { "nodeId": 45, "name": "Express", "memo": "Node.js 경량 웹 프레임워크", "parentId": 11, "orderId": 1 }, + { "nodeId": 46, "name": "미들웨어", "memo": "요청/응답 처리 파이프라인", "parentId": 11, "orderId": 2 }, + { "nodeId": 47, "name": "이벤트 루프", "memo": "Node.js 비동기 처리의 핵심 메커니즘", "parentId": 11, "orderId": 3 }, + + { "nodeId": 48, "name": "IoC/DI", "memo": "제어의 역전과 의존성 주입", "parentId": 12, "orderId": 1 }, + { "nodeId": 49, "name": "JPA", "memo": "Java 표준 ORM 스펙", "parentId": 12, "orderId": 2 }, + { "nodeId": 50, "name": "AOP", "memo": "횡단 관심사를 분리하는 관점 지향 프로그래밍","parentId": 12, "orderId": 3 }, + + { "nodeId": 51, "name": "HTTP 메서드", "memo": "GET/POST/PUT/DELETE/PATCH", "parentId": 13, "orderId": 1 }, + { "nodeId": 52, "name": "상태 코드", "memo": "2xx 성공, 4xx 클라이언트 오류, 5xx 서버 오류","parentId": 13, "orderId": 2 }, + { "nodeId": 53, "name": "API 설계 원칙", "memo": "자원 중심, 명사형 URI, 버전 관리", "parentId": 13, "orderId": 3 }, + + { "nodeId": 54, "name": "JWT", "memo": "서버 무상태 토큰 기반 인증", "parentId": 14, "orderId": 1 }, + { "nodeId": 55, "name": "OAuth 2.0", "memo": "제3자 인가 위임 프로토콜", "parentId": 14, "orderId": 2 }, + { "nodeId": 56, "name": "세션/쿠키", "memo": "서버 저장 방식의 전통적 인증", "parentId": 14, "orderId": 3 }, + + { "nodeId": 57, "name": "SQL", "memo": "관계형 DB 질의 언어", "parentId": 15, "orderId": 1 }, + { "nodeId": 58, "name": "인덱스", "memo": "검색 성능 향상을 위한 자료구조", "parentId": 15, "orderId": 2 }, + { "nodeId": 59, "name": "트랜잭션", "memo": "ACID 속성으로 데이터 일관성 보장", "parentId": 15, "orderId": 3 }, + { "nodeId": 60, "name": "정규화", "memo": "중복 제거와 무결성 유지", "parentId": 15, "orderId": 4 }, + + { "nodeId": 61, "name": "MongoDB", "memo": "문서 기반 NoSQL DB", "parentId": 16, "orderId": 1 }, + { "nodeId": 62, "name": "Redis", "memo": "인메모리 키-값 저장소", "parentId": 16, "orderId": 2 }, + { "nodeId": 63, "name": "Elasticsearch", "memo": "분산 검색 및 분석 엔진", "parentId": 16, "orderId": 3 }, + + { "nodeId": 64, "name": "Hibernate", "memo": "Java 진영 대표 ORM 프레임워크", "parentId": 17, "orderId": 1 }, + { "nodeId": 65, "name": "Sequelize", "memo": "Node.js용 SQL ORM", "parentId": 17, "orderId": 2 }, + + { "nodeId": 66, "name": "캐시 전략", "memo": "Cache-Aside, Write-Through, TTL 설정", "parentId": 18, "orderId": 1 }, + { "nodeId": 67, "name": "CDN", "memo": "정적 자원을 엣지 서버에서 빠르게 제공", "parentId": 18, "orderId": 2 }, + + { "nodeId": 68, "name": "이미지/컨테이너", "memo": "불변 이미지와 실행 중인 컨테이너의 차이", "parentId": 19, "orderId": 1 }, + { "nodeId": 69, "name": "Docker Compose", "memo": "다중 컨테이너 서비스 정의 및 실행", "parentId": 19, "orderId": 2 }, + { "nodeId": 70, "name": "Docker Network", "memo": "컨테이너 간 통신 설정", "parentId": 19, "orderId": 3 }, + + { "nodeId": 71, "name": "GitHub Actions", "memo": "GitHub 내장 CI/CD 워크플로우", "parentId": 20, "orderId": 1 }, + { "nodeId": 72, "name": "Jenkins", "memo": "오픈소스 자동화 서버", "parentId": 20, "orderId": 2 }, + { "nodeId": 73, "name": "배포 전략", "memo": "Blue/Green, Rolling, Canary 배포", "parentId": 20, "orderId": 3 }, + + { "nodeId": 74, "name": "AWS", "memo": "Amazon Web Services 클라우드 플랫폼", "parentId": 21, "orderId": 1 }, + { "nodeId": 75, "name": "GCP", "memo": "Google Cloud Platform", "parentId": 21, "orderId": 2 }, + { "nodeId": 76, "name": "서버리스", "memo": "인프라 관리 없이 함수 단위로 실행", "parentId": 21, "orderId": 3 }, + + { "nodeId": 77, "name": "로깅", "memo": "애플리케이션 이벤트 기록 및 수집", "parentId": 22, "orderId": 1 }, + { "nodeId": 78, "name": "메트릭", "memo": "CPU, 메모리, 응답시간 등 수치 지표", "parentId": 22, "orderId": 2 }, + { "nodeId": 79, "name": "알림", "memo": "임계값 초과 시 온콜 알림 발송", "parentId": 22, "orderId": 3 }, + + { "nodeId": 80, "name": "XSS", "memo": "악성 스크립트 삽입 공격", "parentId": 23, "orderId": 1 }, + { "nodeId": 81, "name": "CSRF", "memo": "사용자 권한으로 위조 요청 전송", "parentId": 23, "orderId": 2 }, + { "nodeId": 82, "name": "SQL Injection", "memo": "악의적 SQL 구문 삽입 공격", "parentId": 23, "orderId": 3 }, + + { "nodeId": 83, "name": "SSL 인증서", "memo": "신뢰 기관이 발급한 공개키 인증서", "parentId": 24, "orderId": 1 }, + { "nodeId": 84, "name": "TLS 핸드셰이크", "memo": "암호화 통신 수립을 위한 협상 과정", "parentId": 24, "orderId": 2 }, + + { "nodeId": 85, "name": "OIDC", "memo": "OAuth 2.0 기반 신원 인증 레이어", "parentId": 25, "orderId": 1 }, + { "nodeId": 86, "name": "SAML", "memo": "기업 SSO에 사용되는 XML 기반 인증 표준", "parentId": 25, "orderId": 2 }, + + { "nodeId": 87, "name": "화살표 함수", "memo": "this 바인딩이 없는 간결한 함수 표현식", "parentId": 34, "orderId": 1 }, + { "nodeId": 88, "name": "구조 분해 할당", "memo": "객체/배열에서 값을 간결하게 추출", "parentId": 34, "orderId": 2 }, + { "nodeId": 89, "name": "Promise/async-await", "memo": "비동기 코드를 동기처럼 작성하는 문법", "parentId": 34, "orderId": 3 }, + + { "nodeId": 90, "name": "useState", "memo": "컴포넌트 내부 상태 선언", "parentId": 39, "orderId": 1 }, + { "nodeId": 91, "name": "useEffect", "memo": "사이드이펙트 처리와 생명주기 대응", "parentId": 39, "orderId": 2 }, + { "nodeId": 92, "name": "useCallback/useMemo", "memo": "불필요한 재계산/재생성 방지", "parentId": 39, "orderId": 3 }, + { "nodeId": 93, "name": "커스텀 Hook", "memo": "반복되는 로직을 Hook으로 추상화", "parentId": 39, "orderId": 4 }, + + { "nodeId": 94, "name": "DDL/DML", "memo": "테이블 정의(DDL)와 데이터 조작(DML)", "parentId": 57, "orderId": 1 }, + { "nodeId": 95, "name": "JOIN", "memo": "여러 테이블을 조건으로 결합", "parentId": 57, "orderId": 2 }, + { "nodeId": 96, "name": "서브쿼리", "memo": "쿼리 안에 중첩된 쿼리", "parentId": 57, "orderId": 3 }, + + { "nodeId": 97, "name": "EC2", "memo": "가상 서버 인스턴스", "parentId": 74, "orderId": 1 }, + { "nodeId": 98, "name": "S3", "memo": "객체 스토리지 서비스", "parentId": 74, "orderId": 2 }, + { "nodeId": 99, "name": "RDS", "memo": "관리형 관계형 DB 서비스", "parentId": 74, "orderId": 3 }, + { "nodeId": 100, "name": "Lambda", "memo": "이벤트 기반 서버리스 함수 실행", "parentId": 74, "orderId": 4 } + ] +} diff --git a/src/main/resources/mocks/chat/tree-small.json b/src/main/resources/mocks/chat/tree-small.json index 58ab721..9cc1db5 100644 --- a/src/main/resources/mocks/chat/tree-small.json +++ b/src/main/resources/mocks/chat/tree-small.json @@ -1,10 +1,10 @@ { - "tree_id": 12, + "treeId": 12, "nodes": [ - { "node_id": 1, "title": "자료구조", "memo": "데이터를 조직하고 저장하는 방법", "parent_id": null, "order_id": 1 }, - { "node_id": 2, "title": "알고리즘", "parent_id": null, "order_id": 2 }, - { "node_id": 3, "title": "배열", "memo": "연속된 메모리 공간", "parent_id": 1, "order_id": 1 }, - { "node_id": 4, "title": "스택", "memo": "LIFO 자료구조", "parent_id": 1, "order_id": 2 }, - { "node_id": 5, "title": "정렬", "parent_id": 2, "order_id": 1 } + { "nodeId": 1, "name": "자료구조", "memo": "데이터를 조직하고 저장하는 방법", "parentId": null, "orderId": 1 }, + { "nodeId": 2, "name": "알고리즘", "parentId": null, "orderId": 2 }, + { "nodeId": 3, "name": "배열", "memo": "연속된 메모리 공간", "parentId": 1, "orderId": 1 }, + { "nodeId": 4, "name": "스택", "memo": "LIFO 자료구조", "parentId": 1, "orderId": 2 }, + { "nodeId": 5, "name": "정렬", "parentId": 2, "orderId": 1 } ] } From 6945d1897bdb2b77ec591f56df440650f7ea304d Mon Sep 17 00:00:00 2001 From: Emithen <86219540+Emithen@users.noreply.github.com> Date: Sun, 14 Jun 2026 23:57:39 +0900 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20mock=20data=20=EC=A0=95=ED=95=A9?= =?UTF-8?q?=EC=84=B1=20=EB=B3=B4=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/mocks/chat/tree-max.json | 259 ++++++++++---------- 1 file changed, 130 insertions(+), 129 deletions(-) diff --git a/src/main/resources/mocks/chat/tree-max.json b/src/main/resources/mocks/chat/tree-max.json index 53f4c34..7d2ca98 100644 --- a/src/main/resources/mocks/chat/tree-max.json +++ b/src/main/resources/mocks/chat/tree-max.json @@ -1,134 +1,135 @@ { "treeId": 55, "nodes": [ - { "nodeId": 1, "name": "프론트엔드", "memo": "사용자와 직접 상호작용하는 클라이언트 영역", "parentId": null, "orderId": 1 }, - { "nodeId": 2, "name": "백엔드", "memo": "서버 측 비즈니스 로직과 데이터 처리", "parentId": null, "orderId": 2 }, - { "nodeId": 3, "name": "데이터베이스", "memo": "데이터의 저장, 조회, 관리", "parentId": null, "orderId": 3 }, - { "nodeId": 4, "name": "DevOps", "memo": "개발과 운영의 통합, 자동화 파이프라인", "parentId": null, "orderId": 4 }, - { "nodeId": 5, "name": "보안", "memo": "웹 애플리케이션 보안 위협과 대응", "parentId": null, "orderId": 5 }, - - { "nodeId": 6, "name": "HTML", "memo": "웹 페이지의 구조와 의미", "parentId": 1, "orderId": 1 }, - { "nodeId": 7, "name": "CSS", "memo": "스타일링과 레이아웃", "parentId": 1, "orderId": 2 }, - { "nodeId": 8, "name": "JavaScript", "memo": "웹의 동작을 담당하는 프로그래밍 언어", "parentId": 1, "orderId": 3 }, - { "nodeId": 9, "name": "React", "memo": "컴포넌트 기반 UI 라이브러리", "parentId": 1, "orderId": 4 }, - { "nodeId": 10, "name": "상태관리", "memo": "클라이언트 데이터의 흐름 제어", "parentId": 1, "orderId": 5 }, - - { "nodeId": 11, "name": "Node.js", "memo": "JS 런타임 기반 서버 플랫폼", "parentId": 2, "orderId": 1 }, - { "nodeId": 12, "name": "Spring Boot", "memo": "Java 기반 엔터프라이즈 백엔드 프레임워크", "parentId": 2, "orderId": 2 }, - { "nodeId": 13, "name": "REST API", "memo": "자원 중심의 HTTP 기반 인터페이스 설계", "parentId": 2, "orderId": 3 }, - { "nodeId": 14, "name": "인증/인가", "memo": "사용자 식별과 권한 제어", "parentId": 2, "orderId": 4 }, - - { "nodeId": 15, "name": "관계형 DB", "memo": "테이블 기반, ACID 보장", "parentId": 3, "orderId": 1 }, - { "nodeId": 16, "name": "NoSQL", "memo": "비정형 데이터에 유연한 DB", "parentId": 3, "orderId": 2 }, - { "nodeId": 17, "name": "ORM", "memo": "객체와 DB 테이블을 매핑하는 기술", "parentId": 3, "orderId": 3 }, - { "nodeId": 18, "name": "캐싱", "memo": "반복 조회 성능 향상을 위한 임시 저장", "parentId": 3, "orderId": 4 }, - - { "nodeId": 19, "name": "Docker", "memo": "컨테이너 기반 애플리케이션 패키징", "parentId": 4, "orderId": 1 }, - { "nodeId": 20, "name": "CI/CD", "memo": "지속적 통합과 배포 자동화", "parentId": 4, "orderId": 2 }, - { "nodeId": 21, "name": "클라우드", "memo": "온디맨드 인프라 서비스", "parentId": 4, "orderId": 3 }, - { "nodeId": 22, "name": "모니터링", "memo": "서비스 상태와 성능 추적", "parentId": 4, "orderId": 4 }, - - { "nodeId": 23, "name": "웹 보안", "memo": "OWASP Top 10 등 주요 취약점", "parentId": 5, "orderId": 1 }, - { "nodeId": 24, "name": "HTTPS/TLS", "memo": "전송 계층 암호화", "parentId": 5, "orderId": 2 }, - { "nodeId": 25, "name": "인증 프로토콜", "memo": "표준 인증/인가 프로토콜", "parentId": 5, "orderId": 3 }, - - { "nodeId": 26, "name": "시맨틱 태그", "memo": "의미 있는 태그로 구조화된 마크업", "parentId": 6, "orderId": 1 }, - { "nodeId": 27, "name": "폼과 입력", "memo": "사용자 입력 수집과 유효성 검사", "parentId": 6, "orderId": 2 }, - { "nodeId": 28, "name": "웹 접근성", "memo": "장애인 포함 모든 사용자를 위한 설계", "parentId": 6, "orderId": 3 }, - - { "nodeId": 29, "name": "박스 모델", "memo": "margin/border/padding/content 구조", "parentId": 7, "orderId": 1 }, - { "nodeId": 30, "name": "Flexbox", "memo": "1차원 유연한 레이아웃", "parentId": 7, "orderId": 2 }, - { "nodeId": 31, "name": "Grid", "memo": "2차원 격자 레이아웃", "parentId": 7, "orderId": 3 }, - { "nodeId": 32, "name": "반응형 디자인", "memo": "미디어 쿼리로 다양한 화면 대응", "parentId": 7, "orderId": 4 }, - { "nodeId": 33, "name": "애니메이션", "memo": "transition, keyframe 기반 동적 효과", "parentId": 7, "orderId": 5 }, - - { "nodeId": 34, "name": "ES6+", "memo": "모던 자바스크립트 문법과 기능", "parentId": 8, "orderId": 1 }, - { "nodeId": 35, "name": "DOM 조작", "memo": "HTML 요소를 JS로 동적 제어", "parentId": 8, "orderId": 2 }, - { "nodeId": 36, "name": "비동기 처리", "memo": "콜백, Promise, async/await", "parentId": 8, "orderId": 3 }, - { "nodeId": 37, "name": "모듈 시스템", "memo": "ESM과 CommonJS 모듈 분리", "parentId": 8, "orderId": 4 }, - - { "nodeId": 38, "name": "컴포넌트", "memo": "UI를 재사용 가능한 단위로 분리", "parentId": 9, "orderId": 1 }, - { "nodeId": 39, "name": "Hook", "memo": "함수형 컴포넌트에서 상태/사이드이펙트 관리","parentId": 9, "orderId": 2 }, - { "nodeId": 40, "name": "라우팅", "memo": "React Router로 SPA 페이지 전환", "parentId": 9, "orderId": 3 }, - { "nodeId": 41, "name": "성능 최적화", "memo": "렌더링 최소화, 코드 분할", "parentId": 9, "orderId": 4 }, - - { "nodeId": 42, "name": "Redux", "memo": "단방향 데이터 흐름의 전역 상태 컨테이너", "parentId": 10, "orderId": 1 }, - { "nodeId": 43, "name": "Recoil", "memo": "atom/selector 기반 React 상태 라이브러리", "parentId": 10, "orderId": 2 }, - { "nodeId": 44, "name": "Context API", "memo": "React 내장 전역 상태 공유 메커니즘", "parentId": 10, "orderId": 3 }, - - { "nodeId": 45, "name": "Express", "memo": "Node.js 경량 웹 프레임워크", "parentId": 11, "orderId": 1 }, - { "nodeId": 46, "name": "미들웨어", "memo": "요청/응답 처리 파이프라인", "parentId": 11, "orderId": 2 }, - { "nodeId": 47, "name": "이벤트 루프", "memo": "Node.js 비동기 처리의 핵심 메커니즘", "parentId": 11, "orderId": 3 }, - - { "nodeId": 48, "name": "IoC/DI", "memo": "제어의 역전과 의존성 주입", "parentId": 12, "orderId": 1 }, - { "nodeId": 49, "name": "JPA", "memo": "Java 표준 ORM 스펙", "parentId": 12, "orderId": 2 }, - { "nodeId": 50, "name": "AOP", "memo": "횡단 관심사를 분리하는 관점 지향 프로그래밍","parentId": 12, "orderId": 3 }, - - { "nodeId": 51, "name": "HTTP 메서드", "memo": "GET/POST/PUT/DELETE/PATCH", "parentId": 13, "orderId": 1 }, - { "nodeId": 52, "name": "상태 코드", "memo": "2xx 성공, 4xx 클라이언트 오류, 5xx 서버 오류","parentId": 13, "orderId": 2 }, - { "nodeId": 53, "name": "API 설계 원칙", "memo": "자원 중심, 명사형 URI, 버전 관리", "parentId": 13, "orderId": 3 }, - - { "nodeId": 54, "name": "JWT", "memo": "서버 무상태 토큰 기반 인증", "parentId": 14, "orderId": 1 }, - { "nodeId": 55, "name": "OAuth 2.0", "memo": "제3자 인가 위임 프로토콜", "parentId": 14, "orderId": 2 }, - { "nodeId": 56, "name": "세션/쿠키", "memo": "서버 저장 방식의 전통적 인증", "parentId": 14, "orderId": 3 }, - - { "nodeId": 57, "name": "SQL", "memo": "관계형 DB 질의 언어", "parentId": 15, "orderId": 1 }, - { "nodeId": 58, "name": "인덱스", "memo": "검색 성능 향상을 위한 자료구조", "parentId": 15, "orderId": 2 }, - { "nodeId": 59, "name": "트랜잭션", "memo": "ACID 속성으로 데이터 일관성 보장", "parentId": 15, "orderId": 3 }, - { "nodeId": 60, "name": "정규화", "memo": "중복 제거와 무결성 유지", "parentId": 15, "orderId": 4 }, - - { "nodeId": 61, "name": "MongoDB", "memo": "문서 기반 NoSQL DB", "parentId": 16, "orderId": 1 }, - { "nodeId": 62, "name": "Redis", "memo": "인메모리 키-값 저장소", "parentId": 16, "orderId": 2 }, - { "nodeId": 63, "name": "Elasticsearch", "memo": "분산 검색 및 분석 엔진", "parentId": 16, "orderId": 3 }, - - { "nodeId": 64, "name": "Hibernate", "memo": "Java 진영 대표 ORM 프레임워크", "parentId": 17, "orderId": 1 }, - { "nodeId": 65, "name": "Sequelize", "memo": "Node.js용 SQL ORM", "parentId": 17, "orderId": 2 }, - - { "nodeId": 66, "name": "캐시 전략", "memo": "Cache-Aside, Write-Through, TTL 설정", "parentId": 18, "orderId": 1 }, - { "nodeId": 67, "name": "CDN", "memo": "정적 자원을 엣지 서버에서 빠르게 제공", "parentId": 18, "orderId": 2 }, - - { "nodeId": 68, "name": "이미지/컨테이너", "memo": "불변 이미지와 실행 중인 컨테이너의 차이", "parentId": 19, "orderId": 1 }, - { "nodeId": 69, "name": "Docker Compose", "memo": "다중 컨테이너 서비스 정의 및 실행", "parentId": 19, "orderId": 2 }, - { "nodeId": 70, "name": "Docker Network", "memo": "컨테이너 간 통신 설정", "parentId": 19, "orderId": 3 }, - - { "nodeId": 71, "name": "GitHub Actions", "memo": "GitHub 내장 CI/CD 워크플로우", "parentId": 20, "orderId": 1 }, - { "nodeId": 72, "name": "Jenkins", "memo": "오픈소스 자동화 서버", "parentId": 20, "orderId": 2 }, - { "nodeId": 73, "name": "배포 전략", "memo": "Blue/Green, Rolling, Canary 배포", "parentId": 20, "orderId": 3 }, - - { "nodeId": 74, "name": "AWS", "memo": "Amazon Web Services 클라우드 플랫폼", "parentId": 21, "orderId": 1 }, - { "nodeId": 75, "name": "GCP", "memo": "Google Cloud Platform", "parentId": 21, "orderId": 2 }, - { "nodeId": 76, "name": "서버리스", "memo": "인프라 관리 없이 함수 단위로 실행", "parentId": 21, "orderId": 3 }, - - { "nodeId": 77, "name": "로깅", "memo": "애플리케이션 이벤트 기록 및 수집", "parentId": 22, "orderId": 1 }, - { "nodeId": 78, "name": "메트릭", "memo": "CPU, 메모리, 응답시간 등 수치 지표", "parentId": 22, "orderId": 2 }, - { "nodeId": 79, "name": "알림", "memo": "임계값 초과 시 온콜 알림 발송", "parentId": 22, "orderId": 3 }, - - { "nodeId": 80, "name": "XSS", "memo": "악성 스크립트 삽입 공격", "parentId": 23, "orderId": 1 }, - { "nodeId": 81, "name": "CSRF", "memo": "사용자 권한으로 위조 요청 전송", "parentId": 23, "orderId": 2 }, - { "nodeId": 82, "name": "SQL Injection", "memo": "악의적 SQL 구문 삽입 공격", "parentId": 23, "orderId": 3 }, - - { "nodeId": 83, "name": "SSL 인증서", "memo": "신뢰 기관이 발급한 공개키 인증서", "parentId": 24, "orderId": 1 }, - { "nodeId": 84, "name": "TLS 핸드셰이크", "memo": "암호화 통신 수립을 위한 협상 과정", "parentId": 24, "orderId": 2 }, - - { "nodeId": 85, "name": "OIDC", "memo": "OAuth 2.0 기반 신원 인증 레이어", "parentId": 25, "orderId": 1 }, - { "nodeId": 86, "name": "SAML", "memo": "기업 SSO에 사용되는 XML 기반 인증 표준", "parentId": 25, "orderId": 2 }, - - { "nodeId": 87, "name": "화살표 함수", "memo": "this 바인딩이 없는 간결한 함수 표현식", "parentId": 34, "orderId": 1 }, - { "nodeId": 88, "name": "구조 분해 할당", "memo": "객체/배열에서 값을 간결하게 추출", "parentId": 34, "orderId": 2 }, - { "nodeId": 89, "name": "Promise/async-await", "memo": "비동기 코드를 동기처럼 작성하는 문법", "parentId": 34, "orderId": 3 }, - - { "nodeId": 90, "name": "useState", "memo": "컴포넌트 내부 상태 선언", "parentId": 39, "orderId": 1 }, - { "nodeId": 91, "name": "useEffect", "memo": "사이드이펙트 처리와 생명주기 대응", "parentId": 39, "orderId": 2 }, - { "nodeId": 92, "name": "useCallback/useMemo", "memo": "불필요한 재계산/재생성 방지", "parentId": 39, "orderId": 3 }, - { "nodeId": 93, "name": "커스텀 Hook", "memo": "반복되는 로직을 Hook으로 추상화", "parentId": 39, "orderId": 4 }, - - { "nodeId": 94, "name": "DDL/DML", "memo": "테이블 정의(DDL)와 데이터 조작(DML)", "parentId": 57, "orderId": 1 }, - { "nodeId": 95, "name": "JOIN", "memo": "여러 테이블을 조건으로 결합", "parentId": 57, "orderId": 2 }, - { "nodeId": 96, "name": "서브쿼리", "memo": "쿼리 안에 중첩된 쿼리", "parentId": 57, "orderId": 3 }, - - { "nodeId": 97, "name": "EC2", "memo": "가상 서버 인스턴스", "parentId": 74, "orderId": 1 }, - { "nodeId": 98, "name": "S3", "memo": "객체 스토리지 서비스", "parentId": 74, "orderId": 2 }, - { "nodeId": 99, "name": "RDS", "memo": "관리형 관계형 DB 서비스", "parentId": 74, "orderId": 3 }, - { "nodeId": 100, "name": "Lambda", "memo": "이벤트 기반 서버리스 함수 실행", "parentId": 74, "orderId": 4 } + { "nodeId": 1, "name": "웹 개발 풀스택", "memo": "프론트엔드부터 백엔드, 인프라, 보안까지 아우르는 전체 영역", "parentId": null, "orderId": 1 }, + + { "nodeId": 2, "name": "프론트엔드", "memo": "사용자와 직접 상호작용하는 클라이언트 영역", "parentId": 1, "orderId": 1 }, + { "nodeId": 3, "name": "백엔드", "memo": "서버 측 비즈니스 로직과 데이터 처리", "parentId": 1, "orderId": 2 }, + { "nodeId": 4, "name": "데이터베이스", "memo": "데이터의 저장, 조회, 관리", "parentId": 1, "orderId": 3 }, + { "nodeId": 5, "name": "DevOps", "memo": "개발과 운영의 통합, 자동화 파이프라인", "parentId": 1, "orderId": 4 }, + { "nodeId": 6, "name": "보안", "memo": "웹 애플리케이션 보안 위협과 대응", "parentId": 1, "orderId": 5 }, + + { "nodeId": 7, "name": "HTML", "memo": "웹 페이지의 구조와 의미", "parentId": 2, "orderId": 1 }, + { "nodeId": 8, "name": "CSS", "memo": "스타일링과 레이아웃", "parentId": 2, "orderId": 2 }, + { "nodeId": 9, "name": "JavaScript", "memo": "웹의 동작을 담당하는 프로그래밍 언어", "parentId": 2, "orderId": 3 }, + { "nodeId": 10, "name": "React", "memo": "컴포넌트 기반 UI 라이브러리", "parentId": 2, "orderId": 4 }, + { "nodeId": 11, "name": "상태관리", "memo": "클라이언트 데이터의 흐름 제어", "parentId": 2, "orderId": 5 }, + + { "nodeId": 12, "name": "Node.js", "memo": "JS 런타임 기반 서버 플랫폼", "parentId": 3, "orderId": 1 }, + { "nodeId": 13, "name": "Spring Boot", "memo": "Java 기반 엔터프라이즈 백엔드 프레임워크", "parentId": 3, "orderId": 2 }, + { "nodeId": 14, "name": "REST API", "memo": "자원 중심의 HTTP 기반 인터페이스 설계", "parentId": 3, "orderId": 3 }, + { "nodeId": 15, "name": "인증/인가", "memo": "사용자 식별과 권한 제어", "parentId": 3, "orderId": 4 }, + + { "nodeId": 16, "name": "관계형 DB", "memo": "테이블 기반, ACID 보장", "parentId": 4, "orderId": 1 }, + { "nodeId": 17, "name": "NoSQL", "memo": "비정형 데이터에 유연한 DB", "parentId": 4, "orderId": 2 }, + { "nodeId": 18, "name": "ORM", "memo": "객체와 DB 테이블을 매핑하는 기술", "parentId": 4, "orderId": 3 }, + { "nodeId": 19, "name": "캐싱", "memo": "반복 조회 성능 향상을 위한 임시 저장", "parentId": 4, "orderId": 4 }, + + { "nodeId": 20, "name": "Docker", "memo": "컨테이너 기반 애플리케이션 패키징", "parentId": 5, "orderId": 1 }, + { "nodeId": 21, "name": "CI/CD", "memo": "지속적 통합과 배포 자동화", "parentId": 5, "orderId": 2 }, + { "nodeId": 22, "name": "클라우드", "memo": "온디맨드 인프라 서비스", "parentId": 5, "orderId": 3 }, + { "nodeId": 23, "name": "모니터링", "memo": "서비스 상태와 성능 추적", "parentId": 5, "orderId": 4 }, + + { "nodeId": 24, "name": "웹 보안", "memo": "OWASP Top 10 등 주요 취약점", "parentId": 6, "orderId": 1 }, + { "nodeId": 25, "name": "HTTPS/TLS", "memo": "전송 계층 암호화", "parentId": 6, "orderId": 2 }, + { "nodeId": 26, "name": "인증 프로토콜", "memo": "표준 인증/인가 프로토콜", "parentId": 6, "orderId": 3 }, + + { "nodeId": 27, "name": "시맨틱 태그", "memo": "의미 있는 태그로 구조화된 마크업", "parentId": 7, "orderId": 1 }, + { "nodeId": 28, "name": "폼과 입력", "memo": "사용자 입력 수집과 유효성 검사", "parentId": 7, "orderId": 2 }, + { "nodeId": 29, "name": "웹 접근성", "memo": "장애인 포함 모든 사용자를 위한 설계", "parentId": 7, "orderId": 3 }, + + { "nodeId": 30, "name": "박스 모델", "memo": "margin/border/padding/content 구조", "parentId": 8, "orderId": 1 }, + { "nodeId": 31, "name": "Flexbox", "memo": "1차원 유연한 레이아웃", "parentId": 8, "orderId": 2 }, + { "nodeId": 32, "name": "Grid", "memo": "2차원 격자 레이아웃", "parentId": 8, "orderId": 3 }, + { "nodeId": 33, "name": "반응형 디자인", "memo": "미디어 쿼리로 다양한 화면 대응", "parentId": 8, "orderId": 4 }, + { "nodeId": 34, "name": "애니메이션", "memo": "transition, keyframe 기반 동적 효과", "parentId": 8, "orderId": 5 }, + + { "nodeId": 35, "name": "ES6+", "memo": "모던 자바스크립트 문법과 기능", "parentId": 9, "orderId": 1 }, + { "nodeId": 36, "name": "DOM 조작", "memo": "HTML 요소를 JS로 동적 제어", "parentId": 9, "orderId": 2 }, + { "nodeId": 37, "name": "비동기 처리", "memo": "콜백, Promise, async/await", "parentId": 9, "orderId": 3 }, + { "nodeId": 38, "name": "모듈 시스템", "memo": "ESM과 CommonJS 모듈 분리", "parentId": 9, "orderId": 4 }, + + { "nodeId": 39, "name": "컴포넌트", "memo": "UI를 재사용 가능한 단위로 분리", "parentId": 10, "orderId": 1 }, + { "nodeId": 40, "name": "Hook", "memo": "함수형 컴포넌트에서 상태/사이드이펙트 관리","parentId": 10, "orderId": 2 }, + { "nodeId": 41, "name": "라우팅", "memo": "React Router로 SPA 페이지 전환", "parentId": 10, "orderId": 3 }, + { "nodeId": 42, "name": "성능 최적화", "memo": "렌더링 최소화, 코드 분할", "parentId": 10, "orderId": 4 }, + + { "nodeId": 43, "name": "Redux", "memo": "단방향 데이터 흐름의 전역 상태 컨테이너", "parentId": 11, "orderId": 1 }, + { "nodeId": 44, "name": "Recoil", "memo": "atom/selector 기반 React 상태 라이브러리", "parentId": 11, "orderId": 2 }, + { "nodeId": 45, "name": "Context API", "memo": "React 내장 전역 상태 공유 메커니즘", "parentId": 11, "orderId": 3 }, + + { "nodeId": 46, "name": "Express", "memo": "Node.js 경량 웹 프레임워크", "parentId": 12, "orderId": 1 }, + { "nodeId": 47, "name": "미들웨어", "memo": "요청/응답 처리 파이프라인", "parentId": 12, "orderId": 2 }, + { "nodeId": 48, "name": "이벤트 루프", "memo": "Node.js 비동기 처리의 핵심 메커니즘", "parentId": 12, "orderId": 3 }, + + { "nodeId": 49, "name": "IoC/DI", "memo": "제어의 역전과 의존성 주입", "parentId": 13, "orderId": 1 }, + { "nodeId": 50, "name": "JPA", "memo": "Java 표준 ORM 스펙", "parentId": 13, "orderId": 2 }, + { "nodeId": 51, "name": "AOP", "memo": "횡단 관심사를 분리하는 관점 지향 프로그래밍","parentId": 13, "orderId": 3 }, + + { "nodeId": 52, "name": "HTTP 메서드", "memo": "GET/POST/PUT/DELETE/PATCH", "parentId": 14, "orderId": 1 }, + { "nodeId": 53, "name": "상태 코드", "memo": "2xx 성공, 4xx 클라이언트 오류, 5xx 서버 오류","parentId": 14, "orderId": 2 }, + { "nodeId": 54, "name": "API 설계 원칙", "memo": "자원 중심, 명사형 URI, 버전 관리", "parentId": 14, "orderId": 3 }, + + { "nodeId": 55, "name": "JWT", "memo": "서버 무상태 토큰 기반 인증", "parentId": 15, "orderId": 1 }, + { "nodeId": 56, "name": "OAuth 2.0", "memo": "제3자 인가 위임 프로토콜", "parentId": 15, "orderId": 2 }, + { "nodeId": 57, "name": "세션/쿠키", "memo": "서버 저장 방식의 전통적 인증", "parentId": 15, "orderId": 3 }, + + { "nodeId": 58, "name": "SQL", "memo": "관계형 DB 질의 언어", "parentId": 16, "orderId": 1 }, + { "nodeId": 59, "name": "인덱스", "memo": "검색 성능 향상을 위한 자료구조", "parentId": 16, "orderId": 2 }, + { "nodeId": 60, "name": "트랜잭션", "memo": "ACID 속성으로 데이터 일관성 보장", "parentId": 16, "orderId": 3 }, + { "nodeId": 61, "name": "정규화", "memo": "중복 제거와 무결성 유지", "parentId": 16, "orderId": 4 }, + + { "nodeId": 62, "name": "MongoDB", "memo": "문서 기반 NoSQL DB", "parentId": 17, "orderId": 1 }, + { "nodeId": 63, "name": "Redis", "memo": "인메모리 키-값 저장소", "parentId": 17, "orderId": 2 }, + { "nodeId": 64, "name": "Elasticsearch", "memo": "분산 검색 및 분석 엔진", "parentId": 17, "orderId": 3 }, + + { "nodeId": 65, "name": "Hibernate", "memo": "Java 진영 대표 ORM 프레임워크", "parentId": 18, "orderId": 1 }, + { "nodeId": 66, "name": "Sequelize", "memo": "Node.js용 SQL ORM", "parentId": 18, "orderId": 2 }, + + { "nodeId": 67, "name": "캐시 전략", "memo": "Cache-Aside, Write-Through, TTL 설정", "parentId": 19, "orderId": 1 }, + { "nodeId": 68, "name": "CDN", "memo": "정적 자원을 엣지 서버에서 빠르게 제공", "parentId": 19, "orderId": 2 }, + + { "nodeId": 69, "name": "이미지/컨테이너", "memo": "불변 이미지와 실행 중인 컨테이너의 차이", "parentId": 20, "orderId": 1 }, + { "nodeId": 70, "name": "Docker Compose", "memo": "다중 컨테이너 서비스 정의 및 실행", "parentId": 20, "orderId": 2 }, + { "nodeId": 71, "name": "Docker Network", "memo": "컨테이너 간 통신 설정", "parentId": 20, "orderId": 3 }, + + { "nodeId": 72, "name": "GitHub Actions", "memo": "GitHub 내장 CI/CD 워크플로우", "parentId": 21, "orderId": 1 }, + { "nodeId": 73, "name": "Jenkins", "memo": "오픈소스 자동화 서버", "parentId": 21, "orderId": 2 }, + { "nodeId": 74, "name": "배포 전략", "memo": "Blue/Green, Rolling, Canary 배포", "parentId": 21, "orderId": 3 }, + + { "nodeId": 75, "name": "AWS", "memo": "Amazon Web Services 클라우드 플랫폼", "parentId": 22, "orderId": 1 }, + { "nodeId": 76, "name": "GCP", "memo": "Google Cloud Platform", "parentId": 22, "orderId": 2 }, + { "nodeId": 77, "name": "서버리스", "memo": "인프라 관리 없이 함수 단위로 실행", "parentId": 22, "orderId": 3 }, + + { "nodeId": 78, "name": "로깅", "memo": "애플리케이션 이벤트 기록 및 수집", "parentId": 23, "orderId": 1 }, + { "nodeId": 79, "name": "메트릭", "memo": "CPU, 메모리, 응답시간 등 수치 지표", "parentId": 23, "orderId": 2 }, + { "nodeId": 80, "name": "알림", "memo": "임계값 초과 시 온콜 알림 발송", "parentId": 23, "orderId": 3 }, + + { "nodeId": 81, "name": "XSS", "memo": "악성 스크립트 삽입 공격", "parentId": 24, "orderId": 1 }, + { "nodeId": 82, "name": "CSRF", "memo": "사용자 권한으로 위조 요청 전송", "parentId": 24, "orderId": 2 }, + { "nodeId": 83, "name": "SQL Injection", "memo": "악의적 SQL 구문 삽입 공격", "parentId": 24, "orderId": 3 }, + + { "nodeId": 84, "name": "SSL 인증서", "memo": "신뢰 기관이 발급한 공개키 인증서", "parentId": 25, "orderId": 1 }, + { "nodeId": 85, "name": "TLS 핸드셰이크", "memo": "암호화 통신 수립을 위한 협상 과정", "parentId": 25, "orderId": 2 }, + + { "nodeId": 86, "name": "OIDC", "memo": "OAuth 2.0 기반 신원 인증 레이어", "parentId": 26, "orderId": 1 }, + { "nodeId": 87, "name": "SAML", "memo": "기업 SSO에 사용되는 XML 기반 인증 표준", "parentId": 26, "orderId": 2 }, + + { "nodeId": 88, "name": "화살표 함수", "memo": "this 바인딩이 없는 간결한 함수 표현식", "parentId": 35, "orderId": 1 }, + { "nodeId": 89, "name": "구조 분해 할당", "memo": "객체/배열에서 값을 간결하게 추출", "parentId": 35, "orderId": 2 }, + { "nodeId": 90, "name": "Promise/async-await", "memo": "비동기 코드를 동기처럼 작성하는 문법", "parentId": 35, "orderId": 3 }, + + { "nodeId": 91, "name": "useState", "memo": "컴포넌트 내부 상태 선언", "parentId": 40, "orderId": 1 }, + { "nodeId": 92, "name": "useEffect", "memo": "사이드이펙트 처리와 생명주기 대응", "parentId": 40, "orderId": 2 }, + { "nodeId": 93, "name": "useCallback/useMemo", "memo": "불필요한 재계산/재생성 방지", "parentId": 40, "orderId": 3 }, + { "nodeId": 94, "name": "커스텀 Hook", "memo": "반복되는 로직을 Hook으로 추상화", "parentId": 40, "orderId": 4 }, + + { "nodeId": 95, "name": "DDL/DML", "memo": "테이블 정의(DDL)와 데이터 조작(DML)", "parentId": 58, "orderId": 1 }, + { "nodeId": 96, "name": "JOIN", "memo": "여러 테이블을 조건으로 결합", "parentId": 58, "orderId": 2 }, + { "nodeId": 97, "name": "서브쿼리", "memo": "쿼리 안에 중첩된 쿼리", "parentId": 58, "orderId": 3 }, + + { "nodeId": 98, "name": "EC2", "memo": "가상 서버 인스턴스", "parentId": 75, "orderId": 1 }, + { "nodeId": 99, "name": "S3", "memo": "객체 스토리지 서비스", "parentId": 75, "orderId": 2 }, + { "nodeId": 100, "name": "RDS", "memo": "관리형 관계형 DB 서비스", "parentId": 75, "orderId": 3 } ] }