상세 컨텐츠

본문 제목

React(리액트) 티키타카 33 SVAR Gantt(업그레이드)

React

by e7e 2025. 11. 3. 12:31

본문

드디어 svar gantt가  쓸만하게 업그레이드 되었당. 

(패키지이름도  wx-react-gantt에서 @svar-ui/react-gantt로 살짜기 바뀌었당)

 

대부분의 간트차트가  유료인 어쩔수 없는 상황에서 svar gantt는  나름 유일한 대안이었지만

가이드 문서부터 실제 실행되는 모습, 리액트 버젼 지원까지  디테일하게 따지자면...

문제가 한 두가지가 아니었지만... 이제는 사용해 볼만하당.

(제대로 안된 문서를 읽고 버린 시간에 미쳐버린 천둥 눈물이 썰물로 빠진당.)

[결코 완벽하다는 이야기는  결코 아니당. 비 바람 번개는 여전히 하늘에 산당]

 

아래 링크에 가면 열심히 설명한당.

https://docs.svar.dev/react/gantt/getting_started/

 

바로 감정 들어가 보장.

당근 먼저 vite로 React/Javascript 프로젝트를 아무 빈 폴더에 셋업한당.

npx create-vite@latest .                                     

 

추가로  설치하장

npm i @svar-ui/react-gantt    ## SVAR React Gantt
npm i axios

 

대략 필요없는 파일은 나름 정리하고 App.jsx를 아래처럼 바꿔보장

 

App,jsx

import { Gantt, WillowDark } from "@svar-ui/react-gantt";
import "@svar-ui/react-gantt/all.css";

function App() {

  return (
    <>
      <h1>
        SVAR GANTT 이제는 쓸만하당
      </h1>
      <WillowDark>
        <Gantt />
      </WillowDark>
    </>
  );
}

export default App;

실행 화면을 확인하면 당연 데이터 없는 Gantt가 눈에 보인당.

WillowDark는 제공되는 테마당. Willow랑 2개가 제공되는데 

당근 Dark가 붙었으니가 어두운 테마, 안 붙은 건 밝은 테마당

 

여기서 나는 왈칵 생각이 난당.

긴꼬리 꼬장꼬장 꼰대 설명보다는 바로 가져다 쓸 수 있는 베이스 샘플이

이 시대가 원하는 옳고 그름을 떠난  바램을 담은 바람임을.......

 

먼저  화면이 영어로 나오는 부분을 한글로 나오도록(localizaion) 위해

아래   ko.js파일을 src 폴더에 맹글장. (귀찮으면 다운받는당)

ko.js
0.00MB

 

ko.js

const ko = {
  //calendar
  calendar: {
    monthFull: [
      " 1월",
      " 2월",
      " 3월",
      " 4월",
      " 5월",
      " 6월",
      " 7월",
      " 8월",
      " 9월",
      "10월",
      "11월",
      "12월",
    ],
    monthShort: [
      " 1월",
      " 2월",
      " 3월",
      " 4월",
      " 5월",
      " 6월",
      " 7월",
      " 8월",
      " 9월",
      "10월",
      "11월",
      "12월",
    ],

    dayFull: [
      "일요일",
      "월요일",
      "화요일",
      "수요일",
      "목요일",
      "금요일",
      "토요일",
    ],

    dayShort: [
      "일요일",
      "월요일",
      "화요일",
      "수요일",
      "목요일",
      "금요일",
      "토요일",
    ],
    hours: "시",
    minutes: "분",
    done: "완료",
    clear: "클리어",
    today: "오늘",
    am: ["오전", "오전"],
    pm: ["오후", "오후"],

    weekStart: 7,
    clockFormat: 24,
  },

  //core
  core: {
    ok: "확인",
    cancel: "취소",
    select: "선택",
    "No data": "데어터 없음",
  },

  formats: {
    dateFormat: "%Y-%m-%d",
    timeFormat: "%H:%i",
  },

  lang: "ko-KR",

  //Gantt
  gantt: {
    // Header / sidebar
    "Task name": "작업명",
    "Start date": "시작일",
    Duration: "기간",
    Task: "작업",
    Milestone: "이정표",
    "Summary task": "작업 써머리",

    // Sidebar
    Save: "저장",
    Delete: "삭제",
    Name: "이름",
    Description: "설명",
    "Select type": "타입 선택",
    Type: "타입",
    "End date": "종료일",
    Progress: "진행율",
    Predecessors: "이전 작업",
    Successors: "이후 작업",
    "Add task name": "작업명 추가",
    "Add description": "설명 추가",
    "Select link type": "링크 타입 선택",
    "End-to-start": "끝과 시작",
    "Start-to-start": "시작과 시작",
    "End-to-end": "끝과 끝",
    "Start-to-end": "시작과 끝",

    // Context menu / toolbar
    Add: "추가",
    "Child task": "하위..",
    "Task above": "위에..",
    "Task below": "아래..",
    "Convert to": "변환 to",
    Edit: "수정",
    Cut: "잘라내기",
    Copy: "복사",
    Paste: "붙여넣기",
    Move: "이동",
    Up: "위로",
    Down: "아래로",
    Indent: "안으로",
    Outdent: "밖으로",
    "Split task": "작업 분리",

    // Toolbar
    "New task": "새 작업",
    "Move up": "위로 이동",
    "Move down": "아래도 이동",
  },
};

