SpringBoot #6 SpringBoot+React 기반 간단한 게시판 생성하기 #8 게시물 수정 및 삭제 구현하기

2021. 10. 18. 17:22JAVA/Spring

이전글

https://yonghwankim-dev.tistory.com/150

 

SpringBoot #6 SpringBoot+React 기반 간단한 게시판 생성하기 #7 게시물 상세 조회

이전글 https://yonghwankim-dev.tistory.com/149 SpringBoot #6 SpringBoot+React 기반 간단한 게시판 생성하기 #6 게시물 검색 조건 및 등록 처리하기 이전글 https://yonghwankim-dev.tistory.com/147 SpringBo..

yonghwankim-dev.tistory.com

 

개요

이전글에서는 게시물의 상세 페이지를 구현하였습니다. 이번글에서는 게시물의 상세 페이지에서 'Modify' 버튼을 클릭하면 수정 페이지로 이동하도록 하고 수정 페이지에서 게시물의 수정 및 삭제 기능을 구현하도록 합니다.

 

1. 게시물의 수정

특정 게시물의 수정 페이지로 이동하기 위해서 상세 게시물 페이지에서 링크처리를 수행합니다.

src/component/webBoard/WebBoardViewComponent.jsx

    onClickModify = ()=>{
        this.props.history.push("/boards/modify?bno="+this.state.board.bno);
    }
import { Component } from "react";
import ApiService from "../../ApiService";
import queryString from 'query-string';
import change_date from "../../function/change_date";

class WebBoardViewComponent extends Component{
    constructor(props){
        super(props);
        
        const b = queryString.parse(this.props.location.search).bno

        this.state = {
            board : {
                bno : b,
                title : "",
                content : "",
                writer : "",
                regdate : ""
            }
        }
    }

    componentDidMount(){
        this.reloadWebBoardView(this.state.board.bno);
    }
    
    reloadWebBoardView = (bno)=>{
        ApiService.viewWebBoard(bno)
                    .then(res=>{
                        this.setState({board : res.data});
                    })
                    .catch(err=>{
                        console.log("viewWebBoard() error!",err);
                    });
    }

    onClickModify = ()=>{
        this.props.history.push("/boards/modify?bno="+this.state.board.bno);
    }

    onClickGoList = ()=>{
        this.props.history.push("/boards/list");
    }

    render(){
        return (
            <>
            <div>View Page</div>
            <div>
                <div>
                    <label>Bno</label>
                    <input name="bno" value={this.state.board.bno} readOnly/>
                </div>
                <div>
                    <label>Title</label>
                    <input name="title" value={this.state.board.title} readOnly/>
                </div>
                <div>
                    <label>Content</label>
                    <input name="content" value={this.state.board.content} readOnly/>
                </div>
                <div>
                    <label>Writer</label>
                    <input name="writer" value={this.state.board.writer} readOnly/>
                </div>
                <div>
                    <label>Regdate</label>
                    <input name="regdate" value={change_date(this.state.board.regdate)} readOnly/>
                </div>
            </div>
            <div>
                <button onClick={()=>{this.onClickModify()}}>Modify</button>
                <button onClick={()=>{this.onClickGoList()}}>Go List</button>
            </div>
            </>
        ); 
    }
}

export default WebBoardViewComponent;

 

아래의 소스코드는 게시물 수정 페이지입니다. fetchModifyWebBoard 함수는 서버에 페이지 번호(bno)에 대한 게시물 정보를 질의하고 웹 페이지에 출력합니다. onClickModify 함수는 제목 또는 내용을 수정하고 Modify 버튼을 클릭하면 수행되는 함수입니다. 이 함수가 서버에 수정 요청하는 함수입니다.

 

src/component/webBoard/WebBoardModifyComponent.jsx

import { Component } from "react";
import queryString from 'query-string';
import ApiService from "../../ApiService";
import change_date from "../../function/change_date";

class WebBoardModifyComponent extends Component{
    constructor(props)
    {
        super(props);

        const {bno} = queryString.parse(this.props.location.search);

        this.state = {
            board : {
                bno : bno,
                title : "",
                content : "",
                writer : "",
                regdate : "",
                updatedate : ""
            }
        }
    
    }

    componentDidMount(){
        this.fetchModifyWebBoard(this.state.board.bno);
    }

    fetchModifyWebBoard(bno){
        ApiService.fetchModifyWebBoard(bno)
                    .then(res=>{
                        this.setState({
                            board : res.data
                        });
                    })
                    .catch(err=>{
                        console.log("fetchModifyWebBoard() error!", err);
                    });
    }

    onChangeTitle = (e)=>{
        this.setState({
            board : {
                bno : this.state.board.bno,
                title : e.target.value,
                content : this.state.board.content,
                writer : this.state.board.writer,
                regdate : this.state.board.regdate,
                updatedate : this.state.board.updatedate
            }
        });
    }

    onChangeContent = (e)=>{
        this.setState({
            board : {
                bno : this.state.board.bno,
                title : this.state.board.title,
                content : e.target.value,
                writer : this.state.board.writer,
                regdate : this.state.board.regdate,
                updatedate : this.state.board.updatedate
            }
        });
    }

