[3] CRUD 게시판 프로젝트 - React CRUD 구성

2023. 7. 12. 00:10Github 프로젝트/게시판프로젝트

728x90
반응형
SMALL

Github 저장소 :https://github.com/BerkleyLim/project_board

 

GitHub - BerkleyLim/project_board: Spring Boot + React CRUD형 게시판 만들기 프로젝트 안내서

Spring Boot + React CRUD형 게시판 만들기 프로젝트 안내서. Contribute to BerkleyLim/project_board development by creating an account on GitHub.

github.com

 

개발 환경은

Front : React 기반

Back-End : Spring Boot 기반

DB : My-SQL 기반

 

Nodejs 및 npm 패키지 / java와 maven 이 미리 설치를 한 상태로 먼저 환경 설정을 셋팅을 한다.

 

 

이번 시간에는  immutablilty-helper 라는 불가변성 라이브러리를 사용하여 state 값 일부만 변동하고,

즉시 리액트 버전 crud 기능이 탑재된 코드를 구현해보겠습니다.

 

1) src/App.js immutablilty-helper 를 임포트 시키겠습니다.

import "../node_modules/bootstrap/dist/css/bootstrap.min.css";

 

 

2) 생성 및 수정용 Form을 준비합니다. src/modal/ModalComponent.jsx

이 코드의 의미는 수정 및 삽입의 대한 폼을 나타내는 코드입니다.

isModal : App.js의 state값에 모달 창 띄울지 파라미터

modalViewToggle : 모달 띄우는 이벤트

createBoard : 삽입 관련 메서드

message : 버튼에 추가 or 수정 텍스트 표시하는 파라미터

mode : 추가 모드 or 수정 모드 구분 짓는 파라미터 변수

updateData : 수정할려는 state 값

updateIndex : 수정할려는 state index 값

updateBoard :수정 할려는 메소드 

 

import React, { useEffect, useState } from 'react'
import {
  Card,
  CardBody,
  CardText,
  Button,
  Row,
  Col,
  Input,
  Modal,
  ModalHeader,
  ModalBody,
  FormGroup,
} from "reactstrap";
import update from "immutability-helper";

function ModalComponent({isModal, modalViewToggle, createBoard, message, mode, updateData, updateIndex, updateBoard}) {

  const [inputCreate, setInputCreate] = useState();
  const [inputUpdate, setInputUpdate] = useState({bno:updateData?.bno});


  // 삽입용
  const createOnChange = (e) => {
    const { name, value } = e.target;
    setInputCreate({
      ...inputCreate,
      [name]: value,
    });
  };
  // console.log(updateData)

  // 수정용
  const updateOnChange = (e) => {
    const { name, value } = e.target;
    setInputUpdate({
      ...inputUpdate,
      bno:updateData?.bno,
      [name]: value,
    });
    console.log(inputUpdate)
  };

  return (
    <Modal
        isOpen={isModal}
        toggle={modalViewToggle}
        centered={true}
        fullscreen={true}
      >
        <ModalHeader toggle={modalViewToggle}>
          {message + " 게시글을 입력하세요"} 
        </ModalHeader>
        <ModalBody>
          <Card className="my-2" color="primary" outline>
            <CardBody>
              <FormGroup>
                <CardText>
                제목
                {
                  mode === "create" ?
                    <Input name="title" onChange={createOnChange}/>
                  :
                    <Input name="title" defaultValue={updateData?.title} onChange={updateOnChange}/>
                }
                내용
                {
                  mode === "create"?
                  <Input type="textarea" name="contents" onChange={createOnChange} />
                  :
                  <Input type="textarea" name="contents" defaultValue={updateData?.contents} onChange={updateOnChange} />

                }
                </CardText>
              </FormGroup>
              <Row>
                <Col sm={{ offset: 3, size: "auto" }}>
                  {
                    mode === "create"?
                      <Button
                        color="success"
                        onClick={() => {
                          createBoard(inputCreate);
                        }}
                      >
                        추가
                      </Button>
                      :
                      <Button
                        color="primary"
                        onClick={() => {
                          updateBoard(inputUpdate,updateIndex);
                        }}
                      >
                        수정
                      </Button>
                  }
                </Col>
                <Col sm={{ offset: 4, size: "auto" }}>
                  <Button
                    onClick={() => {
                      modalViewToggle()
                    }}
                  >
                    닫기
                  </Button>
                </Col>
              </Row>
            </CardBody>
          </Card>
        </ModalBody>
      </Modal>
  )
}

export default ModalComponent

 

이 때, 입력 추가용 state와 수정용 state를 통해 게시판 형태로 사용 가능합니다. 

 

src/App.js에서 Modal을 추가해줍니다.