export default ko;

 

실행 확인을 위한 더미 데이터도 아래 처럼  미리 맹그러 두도록 하장

(역시 귀찮다면 다운받아서 src 폴더에 버려버리장.)

dummyData.js
0.00MB

 

dummyData.js

// 작업
export const tasks = [
  {
    id: 20,
    text: "회의록 작성",
    start: "2025-11-11",
    end: "2025-11-12",
    duration: 1,
    progress: 0,
    type: "task",
  },
  {
    id: 47,
    text: "REACT 프로젝트",
    start: "2025-11-01",
    end: "2025-11-20",
    duration: 20,
    progress: 5,
    parent: 0,
    type: "summary",
    open: true,
  },
  {
    id: 22,
    text: "라우터/레이아웃 설정",
    start: "2025-11-03",
    end: "2025-11-07",
    duration: 5,
    progress: 30,
    parent: 47,
    type: "task",

  },
  {
    id: 21,
    text: "신규 프로젝트 설계",
    start: "2025-12-10",
    end: "2025-12-13",
    duration: 3,
    progress: 0,
    type: "task",
  },
  {
    id: 31,
    text: "금수저 프로젝트",
    start: "2025-12-20",
    end: "2025-12-30",
    duration: 3,
    progress: 0,
    type: "task",
  },

];
// 앞뒤 연결  e2e는 end to end의 의미
export const links = [{ id: 1, source: 20, target: 21, type: "e2e" }];
// 시간 스케일
export const scales = [
  { unit: "month", step: 1, format: "yyyy-MM" },
  { unit: "day", step: 1, format: "d" },
];

export const markers = [
  {
    start: new Date().setDate(new Date().getDate() + 2),
    text: "모레",
  },
  {
    start: new Date().setDate(new Date().getDate() + 7),
    text: "7일후",
  },
];

 

대략 준비가 되었으니, 핵심 바로 가져다 쓸 Base 샘플 코드를 맹글어보장

BaseGantt.jsx
0.00MB

 

BaseGantt.jsx

import { Locale } from "@svar-ui/react-core";
import "@svar-ui/react-gantt/all.css";
import {
  ContextMenu,
  Editor,
  Fullscreen,
  Gantt,
  Toolbar,
  Tooltip,
  WillowDark,
} from "@svar-ui/react-gantt";
import ko from "./ko";
import { tasks, links, scales, markers } from "./dummyData";
import { useState } from "react";

function BaseGantt() {
  const [api, setApi] = useState(null);

  const init = (api) => {
    setApi(api);
  };

  return (
    <>
      <ContextMenu api={api}>
        <Fullscreen hotkey="ctrl+shift+f">
          <WillowDark>
            <Locale words={{ ...ko }}>
              <Tooltip api={api} />
              <Toolbar api={api} />
              <Gantt
                tasks={tasks}
                scales={scales}
                links={links}
                markers={markers}
                zoom
                init={init}
              />
              {api && <Editor api={api} />}
            </Locale>
          </WillowDark>
        </Fullscreen>
      </ContextMenu>
    </>
  );
}

export default BaseGantt;

사실 이 소스에 svar gantt가 제공하는 기본 컴포넌트 구조가 모두 담겨있다고 봐도 괜찮을 거당.

 

ContextMenu 컴포넌트로 Gantt를 둘러싸면 마우스 오른쪽 컨텍스가 제공되고

Fullscreen 컴포넌트로 둘러싸면 화면에  Fullscreen 전환 버튼이 나타나고

