Spring과 Vue를 이용한 게시판 제작하기(1) - 목록보기, 게시글작성

이애옹·2022년 9월 16일
0

👀 홈페이지의 기본인 게시판 만들기 !! 👀

📝 게시판 테이블 제작하기

게시판 테이블은 이전에 제작해둔 spring_board 테이블을 이용했다.

CREATE TABLE spring_board(
    no NUMBER,
    cno NUMBER,
    type NUMBER,
    id VARCHAR2(20),
    name VARCHAR2(34) CONSTRAINT sr3_name_nn NOT NULL,
    msg CLOB CONSTRAINT sr3_msg_nn NOT NULL,
    regdate DATE DEFAULT SYSDATE,
)

아마 이정도로 테이블을 만든 것 같음..(코드 어딨는지 모르게써😨)

📝 BoardVO 만들기

package com.sist.vo;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class BoardVO {
	private int no,hit;
	private String name,subject,content,dbday;
	private Date regdate;
}

VO 폴더에 BoardVO를 만들고, 해당코드를 작성했다😆

Getter/Setter은 lombok의 라이브러리를 사용했는데,
없으면 그냥 Source => Generated Getters and Setter 사용하면 된다~~

📝 BoardMapper 만들기

package com.sist.mapper;
import java.util.*;

import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectKey;

import com.sist.vo.BoardVO;
public interface BoardMapper {
	@Select("SELECT no,subject,name,TO_CHAR(regdate,'YYYY-MM-DD') as dbday,hit,num "
			+ "FROM (SELECT no,subject,name,regdate,hit,rownum as num "
			+ "FROM (SELECT no,subject,name,regdate,hit "
			+ "FROM spring_board ORDEY BY no DESC)) "
			+ "WHERE num BETWEEN #{start} AND #{end}")
	public List<BoardVO> boardListData(Map map);
	
	@Select("SELECT CEIL(COUNT(*)/10.0) FROM spring_board")
	public int boardTotalPage();
	
	@SelectKey(keyProperty = "no", resultType = int.class, before = true,
			statement = "SELECT NVL(MAX(no)+1,1) as no FROM spring_board")
	@Insert("INSERT INTO spring_board VALUES(#{no},#{name},#{subject},#{content},#{pwd},SYSDATE,0)")
	public void boardInsert(BoardVO vo);
}

가장 기본적인 게시판 리스트보기, Pagination, 글쓰기(Insert) 기능만 만들기 위한 코드를 작성했다~~

CEIL(COUNT(*)/10.0) => 게시판 글을 10개씩 잘라서 Pagination

SELECT NVL(MAX(no)+1,1) as no FROM spring_board => Sequence 구문

📝 BoardController 만들기

실제 현업에서는 Controller와 RestController를 따로 구분하지 않는다고 하시던데.. 흠

여튼 지금 코드에서는 RestController와 Controller를 구분해서 사용한다.

RestController => 데이터 전송 용도(JSON)
Controller => 화면 변환 용도

@Controller
public class BoardController {
	@Autowired
	private BoardDAO dao;
	
	//사용자 요청 받기 => URI를 통하여 사용자의 요청을 받음
	@GetMapping("board/list.do")
	//사용자에게 받은 주소가 board/list.do 라면 어떤 역할을 수행할건지??
	public String board_list()
	{
		return "board/list";
	}
	
	@GetMapping("board/insert.do")
	public String board_insert()
	{
		return "board/insert";
	}
}

GetMapping => URI를 통하여 사용자의 요청을 받기위해 사용한다.
쉽게 말해서, 사용자의 요청은 다른 것으로는 받을 수 없고 주소를 통해서만 받을 수 있다고
한다!! 그래서 GetMapping을 이용해 주소를 받는거다 😋

위 코드처럼 @GetMapping("board/list.do") 의 경우 ..
=> 사용자에게 받은 주소가 board/list.do 라면 어떤 역할을 수행할건지?? 이렇게 해석된다!

마지막으로 return "board/list" 는 코드가 실행된 후 반환될 페이지라고 생각하면 될것같다.

📝 BoardRestController 만들기

@RestController
public class BoardRestController {
	@Autowired
	private BoardDAO dao;
	
