개발하는 고양이 오이

8. [React] React로 FullCalendar 사용4 - mssql 데이터 값 calendar에 보이기 (Fullcalendar에 Events 띄우기) 본문

React/FullCalendar

8. [React] React로 FullCalendar 사용4 - mssql 데이터 값 calendar에 보이기 (Fullcalendar에 Events 띄우기)

Cucum 2022. 10. 27. 09:51

★ FullCalendar 목차

https://dhdl-it.tistory.com/category/React/FullCalendar

 

'React/FullCalendar' 카테고리의 글 목록

고양이 오이와 함께 살고있는 초보 개발자입니다.

dhdl-it.tistory.com


안녕하세요. 지난번에 React에서 Node.js를 이용하여 Mssql을 연동했다면,

 

 [React] - 6. [React] Node.js - MSSQL연동 + Setting the TLS ServerName to an IP address is not permitted by RFC 6066 오류 해결

 

6. [React] Node.js - MSSQL연동 + Setting the TLS ServerName to an IP address is not permitted by RFC 6066 오류 해결

안녕하세요. 구글링을 하다보면, React에서 Node.js를 이용하여 Mysql연동은 많이 봤으나, Mssql연동 방법에 대해서는 많지 않아서 공유하고자 올립니다. 우선, React는 클라이언트 사이드로, Mssql와 연

dhdl-it.tistory.com

 

오늘은 연동된 데이터를 fullcalendar에 보여지도록 하는 부분을 공유하고자 올립니다.

 

최종 결과물)

결과

 

① Axios 라이브러리 설치

▶ Axios는 브라우저, Node.js를 위한 Promise API를 활용하는 HTTP 비동기 통신 라이브러리 입니다.

▶ 쉽게 말해, 백엔드(Node.js)와 프론트엔드(React)와의 통신을 쉽게하기 위해 Ajax와 더불어 사용합니다.

▶ 이미 자바스크립트에는 fetch api가 있지만, 프레임워크에서 ajax를 구현할 땐, axios를 쓰는 편이라고 보면 됩니다.

 

설치

npm install axios

 

 ② Back-End(Mssql)에서 JSON 정보 전달하기

(Mssql연동은 상단의 게시물 참고)

mssql 테이블 명 : tblTest

 

■ server.js

 - JSON정보 전달

// main - FullCalendar 화면
app.get('/main', function (req, res) {
    var conn = new mssql.ConnectionPool(dbConfig_user);

    conn.connect().then(function () {
        var req = new mssql.Request(conn);
        
        req.query(`SELECT id, UserName as title, UserType, StartDate as date
                    FROM tblTest 
                    ORDER BY StartDate, UserName`).then(function (events) {
            console.log('req: ', events.recordset);
            conn.close();
            res.json(events.recordset);
        })
        .catch(function (err) {
            console.log('err: ', err);
            conn.close();
            res.json(err);
        });
    })
    .catch(function (err) {
        console.log('err: ', err);
        res.json(err);
    });
});

/main이라는 url에 get 요청이 들어오면, DB 내의 tblTest 테이블에 대한 정보를 res.json을 통해 응답하였습니다.

 

 

이때, sql 쿼리문에서 UserName에 title이라는 이름과, StartDate에 date라는 이름을 준 이유는 다음과 같습니다.

React로 fullcalendar를 사용하기 첫번째 게시물에서([React/FullCalendar] - 2. [React] React로 FullCalendar 사용1 - 기본),

events들을 직접 넣어줬을 때 title이라는 곳에 일정 이름을, date라는 곳에 날짜를 작성했었습니다.

React로 fullcalendar를 사용하기 첫번째 게시물

 

React로 fullcalendar를 사용하기 첫번째 게시물

 

이와 같이, db에서 데이터를 받아올 때 title과 date라는 이름으로 받아와야 fullcalendar에 표시 될 것이라 생각하여

sql 쿼리문을 작성하였습니다.

 

 

③ React에서 JSON 정보 받기1

Back-End에서 받은 정보를 받기 위해서는, 일단 React를 Back-End 서버의 proxy 서버로 설정해야 합니다.

