개발은 재밌어야 한다
article thumbnail
반응형

이번 포스팅에서는 글 목록에서 글 상세보기를 즉 CRUD에서 R에 해당하는 Read를 구현해보도록 하겠습니다.

 

현재 상태는 이렇게 되어 있는데 테이블을 클릭하면 팝업을 띄워 글에 대해 상세한 내용을 보여주는식으로 간단하게 구현을 해보도록 하겠습니다.

 

일단 Element-ui에서 테이블을 행(row)을 클릭할때 emit으로 row-click을 보내고 해당 파라미터에는 row,column,event에 대한 정보를 파라미터에 담아서 보내줍니다.

일단 저 row-click을 코드를 통해서 확인해 보겠습니다.

<template>
  <div>
    <el-table border :data="boardList" @row-click="rowClick">
      <el-table-column prop="bno" label="글번호"></el-table-column>
      <el-table-column prop="title" label="제목"></el-table-column>
      <el-table-column prop="content" label="내용"></el-table-column>
      <el-table-column prop="writer" label="작성자"> </el-table-column>
      <el-table-column prop="regDate" label="등록일" :formatter="DateFormat"></el-table-column>
    </el-table>
  </div>
</template>
 
<script>
import axios from 'axios';
import moment from 'moment';
 
export default {
  name: 'BoardList',
  data() {
    return {
      boardList: [],
    };
  },
  created() {
    this.getBoardList();
  },
  methods: {
    DateFormat(row) {
      return moment(row.regDate).format('YYYY-MM-DD hh:MM:ss');
    },
    getBoardList() {
      axios
        .get('http://localhost:8080/board/get-board-list.do')
        .then((response) => {
          if (response.data.success) {
            this.boardList = response.data.result;
          }
        })
        .catch(function(error) {
          console.log(error);
        });
    },
    rowClick(row, column, event)
    {
      console.log(row);
      console.log(column);
      console.log(event);
    }
  },
};
</script>
 
<style scoped></style>
 

 

rowCilick으로 정의된 데이터의 정보를 한번 확인해보기위해 row데이터를 콘솔로 확인해보겠습니다.

테이블의 한개의 행을 클릭후 콘솔화면

row의 데이터와 column의 데이터, 해당 event에 대한 값을 확인해 볼 수 있습니다.

 

테이블을 클릭할때 Vue devtools의 Event를 통해서 직접 확인 해 볼 수도 있습니다.

테이블에 해당 줄을 클릭하면 row-click를 emit하여서 payload에 각 row, column, event에 대한 값을 담아서 보내주는걸 Vue devtools로도 확인이 가능합니다.

Vue devtools의 사용법에 대해서는 아래의 포스팅을 참고해주세요.

https://dreamcoding.tistory.com/34

 

Vue devtools 설치 및 사용

이번에는 Vue 개발할때 자주 사용하는 개발 도구인 Vue devtools에 대해 포스팅해보겠습니다. 크롬에서 확장 프로그램 플러그인으로 제공하는 Vue devtools는 Vue로 만든 웹의 구조를 파악하거나 데이터

dreamcoding.tistory.com

 

BoardList.vue

여기서 원하는 값은 row의 값중에 bno만 가져와서 BackEnd에 해당 bno를 통해서 데이터를 조회하는 방법으로 구현해보도록 하겠습니다. (물론 해당 row의 데이터만으로도 데이터가 다 있기에 구현이 가능하지만 RestApi로 Read를 구현하는게 목표이기에 bno만 구하겠습니다.)

 

클릭시 rowClick을 호출하고 해당 row에서 bno만 사용하겠습니다.

bno를 확인했으니 해당 bno를 파라미터로 axios로 호출하도록 코드를 바꿔주고 rowclick의 메소드도 명확하게 getBoardDetail로 바꿔서 Controller의 메소드의 이름과 동일하게 해서 헷갈리지 않게 바꿔보도록 하겠습니다.

 

백엔드에서 받아온 데이터는 BoardDetail에 담도록 하겠습니다.

BoardList.vue

<template>
  <div>
    <el-table border :data="boardList" @row-click="getBoardDetail">
      <el-table-column prop="bno" label="글번호"></el-table-column>
      <el-table-column prop="title" label="제목"></el-table-column>
      <el-table-column prop="content" label="내용"></el-table-column>
      <el-table-column prop="writer" label="작성자"> </el-table-column>
      <el-table-column prop="regDate" label="등록일" :formatter="DateFormat"></el-table-column>
    </el-table>
  </div>
</template>
 
<script>
import axios from 'axios';
import moment from 'moment';
 
export default {
  name: 'BoardList',
  data() {
    return {
      boardList: [],
      boardDetail: [],
    };
  },
  created() {
    this.getBoardList();
  },
  methods: {
    DateFormat(row) {
      return moment(row.regDate).format('YYYY-MM-DD hh:MM:ss');
    },
    getBoardList() {
      axios
        .get('http://localhost:8080/board/get-board-list.do')
        .then((response) => {
          if (response.data.success) {
            this.boardList = response.data.result;
          }
        })
        .catch(function(error) {
          console.log(error);
        });
    },
    getBoardDetail(row) {
      const params = {
        bno: row.bno,
      };
      axios
        .post('http://localhost:8080/board/get-board-detail.do', params)
        .then((response) => {
          if (response.data.success) {
            this.boardDetail = response.data.result;
          }
        })
        .catch(function(error) {
          console.log(error);
        });
    },
  },
};
</script>
 