	//VueJS에서 페이지 전송
	@GetMapping(value = "board/list_vue.do",produces = "text/plain;charset=utf-8")
	public String board_list_vue(String page)
	{
		if(page==null)
			page="1";
		int curpage=Integer.parseInt(page);
		Map map=new HashMap();
		int rowSize=10;
		int start=(rowSize*curpage)-(rowSize-1);
		int end=rowSize*curpage;
		
		map.put("start", start);
		map.put("end", end);
		
		List<BoardVO> list=dao.boardListData(map);
		int totalpage=dao.boardTotalPage();
		
		//JavaScript에 데이터를 전송
		String result="";
		try
		{
			//list보낼때 => Array 사용(JSONArray)
			//vo보낼때 => object 사용(JSONObject)
			//==> Javascript의 공식
			
			//object에 있는거 10개를 list에 모아라!(10개씩 나누기로 했으니까)
			JSONArray arr=new JSONArray();
			int k=0;
			for(BoardVO vo:list)
			{
				JSONObject obj=new JSONObject();
				obj.put("no", vo.getNo());
				obj.put("subject", vo.getSubject());
				obj.put("name", vo.getName());
				obj.put("dbday", vo.getDbday());
				obj.put("hit", vo.getHit());
				if(k==0)
				{
					obj.put("curpage", curpage);
					obj.put("totalpage",totalpage);
				}
				arr.add(obj);
				k++;
			}
            result=arr.toJSONString();
		}catch(Exception ex) {}
		return result;
	}
    
    @GetMapping(value = "board/insert_vue.do",produces = "text/plain;charset=utf-8")
	public String board_insert_vue(BoardVO vo)
	{
		dao.boardInsert(vo);
		return "OK";
	}
}

JSONObject obj=new JSONObject() => VO를 받을 때 사용한다

JSONArray arr=new JSONArray() => list를 받을 때 사용한다

⭐️ 이걸로 받아야 Vue가 값을 인식 한다고 한다.
⭐️ 다음 코드와 같이 10개의 게시판을 동시에 보내야 할때는,
JSONObject로 값을 하나씩 받고, JSONArray로 값을 묶어서 저장해주면 된다.

📝 list.jsp 만들기

VueJS를 이용해서 화면 구상 시작!!