Toollbar로 둘러싸면 Gantt 위에 툴바가 나타나고

Tooltip을 넣으면 tooltip이 지원되공

Locale로 둘러싸면 localization이 되는 식이다.

프론트 프레임워크에서 바라는 컴포넌트 구조화가 잘 되어있는 모습이당. 

[만약 속성으로 처리했으면 어땠을까?, 결단코 분명 장단점이 있을게당] 

 

App.jsx

import BaseGantt from "./BaseGantt";

function App() {

  return (
    <>
      <h1 style={titleStyle}>
        그냥 여기서 띠작할께용
      </h1>
      <BaseGantt />
    </>
  );
}

// 그냥 스타일 정의 객체
const titleStyle = {
  textAlign: "center",
  backgroundColor: "blueviolet",
  color: "white",
  marginBottom: 0,
}

export default App;

 

여기까지 했다면 아래 화면이 음.. 하고 보일게당.

 

새작업 버튼을 누르면 New Task가 추가되고 그걸 더블클릭하거낭

작업중에 하나를 선택하고 더블 클릭한다면 아래처럼 보일게당.

 

작업중 하나를 선택하고 마우스 오른쪽 버튼을 누른다면 아래처럼 보일게당.

 

Restful 테스트를 해보기 위해 아래 json-server를 구성한 폴더 압축 파일을 다운받자

json-gantt.zip
0.01MB

 

압축을 풀고  vscode로 폴더를 열어 터미널에 npm start라 치면 그냥 동작한당.

터미널 메세지를 잘 보면 그냥 안당.

 

아래 파일은 axios를 이용하여 위 json-server에서 데이터를 가져와서

gantt 를그리는 샘플 소스를 포함하고 있다.  

mk-gantt.zip
0.04MB

 

압축 풀고, vscode로 열어서 npm i  후 npm run dev 하면 볼 수 있당.

 

실행 확인해 보면  작업(task)에 대해서만 추가/수정/삭제 가 잘 동작함을 

확인할 수 있고, 스타일도 살짝 넣었당(gantt.css 파일 참조).

나머진(link 등등) 아직 하지 않았당.

조금 지저분한 코드들이 들어가버리고 말았는데..(ㅠㅠ)

JSON 서버는 id 속성을 무조건 문자열 처리해 버리고,

SVAR GANTT는 문서에는 id가 number | string 으로 되어 있지만

실제 number로 넘겨주지 않으면 에러가 발생하여 땜방이당.

Spring등으로 실제 Back-End를 구축한다면 간단히 해결될 문제당.

 

개인적인 결론은 svar gantt가 위와 같은 기본 기능이 다 장착되어 있는

베이스 샘플을 제공해 주었으면 하는 마음이당. 현재의 문서 설명은

사용자의 시간의 가치를 엄청나게 저 평가하여 버리고 있당.

 

Slider의 동작은 마구 이상한데... 그 원인을 내가 찾고 말았당.

controlled Component 방식으로 사용한 것이 원인이다.

uncontrolled 방식으로 사용하면  깔끔하게 해결된당.

 

아래 코드를  기존 api.intercept가 나열된 소스 뒤에 추가 하면 된당.

(역시 흐름을 생각하니, 해결책이 보인당. 마구 기쁘당!~~ ㅋㅋ)

    api.intercept("scroll-chart", (e) => {
      console.log("check e", e);
      return false;  // 뒤에 따라 오는 처리를 하지 않겠음
    });

 


하늘색 종이 위에  살금살금 소리없는 흰구름을 그리고

바다색 종이 위에  웅성웅성 소리높은 흰파도를 그린다.

 

흰 파도야 넌 언제 니 얘기 멈출거야?

흰 구름아 넌 또 언제  니 얘기 할거닝?

 

흰 구름은 먹구름 되어 천둥으로 호통치고

흰 파도는 지지않고 더 높여 울음소리 내달린다.

 

둘은 친구가 될 수 있을까?

이런!  둘 다 내 안에 살고 있었다.

 

https://www.youtube.com/watch?v=KNtJGQkC-WI

'React' 카테고리의 다른 글

React Spinner(react-loader-spinner)  (8) 2025.11.07
React(리액트) 티키타카 18 ( rc-tree 트리 컴포넌트)  (2) 2025.11.04
React With TypeScript 체킁1  (2) 2025.10.21
템플릿  (6) 2025.06.27
React(리액트) 티키타카 37 (Route 이해)  (4) 2025.05.16

관련글 더보기