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

이번 포스팅에서는 글 등록을 구현해 보도록 하겠습니다.

우선 Vue 부분에 컴포넌트를 조금 정리하고 가도록 하겠습니다.

제일 처음 생성되는 App.vue에서 상단에는 Vue 이미지 파일과 HelloWordl 컴포넌트를 통해서 첫화면을 보여주고 있습니다.

해당 부분을 조금 바꿔 볼까 합니다.

HelloWorld컴포넌트를 BoardList.vue로 변경해주고 상단에 이미지 부분은 글 등록하는 컴포넌트를 넣어보도록 하겠습니다.

우선 HelloWorld.vue 파일을 BoardList.vue로 이름을 변경합니다.

기존에 HelloWorld.vue => BoardList.vue 로 변경했으면 name에도 마찬가지로 BoardList로 변경을 해주도록 하겠습니다.

 

<template>
  <div>
    <el-table border :data="boardList">
      <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: [],
    };
  },
  props: {
    msg: String,
  },
  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);
        });
    },
  },
};
</script>

<style scoped></style>

<BoardList.vue>

 

이번에는 App.vue로 가서 import 부분을 수정해주도록 하겠습니다.

App.vue는 기존에 있던 이미지와 스타일들을 제거하고 HelloWorld.vue라고 되어있는 부분을 BoardList.vue로 수정했으니 경로에 있는 파일명과 components에 선언된 컴포넌트이름도 변경해주시고 template에 있는 컴포넌트도 board-list로 변경하도록 하겠습니다.

자 이제 백지상태에서의 그냥 테이블만 덩그러니 남아있는걸 볼 수 있습니다.

Vue devtools로 컴포넌트가 정상적으로 잘 되어있는지 확인해보도록하겠습니다. (Vue devtools에 관한 내용은 아래 포스팅에서 확인해주세요!)

https://dreamcoding.tistory.com/34

 

Vue devtools 설치 및 사용

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

dreamcoding.tistory.com

F12번을 눌러서 개발자 모드로 확인해보겠습니다.

App컴포넌트 하위에 BoardList컴포넌트가 정상적으로 잘 들어가있네요

BoardList.vue에서 props로 msg를 받고있는데 msg에 대한 정보가 없어서 undefined로 표시되는데 

원래 HelloWorld에 msg로 Welcome to Your Vue.js App 라는 글을 props로 보내주고 있었기에 BoardList에 msg가 props로 받고 있어서 해당 부분을 지워 주도록 하겠습니다.

 

BoardList.vue

해당 부분을 지우겠습니다.

자 깔끔한 상태가 되었죠?

 

그럼 이제 글등록을 위한 버튼을 넣어보도록 하겠습니다.

App.vue에서 글 등록을 위한 컴포넌트를 넣어서 글등록만을 위한 컴포넌트를 만들어서 넣어보도록 하겠습니다.

App.vue

<template>
  <div id="app">
    <regist-board></regist-board>
    <board-list></board-list>
  </div>
</template>

<script>
import RegistBoard from './components/RegistBoard.vue';
import BoardList from './components/BoardList.vue';

export default {
  name: 'App',
  components: {
    RegistBoard,
    BoardList,
  },
};
</script>

<style></style>

BoardList.vue를 등록했던것 처럼 등록하시면 됩니다.

그럼 BoardList.vue가 있던 components폴더에 마찬가지로 RegistBoard.vue 파일을 생성해주도록 합니다.

RegistBoard.vue를 생성해주세요

<template>
  <div>
    <el-button type="danger">글쓰기</el-button>
  </div>
</template>

<script>
export default {
  name: 'RegistBoard',
  data() {
    return {};
  },
  methods: {},
};
</script>

<style scoped></style>

처음에는 그냥 간단하게 글쓰기 버튼을 넣어보도록 하겠습니다. danger로 type을 지정하면 약간 뻘건색 글쓰기 버튼이 나올겁니다.

자 글을 등록하려면 글을 입력할 공간이 필요하겠죠?

저는 글 등록에 대한 입력을 팝업 형태로 구현을 해 보도록하겠습니다. (새로운 페이지를 띄우는 형식이나 다른 형식도 있지만 팝업이 개인적으로 제일 간단하고 직관적이라고 생각합니다)

https://element.eleme.io/#/en-US/component/dialog

 

Element - The world's most popular Vue UI framework

 

element.eleme.io

element-ui에서는 팝업의 형태를 dialog라는 이름으로 제공을 하고 있습니다.

이걸 이용해서 글쓰기를 클릭하면 글쓰는 공간의 팝업을 구현해보겠습니다.

RegistBoard.vue

간단하게 글쓰기 버튼을 누르면 openPopup데이터가 true가 되면서 :visible.sync에서 데이터가 true가 되면서 dialog가 보여지게 되면서 정의된 title과 width center에 따른 팝업이 생겨나고

하단에 footer영역에는 확인버튼과 취소버튼을 만들고 일단은 두 버튼다 팝업창을 닫도록 하였습니다.

 

확인해볼까요?

 