코드를 입력<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!-- Vue를 이용한 코딩 => JSTL,EL 필요없음(for문 돌릴필요없음) -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
.row1{
	width:850px;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
	<div class="container">
		<h1 class="text-center">VueJS를 이용한 목록 출력</h1>
		<div class="row row1">
			<table class="table">
			<tr>
				<td>
					<a href="../board/insert.do" class="btn btn-sm btn-primary">새글</a>
				</td>
			</tr>
				<tr>
					<th width=10% class="text-center">번호</th>
					<th width=45% class="text-center">제목</th>
					<th width=15% class="text-center">이름</th>
					<th width=20% class="text-center">작성일</th>
					<th width=10% class="text-center">조회수</th>
				</tr>
				<!-- VueJS의 for문 -->
				<tr v-for="vo in board_list">
					<th width=10% class="text-center">{{vo.no}}</th>
					<th width=45%>{{vo.subject}}</th>
					<th width=15% class="text-center">{{vo.name}}</th>
					<th width=20% class="text-center">{{vo.dbday}}</th>
					<th width=10% class="text-center">{{vo.hit}}</th>
				</tr>
			</table>
			<table class="table">
				<tr>
					<td class="text-center">
						<input type=button value="이전" class="btn btn-sm btn-danger">
						{{curpage}} page / {{totalpage}} pages
						<input type=button value="다음" class="btn btn-sm btn-danger">
					</td>
				</tr>
			</table>
		</div>
	</div>
	<script>
		new Vue({
			//el : 관리 영역 지정 => container
			el:'.container',
			data:{
				board_list:[],
				curpage:1,
				totalpage:0
			},
			mounted:function(){
				let _this=this;
				axios.get("http://localhost:8080/web/board/list_vue.do",{
					params:{
						page:_this.curpage
					}
				}).then(function(result){
					//개발자도구창에서 넘어온값 확인가능
					console.log(result.data);
					_this.board_list=result.data;
					_this.curpage=result.data[0].curpage;
					_this.totalpage=result.date[0].totalpage;
				})
			}
		})
	</script>
</body>
</html>

⭐️ ajax와 Vue 다른점 ⭐️

  • Vue는 JSTL/EL를 사용하지 않는다.(ajax 처럼 c:for 이런식으로 쓸 필요 없음)
    -> Vue는 v-for 이런식으로 쓴다.
  • script문을 문장의 하단에 쓴다!! (꼭 그래야하는건가??)
  • ajax는 변수 선언 시 ${변수명}으로 썼는데, Vue는 {{변수명}}으로 쓴다.
  • ajax는 name과 id값으로 값을 확인했는데, Vue는 v-model과 ref를 쓴다.
  • v-on:click 이라는 구문을 사용해서 클릭시 실행 할 동작을 제어한다.

그리고 Vue쓰려면 해당 구문을 넣어줘야한다 !

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

el:'.container' => 관리 영역 지정(나는 모든 구문을 제어 할 것이고, 구문들을 Container로
감싸줬기때문에 이렇게 썼다!

mounted:function() => 버튼을 클릭하거나 엔터를 치거나 이런 동작 없이 시작과 동시에
값을 가져온다.

console.log(result.data) => 값 잘넘어왔는지 '개발자도구' 창에서 확인 할수있게 하는 코드!

📝 insert.jsp 만들기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style type="text/css">
.row1 {
   margin: 0px auto;
   width: 700px;
}
h1 {
   text-align: center
}
</style>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
  <div class="container">
    <h1>글쓰기</h1>
    <div class="row row1">
      <table class="table">
       <tr>
         <th width=20% class="text-right">이름</th>
         <td width=80%>
           <input type=text v-model="name" size=20 class="input-sm" ref="name">
         </td>
       </tr>
       <tr>
         <th width=20% class="text-right">제목</th>
         <td width=80%>
           <input type=text v-model="subject" size=50 class="input-sm" ref="subject">
         </td>
       </tr>
       <tr>
         <th width=20% class="text-right">내용</th>
         <td width=80%>
           <textarea rows="10" cols="50" v-model="content" ref="content"></textarea>
         </td>
       </tr>
       <tr>
         <th width=20% class="text-right">비밀번호</th>
         <td width=80%>
           <input type=password v-model="pwd" size=15 class="input-sm" ref="pwd">
         </td>
       </tr>
       <tr>
        <td colspan="2" class="text-center">
          <input type=button value="글쓰기" class="btn btn-sm btn-warning" v-on:click="boardWrite()">
          <%--
             v-on:click="aaa()"
             @click="aaa()"
           --%>
          <input type=button value="취소" class="btn btn-sm btn-info"
            onclick="javascript:history.back()">
        </td>
       </tr>
      </table>
    </div>
  </div>
  <script>
  //입력하면 멤버변수 안에 값을 채워줌(name,subject...)
  	new Vue({
  		el:'.container',
  		data:{
  			name:'',
  			subject:'',
  			content:'',
  			pwd:''
  		},
  		methods:{
  			boardWrite:function(){
  				//this 안붙이면 지역변수로 인식 => this 꼭 붙이기
  				//유효성 검사 ) => 값이 공백이면 포커스 잡아줌
  				if(this.name.trim()=="")
  				{
  					this.$refs.name.focus();
  					return;
  				}
  				if(this.subject.trim()=="")
  				{
  					this.$refs.subject.focus();
  					return;
  				}
  				if(this.content.trim()=="")
  				{
  					this.$refs.content.focus();
  					return;
  				}
  				if(this.pwd.trim()=="")
  				{
  					this.$refs.pwd.focus();
  					return;
  				}
  				
  				//전송
  				axios.get("http://localhost:8080/web/board/insert_vue.do",{
  					//값 채워주기
  					params:{
  						name:this.name,
  						subject:this.subject,
  						content:this.content,
  						pwd:this.pwd
  					}
  				}).then(function(result){
  					location.href="../board/list.do";
  				})
  			}
  		}
  	})
  </script>
</body>
</html>

💻 결과 확인하기

✔️ 게시판 목록 조회(list)

✔️ 게시판 글 작성하기(Insert)


게시판 글 작성 페이지


작성 완료 후 모습!!!😝

Pagination은 고쳐야겠당 ..

profile
안녕하세요

0개의 댓글