Model2 - 게시판(Create...Write)

김정훈·2021년 2월 27일
0
post-thumbnail

📌 Model2 답변형 게시판 만들기

개요

  • Model2 방식으로 답변형 게시판을 구현한다.
  • 우선 기능은 기본적이 C.R.U.D이다.
  • 기본 기능을 다 구현하면, 기능을 조금씩 추가할 예정이다.

첫 번째는 글쓰기(Create) 기능을 구현해보자.

  1. 우선 게시글을 작성 후 담아줄 DB를 만들어보자.
create table myboard(
	num int primary key auto_increment,
	writer varchar(10) not null,
	email varchar(30) not null,
	subject varchar(20) not null,
	passwrod varchar(50) not null,
	reg_date timestamp default now(),
	know_ref int,   # 글 그룹
	re_step int,    # 글 스텝
	relevel int,    # 글 레벨
	readcount int default 0,
	content text not null
	);

DB와 프로젝트를 연결하고, DTO클래스와 DAO클래스는 밑에 부분에 정리!

주석 처리한 글 그룹(G)과, 글 스텝(S), 글 레벨(L) 부분이 이 게시판에서 가장 중요하다고 볼 수 있다.

ex> 내가 1번째 게시글을 "농구가 좋다"로 작성했다고 하자.
그럼 "농구가 좋다"의 G는 1, S도 1, L도 1이다.
자 그럼 2번째 글은 "운동이 싫다"로 작성했다.
그럼 "운동이 싫다"는 G는 2, S는 1, L은 1이다.

그러면 이제는 "농구가 좋다"1번째답글을 "나도 농구 좋아해"로 달아보자.
"나도 농구 좋아해"G는 1(농구가 좋다(부모글)) S는 2, L도 2이다.

여기서 "농구가 좋다"2번째 답글인 "나는 농구선수다"를 달았다.
그러면 "나는 농구선수다" G는 1, S는 2, L은 2가 되고!
"나도 농구 좋아해"의 L은 3이 되어버린다.

한번만 더 가면 끝이다.(대댓글)
"나도 농구 좋아해"라는 답글에 답글을 "포지션이 어디야"라고 달았다.
그러면 G는1, S는 3, L도 3이 된다.
L이 3이 되는 이유는 부모글인 "나도 농구 좋아해"의 L은 2이기 때문에 +1을 하게 되면 L이 3이 된다.
아니면 이 부분은 "포지션이 어디야"의 부모글의 L보다 +1을 해주면 된다고 생각

이 부분이 처음에는 이해가 잘 안 갔지만, 몇번 계속 읽고, 게시판을 만들어보니 이해가 가는 부분이었다.
답글형 게시판은 연습삼아 만들어 보는 것이지만, 
어차피 이 개념은 댓글 기능을 구현할 때에도 유용하게 쓰일 것 같으니 한 번 정리하고 가면 좋을 것 같다.
  1. 이제 뭐 기본적인 준비는 끝났고, Eclipse로 Dynamic Web Project를 생성해서 WebContent폴더에
    BoardWriteForm.jsp 파일을 작성해보자.

    Jsp생성시 상단부에 charset, pageEncoding 부분이 EUC-KR 되어있는 부분을 UTF-8로 바꿔주어야 한다. 아니면 나중에 DB로 넘어가는 한글이 깨질 수 있다.

  <%@ page language="java" contentType="text/html; charset=UTF-8 
  pageEncoding="UTF-8"%>
 <h2> 게시글 쓰기 </h2>
 	<form action="WriteProc" method="post">
    		<table width="600" border="1">
            		<tr height="40">
                			<td align="center" width="150"> 작성자 </td>
                            	<td width="450">
                                		<input type="text" name="writer" size="60">
                                 </td>
                          </tr>
                          <tr height="40">
                			<td align="center" width="150"> 제목 </td>
                            	<td width="450">
                                		<input type="subject" name="subject" size="60">
                                 </td>
                          </tr>
                          <tr height="40">
                			<td align="center" width="150"> 이메일 </td>
                            	<td width="450">
                                		<input type="email" name="email" size="60">
                                 </td>
                          </tr>
                          <tr height="40">
                			<td align="center" width="150"> 패스워드 </td>
                            	<td width="450">
                                		<input type="password" name="password" size="60">
                                 </td>
                          </tr>
                          <tr height="40">
                			<td align="center" width="150"> 글내용 </td>
                            	<td width="450">
                                		<textarea rows="10" cols="60" name="content"></textarea>
                                 </td>
                          </tr>
                          
                          <tr height="40">
                          	<td align="center" colspan="2">
                            		<input type="submit" value="글쓰기">&nbsp;&nbsp;
                                    	<input type="reset" value="내용을 다시 작성하기">&nbsp;&nbsp;
                                        	<button onclick="location.href='ListConnection'">게시글 리스트</button>
                                  </td>
                         </tr>
                   </table>
             </form>
             