React 프로젝트 내의 package.json에 다음과 같은 내용을 추가해줍니다.

"proxy": "http://localhost:8088",

(8088 : 각자 Back-End 서버의 포트번호를 알맞게 수정해서 적어주시면 됩니다.)

server/server.js의 port번호 : 8088
package.json

위의 내용을 package.json에 추가해주지 않으면, 아래와 같은 오류가 발생합니다.

(AxiosError: Request faild with status code 404)

 

 

④ React에서 JSON 정보 받기2

fullcalendar 화면을 만들어 둔 MyCalendar.js에서, Back-End에서 보낸 데이터를 받아보겠습니다.

import React, { Component } from 'react';
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';

import axios from 'axios';

class MyCalendar extends Component {
    state = {}

    // 아래의 모든 과정은 componentDidMount에 의해, 컴포넌트가 만들어지고 첫 렌더링을 모두 끝낸 후 실행됨
    componentDidMount() {
        this._getEvents();
    }

    // _axiosEvents이 응답을 받을때까지 기다리고, 응답을 받는다면 setState 메소드를 호출하여 state 값에 events라는 데이터를 넣어줌
    _getEvents = async () => {
        const events = await this._axiosEvents();
            this.setState({
                events
        })
    }

    // axios의 get 메소드를 통해 Back-End의 '/main' url에 정보를 요청하고, 그에 따른 res.data 응답 리턴
    _axiosEvents = async () => {
        return axios.get('/main')
                    .then(res => res.data);                  
    }
    
    render() {
      let { events } = this.state;      

        return (
          <div className="calendar">
                { events ? 
                    <FullCalendar 
                        defaultView="dayGridMonth" 
                        plugins={[ dayGridPlugin ]}

                        select={ this.handleDateSelect }
                        events={ this.state.events } 
                    /> :
                    'loading...'
                }
            </div>
        );
    }
}
export default MyCalendar;

(해당 코드는 구글링을 통해 찾은 게시물을 이용해 작성했으며, 해당 게시물은 출처로 남기겠습니다.)

 

위와 같이 작성 한 후에, 2개의 터미널 창을 띄운 후에, 아래의 명령어를 각각 입력해줍니다.

node server/server.js
npm start

node server/server.js 입력 후 다음과 같이 db 내용이 뜬다면 성공!
fullcalendar 화면에 해당 데이터 값이 들어가면 성공!

 

⑤ 시작날짜와 종료날짜가 다른 경우

이때, 저의 DB를 살펴보면, 시작날짜와 종료날짜가 다른 경우가 있는데 위의 결과물은 하루만 나오게 되었습니다.

mssql

 

이 또한 위에서 말씀드린 title, date와 연관이 있는데요

구글링을 통해 찾아본 결과, fullcalendar에서는 title, date 외에도 start, end, color 등 다양하게 존재함을 알 수 있었습니다.

그렇다면, server.js에서 작성한 쿼리문을 다음과 같이 변경해보겠습니다.

SELECT id, UserName as title, UserType, StartDate as start, EndDate as [end]
FROM tblTest 
ORDER BY StartDate, UserName

(이때, [end]라 한 이유는, 아래와 같이 end 키워드에 오류가 생기기 때문입니다.)

 

▷ node server/server.js를 실행한 터미널을 Ctrl+z 로 종료시킨 후, 재실행해줍니다.

언뜻 보면, 성공한 것 같이 보이나, 자세히 보면 B의 데이터 값과 C의 데이터 값이 이상함을 알 수 있습니다.

B는 27일부터 29일까지이며, C는 28일부터 29일까지인데 end 값이 하루씩 줄어들었음을 알 수 있습니다.

 

 

이 점을 감안하여, 하루를 더해주는 DATEADD 함수를 이용하여 다시 쿼리문을 수정해보겠습니다.

SELECT id, UserName as title, UserType, StartDate as start, DATEADD(DAY, 1, EndDate) as [end]
FROM tblTest 
ORDER BY StartDate, UserName

 

쿼리문에서 단순히 DATEADD함수를 통해 하루만 더해주게 된다면,