import ModalComponent from "./modal/ModalComponent";
  <ModalComponent
    isModal={isModal}
    modalViewToggle={modalViewToggle}
    createBoard={createBoard}
    message={message}
    mode={mode}
    updateData={updateData}
    updateIndex={updateIndex}
    updateBoard={updateBoard}
  />

 

3) 모달 띄우기 (src/App.js) 

아래와 같이 함수를 지정하여 사용후 모달 관련 함수를 사용합니다.

모달의 대해 자세한 내용은 reactstrap 공식 문서를 참조 바랍니다.

https://reactstrap.github.io/?path=/docs/components-modal--modal 

 

Storybook

 

reactstrap.github.io

 

 

 // 모달 띄울것인지 아닌지 상태 변수를 가리킴
 const [isModal, setIsModal] = useState(false);
// 모달 화면 띄우는 이벤트
const modalViewToggle = () => setIsModal(!isModal);
// 모드에 수정모드 or 삽입 모드 설정하는 모달창
const [mode, setMode] = useState("create");
// 모달에 버튼 기능 추가 or 수정 텍스트 표시할 변수
const [message, setMessage] = useState();
// 모달 이벤트를 변화 주는 메서드
const modalViewToggle = () => setIsModal(!isModal);
  // state 값 변화시 각 state 변화된 결과를 렌더링 하기 위해 추가
  // 특히 board state 값을 위한 메서드
  const [isStateChange, setIsStateChange] = useState(false);

 

4) 생성 관련 기능 추가

// 모달에 전달해주는 메서드
const readyChange = () => {
    setMessage("추가"); // 버튼 추가 텍스트 전달
    setMode("create"); // 생성 모드로 모달 창 띄우기
    modalViewToggle(); // 모달 띄우기
  };

// 생성 메서드 
// 이때, 불가변성으로 생성 할 수 있는 기능을 삽입한다.
const createBoard = (data) => {
    // front 화면에서 생성하는 것처럼 행동
    setBoard(
      update(board, {
        $push: [data],
      })
    );

	modalViewToggle(); // 모달창을 닫는다.
};

 

 

5) 수정 관련 기능 추가

  // 수정용 state 값 : data - 해당 index의 데이터 전달, index - 해당 인덱스 전달
  const [updateData, setUpdateData] = useState();
  const [updateIndex, setUpdateIndex] = useState();
// 모달에 전달해주는 값 메소드 추가
const readyUpdate = (data, index) => {
    setMessage("수정"); // 버튼에 수정 표시
    setMode("update"); // 수정 모드로 모달 열기
    modalViewToggle(); // 모달 열기
    setUpdateData(data); // 수정 모드 해당 데이터 전달
    setUpdateIndex(index); // 수정 모드 해당 인덱스 전달
  };

// 수정 이벤트
const updateBoard = (data, index) => {
    // 불가변성으로 이용하여 해당 데이터 수정
    setBoard(
        update(board, {
            $merge: { [index]: data },
        })
    );
    modalViewToggle(); // 모달 창 닫기
    setIsStateChange(!isStateChange); // state 값 변하면 바로 리렌더링하는 기능
};

 

6) 삭제를 위한 기능

  // 삭제를 위한 메서드
  const deleteBoard = (index) => {
    const deleteData = board[index];
    setBoard(
      update(board, {
        $splice: [[index, 1]],
      })
    );
  };

 

7) 기능 추가 후, rendering 하는 코드에 아래와 같이 수정합니다.

  {board?.map((b, index) => (
    <Card key={index} className="my-2" color="primary" outline>
      <CardHeader>{b?.title}</CardHeader>
      <CardBody>
        <CardText>{b?.contents}</CardText>
        <br />
        <br />
        <Row>
          <Col sm={{ offset: 3, size: "auto" }}>
            <Button
              color="primary"
              onClick={() => {
                readyUpdate(b, index);
              }}
            >
              수정
            </Button>
          </Col>
          <Col sm={{ offset: 4, size: "auto" }}>
            <Button color="danger" onClick={() => deleteBoard(index)}>
              삭제
            </Button>
          </Col>
        </Row>
      </CardBody>
    </Card>
  ))}
  <br />
  <br />
  <br />
  <br />
  <Row>
    <Button
      color="success"
      onClick={() => {
        readyChange();
      }}
    >
      추가
    </Button>
  </Row>

 

8) src/App.js 전체 코드

import {
  Card,
  CardHeader,
  CardBody,
  CardText,
  Button,
  Row,
  Col,
} from "reactstrap";
import "./App.css";
import { useEffect, useState } from "react";
import ModalComponent from "./modal/ModalComponent";
import update from "immutability-helper";