<style scoped></style>
 

get-board-detail.do에 맞는 Controller에도 Mapping되는 주소를 BoardController.java에 정의하도록 하겠습니다.

BoardController.java

@RequestBody 어노테이션을 사용하여 HTTP 요청 본문에 담긴 값들을 자바객체로 변환시켜, 객체에 저장시켜줍니다. 여기서는 파라미터에 BoardVO 객체를 통해 .getBno()를 사용하여 bno를 구하기 위해 파라미터를 위와 같이 표현하였습니다(@RequestParam int bno 을 통해서 bno만 취할수도 있습니다.)

 

package com.dream.controller;
 
import java.util.Map;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
 
import com.dream.service.BoardService;
import com.dream.vo.BoardVO;
import com.dream.vo.ResultVO;
 
@CrossOrigin(origins = "*")
@Controller
@RequestMapping("board/")
public class BoardController {
 
	private static final Logger LOG = LoggerFactory.getLogger(BoardController.class);
 
	@Autowired
	BoardService service;
 
	@ResponseBody
	@RequestMapping(value = "get-board-list.do", method = RequestMethod.GET)
	public ResultVO getBoardList() 
	{	
		// 호출 시 찍히게 될 로그
		LOG.info("[GET] getBoardList");
		// 결과 값을 담을 ResultVO를 선언한 생성자를 통해서 만드는데 기본값은 success는 false, result는 null로 세팅
		ResultVO result = new ResultVO(false, null);
 
		try {
			result.setResult(service.getBoardList());
			result.setSuccess(true);
		} catch (Exception e) {
			// TODO: handle exception
			LOG.error("[Board] getBoardList : " + e.getMessage(), e);
		}
 
		return result;
 
	}
 
	@ResponseBody
	@RequestMapping(value = "regist-board.do", method = RequestMethod.POST)
	public ResultVO registBoard(@RequestBody BoardVO vo) 
	{	
		// 호출 시 찍히게 될 로그
		LOG.info("[POST] registBoard");
		// 결과 값을 담을 ResultVO를 선언한 생성자를 통해서 만드는데 기본값은 success는 false, result는 null로 세팅
		ResultVO result = new ResultVO(false, null);
 
		try {
			result.setResult(service.registBoard(vo));
			result.setSuccess(true);
		} catch (Exception e) {
			// TODO: handle exception
			LOG.error("[Board] getBoardList : " + e.getMessage(), e);
		}
 
		return result;
 
	}
 
	@ResponseBody
	@RequestMapping(value = "get-board-detail.do", method = RequestMethod.POST)
	public ResultVO getBoardDetail(@RequestBody BoardVO vo) 
	{	
		// 호출 시 찍히게 될 로그
		LOG.info("[POST] getBoardDetail");
		// 결과 값을 담을 ResultVO를 선언한 생성자를 통해서 만드는데 기본값은 success는 false, result는 null로 세팅
		ResultVO result = new ResultVO(false, null);
 
		try {
			result.setResult(service.getBoardDetail(vo));
			result.setSuccess(true);
		} catch (Exception e) {
			// TODO: handle exception
			LOG.error("[Board] getBoardDetail : " + e.getMessage(), e);
		}
 
		return result;
 
	}
}
 

해당 BoardService에서 getBoardDetail메소드도 작성해주도록 하겠습니다.

BoardService.java

 

package com.dream.service;
 
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
 
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
 
import com.dream.mapper.BoardMapper;
import com.dream.vo.BoardVO;
 
@Service
public class BoardService implements BoardServiceIF {
 
	@Autowired
	private SqlSessionFactory sqlSessionFactory;
 