위의 사진과 같이 end값에 시간까지 출력되는 datetime 형식으로 변경되기 때문에, 다시 CONVERT 함수를 통해 varchar 형식으로 변경이 필요합니다.

SELECT id, UserName as title, UserType, StartDate as start, CONVERT(CHAR(10),DATEADD(DAY, 1, EndDate),23) as [end]
FROM tblTest 
ORDER BY StartDate, UserName

 

▷ node server/server.js를 실행한 터미널을 Ctrl+z 로 종료시킨 후, 재실행해줍니다.

결과

 

위의 과정을 모두 거치면 최종적으로 원하는 결과가 나왔음을 알 수 있습니다.

감사합니다.

 

☆ 전체 코드 ☆

server/server.js

const express = require('express');

const app = express();
app.listen(8088, function () {
    console.log('listening on 8088')
});

// mssql 연동
var mssql = require("mssql");
var dbConfig_user = {
    server: "",
    database: "",
    user: "",
    password: "",
    port: ,
    options: {      // DeprecationWarning: Setting the TLS ServerName to an IP address is not permitted by RFC 6066. This will be ignored in a future version. 오류 해결
        encrypt: false,
        trustServerCertificate: true,
    }  
};

mssql.connect(dbConfig_user, function(err){
    if(err){
        return console.error('error : ', err);
    }
    console.log('MSSQL 연결 완료')
});

// main - FullCalendar 화면
app.get('/main', function (req, res) {
    var conn = new mssql.ConnectionPool(dbConfig_user);

    conn.connect().then(function () {
        var req = new mssql.Request(conn);
        
        // EndDate에 +1 을 해줘야, fullCalendar에 제대로 보임. 
        // 그러나 varchar 형식이기 때문에 DATEADD 함수를 이용하여 하루를 더해주면 datetime 형식으로 변경되기에, 다시 CONVERT 함수 이용해서 varchar 형식으로 변경
        req.query(`SELECT id, UserName as title, UserType, StartDate as start, CONVERT(CHAR(10),DATEADD(DAY, 1, EndDate),23) as [end]
                    FROM tblTest 
                    ORDER BY StartDate, UserName`).then(function (events) {
            console.log('req: ', events.recordset);
            conn.close();
            res.json(events.recordset);
        })
        .catch(function (err) {
            console.log('err: ', err);
            conn.close();
            res.json(err);
        });
    })
    .catch(function (err) {
        console.log('err: ', err);
        res.json(err);
    });
});

 

MyCalendar.js

import React, { Component } from 'react';
import FullCalendar from '@fullcalendar/react';
import dayGridPlugin from '@fullcalendar/daygrid';

import axios from 'axios';

class MyCalendar extends Component {
    state = {}

    // 아래의 모든 과정은 componentDidMount에 의해, 컴포넌트가 만들어지고 첫 렌더링을 모두 끝낸 후 실행됨
    componentDidMount() {
        this._getEvents();
    }

    // _axiosEvents이 응답을 받을때까지 기다리고, 응답을 받는다면 setState 메소드를 호출하여 state 값에 events라는 데이터를 넣어줌
    _getEvents = async () => {
        const events = await this._axiosEvents();
            this.setState({
                events
        })
    }

    // axios의 get 메소드를 통해 Back-End의 '/main' url에 정보를 요청하고, 그에 따른 res.data 응답 리턴
    _axiosEvents = async () => {
        return axios.get('/main')
                    .then(res => res.data);                  
    }
    
    render() {
      let { events } = this.state;      

        return (
          <div className="calendar">
                { events ? 
                    <FullCalendar 
                        defaultView="dayGridMonth" 
                        plugins={[ dayGridPlugin ]}
                        select={ this.handleDateSelect }
                        events={ this.state.events }            
                    /> :
                    'loading...'
                }
            </div>
        );
    }
}
export default MyCalendar;

 

출처 및 참고한 게시물

https://yuhodots.github.io/frontend/19-08-28-2/

 

React로 FullCalendar Events 띄우기

 

yuhodots.github.io