    onClickModify = ()=>{
        ApiService.modifyWebBoard(this.state.board)
                    .then(res=>{
                        if(res.data==="success")
                        {
                            alert("정상적으로 수정되었습니다.");
                            this.props.history.push("/boards/view?bno="+this.state.board.bno);
                        }
                        else
                        {
                            alert("수정이 실패하였습니다.");
                        }
                    })
                    .catch(err=>{
                        console.log("modifyWebBoard() error!",err);
                    });
    }

    onClickDelete = ()=>{
        ApiService.deleteWebBoard(this.state.board.bno)
                    .then(res=>{
                        if(res.data==="success")
                        {
                            alert("정상적으로 삭제되었습니다.");
                            this.props.history.push("/boards/list");
                        }
                        else
                        {
                            alert("삭제가 실패하였습니다.");
                        }
                    })
                    .catch(err=>{
                        console.log("deleteWebBoard() error!", err);
                    })
    }

    onClickCancel = ()=>{
        this.props.history.push("/boards/view?bno="+this.state.board.bno);
    }

    render(){
        return (
            <>
            <div>Modify Page</div>
            <div>
                <div>
                    <label>Bno</label>
                    <input name="bno" value={this.state.board.bno} readOnly style={{background:'lightgray'}}/>
                </div>
                <div>
                    <label>Title</label>
                    <input name="title" defaultValue={this.state.board.title} onChange={this.onChangeTitle}/>
                </div>
                <div>
                    <label>Content</label>
                    <input name="content" defaultValue={this.state.board.content} onChange={this.onChangeContent}/>
                </div>
                <div>
                    <label>Writer</label>
                    <input name="writer" value={this.state.board.writer} readOnly style={{background:'lightgray'}}/>
                </div>
                <div>
                    <label>Regdate</label>
                    <input name="regdate" value={change_date(this.state.board.regdate)} readOnly style={{background:'lightgray'}}/>
                </div>
            </div>
            <div>
                <button onClick={()=>{this.onClickModify()}}>Modify</button>
                <button onClick={()=>{this.onClickDelete()}}>Delete</button>
                <button onClick={()=>{this.onClickCancel()}}>Cancel & Go List</button>
            </div>
            </>
        );
    }
}

export default WebBoardModifyComponent;

 

server : 데이터베이스에 수정 질의

org.zerock.controller.WebBoardController.java

package org.zerock.controller;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.zerock.domain.WebBoard;
import org.zerock.persistence.WebBoardRepository;
import org.zerock.vo.PageMaker;
import org.zerock.vo.PageVO;

import lombok.extern.java.Log;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/boards/")
@Log
public class WebBoardController {
	
    ... 생략
	
	@GetMapping("/modify")
	public Optional<WebBoard> fetchModify(Long bno) {
		log.info("FETCH MODIFY BNO: " + bno);
		
		Optional<WebBoard> result = repo.findById(bno);
		
		if(result.isPresent())
		{
			return result;
		}
		else
		{
			return null;
		}
	}
	
	@PostMapping("/modify")
	public String modify(Long bno, String title, String content) {
		log.info("MODIFY BNO: "+bno);
		log.info("MODIFY Title: "+title);
		log.info("MODIFY Content: "+content);
		
		Optional<WebBoard> result = repo.findById(bno);
		
		if(result.isPresent() && !title.equals("") && !content.equals(""))
		{
			WebBoard origin = result.get();
			origin.setTitle(title);
			origin.setContent(content);
			repo.save(origin);
			return "success";
		}
		else
		{
			return "fail";
		}
	
	}
	
}

 

실행결과 확인

1. 307번의 상세 게시물 이동

2. 수정하기 위해서 Modify 버튼 클릭

3. Title 또는 Content 변경

4. Modify버튼 클릭하여 서버에 수정 요청

수정이 완료되어 "/boards/view?bno=307"로 이동

5. 수정 완료 확인

 

2. 게시물 삭제

server : 데이터베이스에 삭제 질의

org.zerock.controller.WebBoardController.java

package org.zerock.controller;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.zerock.domain.WebBoard;
import org.zerock.persistence.WebBoardRepository;
import org.zerock.vo.PageMaker;
import org.zerock.vo.PageVO;

import lombok.extern.java.Log;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/boards/")
@Log
public class WebBoardController {
	
	@Autowired
	private WebBoardRepository repo;
	
	... 생략
	
	@PostMapping("/delete")
	public String delete(Long bno) {
		log.info("DELETE BNO: " + bno);
		
		repo.deleteById(bno);
		return "success";
	}
}

 

삭제 실행 결과 확인

1. 307번 상세 게시물 이동

2. 삭제를 위해 Modify 버튼 클릭

3. 삭제를 위해 Delete 버튼 클릭

삭제 성공 메시지 받은 후 "/boards/list"로 이동

 

4. 307번 게시물 삭제 확인

 

이번글에서는 게시물의 수정 및 삭제 처리를 구현하였습니다.

 

References

boot06 source code : https://github.com/yonghwankim-dev/SpringBoot-Study
스타트 스프링 부트, 구멍가게 코딩단 지음