	@Override
	public List<BoardVO> getBoardList() {
		// TODO Auto-generated method stub
		List<BoardVO> boardList = new ArrayList<BoardVO>();
 
		try (SqlSession session = sqlSessionFactory.openSession()) {
			BoardMapper mapper = session.getMapper(BoardMapper.class);
 
			boardList = mapper.getBoardList();
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return boardList;
	}
 
	public Boolean registBoard(BoardVO vo) {
		// TODO Auto-generated method stub
 
		vo.setRegDate(new Date());
		vo.setWriter("user");
 
		boolean result = false;
 
		try (SqlSession session = sqlSessionFactory.openSession()) {
			BoardMapper mapper = session.getMapper(BoardMapper.class);
 
			// 매퍼의 결과를 담을 변수
			int mapperResult = 0;
 
			// 성공시 1이 반환됩니다.
			mapperResult = mapper.registBoard(vo);
 
			//정상 동작시 return 값을 true
			if (mapperResult > 0) {
				result = true;
			}
			//정상 동작이 아닐 시 return 값을 false
			else {
				result = false;
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
 
		return result;
	}
 
	public BoardVO getBoardDetail(BoardVO vo) {
		// TODO Auto-generated method stub
		BoardVO board = new BoardVO();
 
		try (SqlSession session = sqlSessionFactory.openSession()) {
			BoardMapper mapper = session.getMapper(BoardMapper.class);
 
			board = mapper.getBoardDetail(vo.getBno());
 
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return board;
	}
}
 

BoardMapper 인터페이스에 mapper 메소드를 정의합니다.

BoardMapper 인터페이스

 

package com.dream.mapper;
 
import java.util.List;
 
import org.apache.ibatis.annotations.Mapper;
 
import com.dream.vo.BoardVO;
 
@Mapper
public interface BoardMapper {
 
	public List<BoardVO> getBoardList();
 
	public int registBoard(BoardVO vo);
 
	public BoardVO getBoardDetail(int bno);
 
}
 

다음으로 해당 메소드에 맞는 id의 SQL문을 BoardMapper.xml에 작성해줍니다.

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dream.mapper.BoardMapper">
 
	<resultMap type="com.dream.vo.BoardVO" id="boardMap">
		<id property="bno" column="bno"></id>
		<result property="title" column="title"/>
		<result property="content" column="content"/>
		<result property="writer" column="writer"/>
		<result property="regDate" column="regDate"/>
	</resultMap>
 
	<select id="getBoardList" resultMap="boardMap">
		SELECT * FROM BOARD
	</select>
 
	<insert id="registBoard">
		INSERT INTO BOARD
			(title, content, writer, regDate)
			VALUES (#{title}, #{content}, #{writer}, #{regDate})
	</insert>
 
	<select id="getBoardDetail" resultMap="boardMap">
		SELECT * FROM BOARD WHERE bno = #{bno}
	</select>
 
</mapper>
 

 

 

자 Reponse가 정상적으로 되는지 확인해보겠습니다.

정상적으로 Board의 정보를 반환하는것을 확인 할 수 있습니다.

테이블에서 한개의 row를 클릭시 api호출 후 Response

Vue devtools로 해당 컴포넌트의 데이터를 확인해보니 정상적으로 boardDetail에 데이터가 있는것도 확인했습니다.

.

자 이제 팝업으로 띄워보도록 하겠습니다.

BoardList.vue에 팝업에 대한 코드를 추가합니다.

BoardList.vue

 

<template>
  <div>
    <el-table border :data="boardList" @row-click="getBoardDetail">
      <el-table-column prop="bno" label="글번호"></el-table-column>
      <el-table-column prop="title" label="제목"></el-table-column>
      <el-table-column prop="content" label="내용"></el-table-column>
      <el-table-column prop="writer" label="작성자"> </el-table-column>
      <el-table-column prop="regDate" label="등록일" :formatter="DateFormat"></el-table-column>
    </el-table>
    <!-- 글 상세 보기 내용 -->
    <el-dialog title="글 상세 보기" :visible.sync="openDetail" width="30%" center>
      글 번호 : {{ boardDetail.bno }} <br>
      제목 : {{ boardDetail.title }} <br>
      등록일 : {{ boardDetail.regDate }} <br>
      내용 : {{ boardDetail.content }} <br>
      작성자 : {{ boardDetail.writer }} <br>
    </el-dialog>
  </div>
</template>
 
<script>
import axios from 'axios';
import moment from 'moment';
 
export default {
  name: 'BoardList',
  data() {
    return {
      boardList: [],
      boardDetail: [],
      openDetail: false,
    };
  },
  created() {
    this.getBoardList();
  },
  methods: {
    DateFormat(row) {
      return moment(row.regDate).format('YYYY-MM-DD hh:MM:ss');
    },
    getBoardList() {
      axios
        .get('http://localhost:8080/board/get-board-list.do')
        .then((response) => {
          if (response.data.success) {
            this.boardList = response.data.result;
          }
        })
        .catch(function(error) {
          console.log(error);
        });
    },
    getBoardDetail(row) {
      const params = {
        bno: row.bno,
      };
      axios
        .post('http://localhost:8080/board/get-board-detail.do', params)
        .then((response) => {
          if (response.data.success) {
            this.boardDetail = response.data.result;
            this.openDetail = true;
          }
        })
        .catch(function(error) {
          console.log(error);
        });
    },
  },
};
</script>
 
<style scoped></style>
 

간단하게 해당 정보를 팝업에 보여주도록 하겠습니다.

정상적으로 잘 보이는것을 확인 할 수 있습니다.

 

다음번은 수정하기에 대해 포스팅하도록 하겠습니다.

 

 

 

전체 소스코드는 아래 깃허브에서 확인 할 수 있습니다.

https://github.com/skarbgud/Board-Project

 

GitHub - skarbgud/Board-Project: 스프링 Vue 게시판 만들기 (티스토리 블로그 레포지토리)

스프링 Vue 게시판 만들기 (티스토리 블로그 레포지토리). Contribute to skarbgud/Board-Project development by creating an account on GitHub.

github.com

 

 

 

반응형
profile

개발은 재밌어야 한다

@ghyeong

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!