function App() {
  const data = [
    {
      bno: 1,
      title: "제목1",
      contents: "내용1",
    },
    {
      bno: 2,
      title: "제목2",
      contents: "내용2",
    },
    {
      bno: 3,
      title: "제목3",
      contents: "내용3",
    },
    {
      bno: 4,
      title: "제목4",
      contents: "내용4",
    },
  ];
  // console.log(data);

  // 게시판 데이터 담는 state 값
  const [board, setBoard] = useState();

  // 모달창띄울지 여부 확인
  const [isModal, setIsModal] = useState(false);

  // 모달에 수정모드 or 삽입모드 결정 짓는 state 값
  const [mode, setMode] = useState("create");

  // 버튼 텍스트 전달할 state값
  const [message, setMessage] = useState();

  // 수정용 state 값 : data - 해당 index의 데이터 전달, index - 해당 인덱스 전달
  const [updateData, setUpdateData] = useState();
  const [updateIndex, setUpdateIndex] = useState();

  // state 값 변화시 각 state 변화된 결과를 렌더링 하기 위해 추가
  // 특히 board state 값을 위한 메서드
  const [isStateChange, setIsStateChange] = useState(false);

  // 모달 여/닫기 이벤트용 메서드
  const modalViewToggle = () => setIsModal(!isModal);

  // html 렌더링 후 데이터 가져오기를 위한 기능
  // [] 는 첫번째만 호출
  useEffect(() => {
    setBoard(data);
  }, []);
  console.log(board);

  // 모달에 전달해주는 삽입 메서드
  const readyChange = () => {
    setMessage("추가"); // 버튼 추가 텍스트 전달
    setMode("create"); // 생성 모드로 모달 창 띄우기
    modalViewToggle(); // 모달 띄우기
  };

  // 생성 메서드
  // 이때, 불가변성으로 생성 할 수 있는 기능을 삽입한다.
  const createBoard = (data) => {
    // front 화면에서 생성하는 것처럼 행동
    setBoard(
      update(board, {
        $push: [data],
      })
    );

    modalViewToggle(); // 모달창을 닫는다.
  };

  // 모달에 전달해주는 데이터 수정 메소드 추가
  const readyUpdate = (data, index) => {
    setMessage("수정"); // 버튼에 수정 표시
    setMode("update"); // 수정 모드로 모달 열기
    modalViewToggle(); // 모달 열기
    setUpdateData(data); // 수정 모드 해당 데이터 전달
    setUpdateIndex(index); // 수정 모드 해당 인덱스 전달
  };

  // 수정 이벤트
  const updateBoard = (data, index) => {
    // 불가변성으로 이용하여 해당 데이터 수정
    setBoard(
      update(board, {
        $merge: { [index]: data },
      })
    );
    modalViewToggle(); // 모달 창 닫기
    setIsStateChange(!isStateChange); // state 값 변하면 바로 리렌더링하는 기능
  };

  // 삭제를 위한 메서드
  const deleteBoard = (index) => {
    setBoard(
      update(board, {
        $splice: [[index, 1]],
      })
    );
  };

  return (
    <div className="container">
      <h1>게시판 프로젝트</h1>
      <br />
      <br />
      <br />
      <br />
      {board?.map((b, index) => (
        <Card key={index} className="my-2" color="primary" outline>
          <CardHeader>{b?.title}</CardHeader>
          <CardBody>
            <CardText>{b?.contents}</CardText>
            <br />
            <br />
            <Row>
              <Col sm={{ offset: 3, size: "auto" }}>
                <Button
                  color="primary"
                  onClick={() => {
                    readyUpdate(b, index);
                  }}
                >
                  수정
                </Button>
              </Col>
              <Col sm={{ offset: 4, size: "auto" }}>
                <Button color="danger" onClick={() => deleteBoard(index)}>
                  삭제
                </Button>
              </Col>
            </Row>
          </CardBody>
        </Card>
      ))}
      <br />
      <br />
      <br />
      <br />
      <Row>
        <Button
          color="success"
          onClick={() => {
            readyChange();
          }}
        >
          추가
        </Button>
      </Row>
      <ModalComponent
        isModal={isModal}
        modalViewToggle={modalViewToggle}
        createBoard={createBoard}
        message={message}
        mode={mode}
        updateData={updateData}
        updateIndex={updateIndex}
        updateBoard={updateBoard}
      />
    </div>
  );
}

export default App;

 

 

 

마치며,

지금까지 React로 이용하여 CRUD 까지 구현해보았습니다.

다음 시간에는 API를 이용하여 데이터 CRUD 구성하기 위해 DB 설계와 SQL문, 그리고 Spring Boot API를 이용하여 인터페이스 호출까지 하는 시간을 가지겠습니다.

728x90
반응형
LIST