상단에 글쓰기 타이틀과 하단에 확인버튼 취소버튼이 잘 나오는걸 확인 할 수 있습니다.

그럼 저기 글쓰기 영역에 글에 대한 제목과 내용부분을 입력할 수 있는 영역을 넣어보도록 하겠습니다.

 

RegistBoard.vue

제목과 내용을 입력받는 input을 생성해주도록 합니다.

<template>
  <div>
    <!-- 글쓰기 버튼 -->
    <el-button type="danger" @click="openPopup = true">글쓰기</el-button>
    <!-- 팝업 내용 -->
    <el-dialog title="글쓰기" :visible.sync="openPopup" width="30%" center>
      <!-- 본문 영역 -->
      <el-input placeholder="제목을 입력해 주세요" v-model="title"></el-input>
      <el-input
        style="margin-top:30px;"
        type="textarea"
        :rows="30"
        placeholder="내용을 입력해 주세요."
        v-model="content"
      >
      </el-input>
      <!-- dialog footer 영역 -->
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="openPopup = false">확인</el-button>
        <el-button @click="openPopup = false">취소</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: 'RegistBoard',
  data() {
    return {
      openPopup: false,
      title: '',
      content: '',
    };
  },
  methods: {},
};
</script>

<style scoped></style>

자 얼추 글쓰기 형태가 나는것 같습니다. 

 

 

그럼 확인 버튼을 눌렀을때에 메소드를 구현해보도록 하겠습니다.

RegistBoard.vue

<template>
  <div>
    <!-- 글쓰기 버튼 -->
    <el-button type="danger" @click="openPopup = true">글쓰기</el-button>
    <!-- 팝업 내용 -->
    <el-dialog title="글쓰기" :visible.sync="openPopup" width="30%" center>
      <!-- 본문 영역 -->
      <el-input placeholder="제목을 입력해 주세요" v-model="title"></el-input>
      <el-input
        style="margin-top:30px;"
        type="textarea"
        :rows="30"
        placeholder="내용을 입력해 주세요."
        v-model="content"
      >
      </el-input>
      <!-- dialog footer 영역 -->
      <span slot="footer" class="dialog-footer">
        <el-button type="primary" @click="registboard()">확인</el-button>
        <el-button @click="openPopup = false">취소</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  name: 'RegistBoard',
  data() {
    return {
      openPopup: false,
      title: '',
      content: '',
    };
  },
  computed: {
    setParams() {
      const params = {
        title: this.title,
        content: this.content,
      };
      return params;
    },
  },
  methods: {
    registboard() {
      axios
        .post('http://localhost:8080/board/regist-board.do', this.setParams)
        .then((response) => {
          if (response.data.success) {
            console.log(response);
          }
        })
        .catch(function(error) {
          console.log(error);
        });
    },
  },
};
</script>

<style scoped></style>

확인 버튼을 누르면 registBoard라는 메소드가 호출이 되고 목록과 마찬가지로 axios를 사용하는 대신 post로 파라미터는 setParams를 computed에 선언해 사용하는 방식으로 구현을 해봅니다.

 

 

이번에는 BoardController.java로 와서 해당 컨트롤러에 대한 정의를 합니다.

BoardController.java

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.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 {
			service.registBoard(vo);
			result.setSuccess(true);
		} catch (Exception e) {
			// TODO: handle exception
			LOG.error("[Board] getBoardList : " + e.getMessage(), e);
		}

		return result;

	}
}

서비스에서 등록에 대한 비즈니스 로직을 구현해보겠습니다.

BoardService.java

일단은 등록일은 new Date()로 현재 시간을 세팅해주고 작성자도 일단을 user로 넣어줍니다.

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 void registBoard(BoardVO vo) {
		// TODO Auto-generated method stub
		
		vo.setRegDate(new Date());
		vo.setWriter("user");
		
		try (SqlSession session = sqlSessionFactory.openSession()) {
			BoardMapper mapper = session.getMapper(BoardMapper.class);

			mapper.registBoard(vo);
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
	}

}

mapper에도 메소드를 정의해줍니다.
BoardMapper인터페이스에 registBoard메소드를 정의해줍니다.

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 void registBoard(BoardVO vo);
	
}

BoardMapper.xml에도 메소드 이름에 맞는 insert문을 작성해줍니다.

<?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>

</mapper>

자 서버를 재실행하고 글을 한번 등록해보겠습니다.

확인버튼을 누르면 post로 컨트롤러에 정의된 regist-board.do에 호출을 하게되고 service를 통해 mybatis를 통해서 DB에 넣게 될겁니다.

SELECT * FROM board를 해보면 데이터가 잘 들어간 것을 확인 할 수 있습니다.

 

화면에서는 아무런 변화가 없고 한글로 등록하면 오류가 나는데 해당 이슈들은 다음 포스팅에서 다뤄보도록 하겠습니다.

 

 

 

소스파일에 대한 정보는 깃허브에서 확인 할 수 있습니다.

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

 

GitHub - skarbgud/Board-Project

Contribute to skarbgud/Board-Project development by creating an account on GitHub.

github.com

 

반응형
profile

개발은 재밌어야 한다

@ghyeong

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