이 부분은 복붙을 사용하던지 크게 상관없고,
그나마 중요한 부분은 form action="WriteProc"부분
==> 게시글을 저장하는 로직을 탄다.
button부분이다.
==> 게시글 리스트를을 띄우는 로직을 탄다.

  1. DTO데이터 전송객체인 BoardDTO를 만들어보자.
    우리가 게시글을 DB쪽으로 데이터 객체라고 생각하자.
public class BoardDTO {
	private int num;
	private String writer;
	private String email;
	private String subject;
	private String password;
	private String reg_date;
	private int know_ref;
	private int re_step;
	private int relevel;
	private int readcount;
	private String content;
	
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public String getReg_date() {
		return reg_date;
	}
	public void setReg_date(String reg_date) {
		this.reg_date = reg_date;
	}
	public int getKnow_ref() {
		return know_ref;
	}
	public void setKnow_ref(int know_ref) {
		this.know_ref = know_ref;
	}
	public int getRe_step() {
		return re_step;
	}
	public void setRe_step(int re_step) {
		this.re_step = re_step;
	}
	public int getRelevel() {
		return relevel;
	}
	public void setRelevel(int relevel) {
		this.relevel = relevel;
	}
	public int getReadcount() {
		return readcount;
	}
	public void setReadcount(int readcount) {
		this.readcount = readcount;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
    

이제 Connection Pool 을 연결하는데, 간단하게 알아보고 가자.
: 웹 컨테이너(톰캣)이 실행되면서<Tomcat - Server - server.xml 에서 설정> Connection 객체를 미리 Pool(풀)에 생성해둔다.
DB와 연결된 Connection을 미리 생성해서 Pool속에 저장해두고 있다가 필요할 때 가져다쓰고 반환한다.
미리 생성해두기 때문에 데이터베이스 부하를 줄이고 유동적으로 연결관리가 가능하다.

  1. 프로젝트의 Server폴더를 클릭해서 server.xml을 열어보자.

    제일 밑으로 내려보면 자신이 만든 프로젝트의 이름을 볼 수 있을 것이다. 밑에 코드를 참고!
<Context docBase="madeByMe" path="/madeByMe" reloadable~~>
	<!-- 추가 해야할 부분 -->
    <Resource auth="Container" driverClassName="com.mysql.jdbc.Driver" loginTimeout="10" maxWait="5000" 
    name="jdbc/mypool" password="mysql비번" type="javax.sql.DataSource"
    url="jdbc:mysql://localhost:mysql포트번호/데이터베이스이름?serverTimezone=UTC" username="root"/>
</Context>
</Host>

이렇게 해주고 이제 BoardDAO로 가서 Connection Pool을 사용할 수 있도록 설정해보자.

  1. BoardDAO.java
public void getCon(){

    try{
    	Context initctx= new InitialContext();
			
			Context envctx = (Context) initctx.lookup("java:comp/env");
			DataSource ds = (DataSource) envctx.lookup("jdbc/mypool");
			con = ds.getConnection();
		
		}catch(Exception e) {
			e.printStackTrace();
		}
     }

이 코드가 Connection Pool(DB)와 연결해주는 코드이다.
4, 5번은 Connection Pool의 개념을 아는 것이 중요하기 때문에 설정하는 방법은 그냥 이런 식으로 사용된다 정도만 알고 넘어가면 될 것 같다.

  1. BoardWriteProcCon.java코드 Mapping은 WriteProc
@WebServlet("/WriteProc")
public class BoardWriteProcCon extends HttpServlet{
	
    protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
    	reqPro(req, res)
    }
    protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
    	reqPro(req, res)
    }
    protected void reqPro(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException{
    request.setCharacterEncoding("UTF-8")
    // 한글 깨짐 처리
    
    	BoardDTO dto = new BoardDTO();
    	dto.setWriter(request.getParameter("writer"));
        dto.setSubject(requst.getParameter("subject"));
        dto.setEmail(request.getParameter("email"));
        dto.setPassword(request.getParameter("password"));
        dto.setContent(request.getParameter("content"));
        
        BoardDAO dao = new BoardDAO();
       	dao.insertBoard(dto);
        
        RequestDispatcher dis = request.getRequestDispatcher("ListConnection");
        dis.forward(req, res);
    	}
  • RequestDispatcher : 클라이언트로부터 요청받은 정보를 서버의 다른 자원(HTMl, JSP또는 Servlet등의 자원) 에 보내는 역할을 하는 인터페이스

여기서 dao.insertBoard(dto) 부분을 처리하게 되는 순간
BoardDAO클래스로 간다.

  • BoardDAO클래스의 insertBoard메소드를 살펴보자
public void insertBoard(BoardDTO dto){
	
    getCon();
    int know_ref=0;
    int re_step=1; // 새글이기 때문에
    int relevel=1; // 새글이기 때문에
    
    try{
    	//쿼리작성
        String refsql  = "select max(know_ref) from myboard";
        pstmt = con.prepareStatement(refsql);
        
        //쿼리를 실행한 후 결과를 리턴한다.
        rs=pstmt.executeQuery();
        if(rs.next()){
        //rs.next() : 쿼리의 결과 값이 있으면 ==> 그냥 true라고 생각하면 된다.
        	know_ref = rs.getInt(1)+1;
            /* 글 순서가 최신일수록 숫자가 높을 것이다
             거기에 숫자를 1 더해주면 최신글이 가장 클 것이고
             sql구문으로 최신글 순으로 정렬할 수 있게 된다. */
            
        // 데이터를 삽입하는 쿼리
        String sql = "insert into myboard value(null,?,?,?,?,now(),?,?,?,0,?)";
        
       	pstmt.executeUpdate();
        
        con.close();
      }catch(Exception e){
      		e.printStackTrace();
            }
         }

간단한 정리
executeUpdate : Select구문을 제외한 쿼리를 수행할 때 사용하는 함수, 수행결과로 int값을 반환한다.

executeQuery : Select구문을 사용할 때 사용되는 함수, 수행결과로 ResultSet 객체의 값을 반환한다.

  • 이제 이렇게하면 BoardWriteProc의 dao.insertBoard(dto)부분이 완료되고,
    RequestDispatcher dis = request.getRequestDispatcher("ListConnection"); 이 코드를 실행할 것이다. 이 코드는 Mapping이 "ListConnection"인 Servlet파일을 찾아갈 것이고, 이것은 글 목록을 보는 Servlet 파일로 만들 것이다.

⌘ 정리 : Jsp파일(BoardWriteForm) → Servlet파일(BoardWriteProcCon) → Java(BoardDAO)파일로 가서 Write(insertBoard)로직 수행 → 다시Servlet파일(BoardWriteProcCon) → ListConnection맵핑으로 이동

profile
WebDeveloper

0개의 댓글