본문 바로가기
Project/블로그 프로젝트

네이버 블로그 만들기 프로젝트(5) - 내 블로그 페이지 만들기 / 나만 내 게시글 삭제하기

by 히앤님 2022. 10. 28.
반응형
SMALL

내 블로그 페이지 만들기

이젠 반복작업이다. 저번 포스팅의 위젯을 그대로 따고, 내 블로그 페이지에는 세션에 있는 회원의 정보를 띄워주도록 하자.

[ 만들 기능 ]
1. 내 블로그 클릭하면 내가 쓴 게시글 목록이 나오게 하기
2. 게시글 목록을 클릭하면 게시글 상세페이지로 이동
3. 위젯에 내 프로필 사진과 ID를 띄움
4. 세션 ID = 게시글 쓴 사람 이면 삭제버튼이 보이게 하기
5. 게시글 삭제 기능 구현

1. 메인페이지에서 내 블로그 클릭하면 내가 쓴 게시글 목록이 나오게 하기

간단하게 링크를 걸어준다.

1) JSP

<li class="nav-item"><a class="nav-link" href="myBlogAction.me?id=${sessionScope.id}">MyBlog</a></li>

로그인한 '내' 블로그에 가는 것이므로 sessionScope.id를 사용해준다.

2) Controller

//-------------------- 내 블로그 페이지를 보여주는 myBlogAction 페이지 생성 ---------------------------
else if (command.equals("/member/myBlogAction.me")) {
    action = new MyBlogAction();
    // MyBlogAction, 내 블로그 페이지 표시.
    try {
        forward = action.execute(req, resp);
        System.out.println( "내 블로그 페이지 표시"))
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

3) Action

내 블로그에는 내가 쓴 게시글 목록을 띄울 것이다. sessionId가 있어야 내 블로그인 줄 알테니까 sessionId 생성 후 Service에 같이 던져준다.

package action;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import svc.MyPostListService;
import vo.ActionForward;
import vo.PostBean;

/* 인터페이스를 함께 추가했다. 내 블로그 표시를 위한 클래스이다.*/
public class MyBlogAction implements Action {

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {

		//session을 써서 서버 생성함.
		HttpSession session = req.getSession();
		// 세션에서 id값 가지고 있기.
		String sessionId = (String) session.getAttribute("id");
		ActionForward forward = null; //어디로 갈지?

			// 내 게시글 목록 및 내용 표시.
			forward = new ActionForward();
			MyPostListService myPostListService = new MyPostListService();
			//배열로 게시글 목록을 가져온다. id는 같이 던져줘야 읽음.
			ArrayList<PostBean> myPostList = myPostListService.getMyPostList(sessionId);

			req.setAttribute("myPostList", myPostList);
			
			//mainPage로 게시글 목록을 던져준다.
			forward.setPath("./myBlog.jsp");
		
		return forward;
	}
}

4) Service

DB연결해서 커넥션 풀 열고 닫기

package svc;
import static db.JdbcUtil.close;
import static db.JdbcUtil.getConnection;
import java.sql.Connection;
import java.util.ArrayList;
import DAO.PostDAO;
import vo.PostBean;


/* 내 게시글를 띄울 시 DB와 JSP를 연결해주는 역할을 담당하는 클래스(Service) */
public class MyPostListService {
	
	public ArrayList<PostBean> getMyPostList(String sessionId) { //리스트이므로 배열로 가져온다.
		//커넥션 풀 : DB와 미리 연결해놓은 커넥션 객체들을 풀에 저장해뒀다가 클라에서 요청오면 객체 빌려주고 볼일 끝나면 다시 반납받아 풀에 저장하는 방식
		Connection con = getConnection();
		// DB와 연결을 얻어내고.
		PostDAO postDAO = PostDAO.getInstance();
		// DB접속용 DAO 객체 참조 얻어오기.(싱글톤 패턴 : 인스턴스가 1개만 생성됨)
		// import static db.JdbcUtil.*;
		postDAO.setConnection(con);
		// 얻어온 커넥션 저장. -> 연결해서 할일 함.
		ArrayList<PostBean> myPostList = postDAO.selectMyPostList(sessionId); //selectMyPostList는 PostDAO에서 받아온다.
		//커넥션으로 DB에서 게시글 목록 받아서 배열에 저장

		close(con);
		// 사용을 마친 커넥션 반환
		return myPostList;
		// 내 게시글 목록 리턴.
	}
}

5) DAO

내 블로그 게시글 목록을 가져온다. 목록이므로 미리보기처럼 보일 수 있게 게시글 내용은 15자 이내로 자르고, 회원 테이블에서 ID값과 pic을 가져와서 넣어준다.

//=========================== 내 블로그 게시글을 가져와 보여주는 SQL로직 ===============================
public ArrayList<PostBean > selectMyPostList(String sessionId) {
    // ArrayList: 객체 배열 비슷, 컬렉션 프로임워크
    // 여러 개의 게시글 정보를 저장한다.

    //디비에 저장된 내 게시글 목록을 확인하는 SQL문(DB 이름 확인하기***)
    String sql =  "select p.*,m.mem_id,m.mem_pic from post_info p join memberinfo m on p.mem_no = m.mem_no where m.mem_id = ?"

    ArrayList<PostBean> myPostList = new ArrayList<PostBean>();
    PostBean pb = null; //Bean(vo)은 그릇이다. 뭘 가져올지는 vo에 목록이 있다.

    try {
        pstmt = con.prepareStatement(sql);

        //세션 id값 가져와서 SQL 문에 넣어줌.
        pstmt.setString(1, sessionId);
        System.out.println( "sessionId : "+sessionId))

        rs = pstmt.executeQuery(); //executeQuery : resultSet 객체 반환
        //select는 executeQuery()를 사용한다.
        //쿼리문 처리결과 ResultSet의 객체인 rs에 저장.

        if (rs.next()) {
            //조회된 결과가 있다면 아래 문장 수행.
            do {
                //한 번 수행하고 또 수행할 게 있으면 수행.
                pb = new PostBean();
                //게시글 1개의 정보를 저장할 수 있는 PostBean 객체 생성.
                pb.setPOST_NO(rs.getInt( "POST_NO"))) //게시글번호
                pb.setMEM_NO(rs.getInt( "MEM_NO"))) //회원번호
                pb.setPOST_TITLE(rs.getString( "POST_TITLE"))) //게시글제목
                pb.setPOST_THUMBNAIL(rs.getString( "POST_THUMBNAIL"))) //게시글섬네일
                pb.setPOST_VIDEO(rs.getString( "POST_VIDEO"))) //게시글비디오					

                //--- 게시글 내용 가져와서 15자만 미리보기로 보여줌 ---
                String preStr=rs.getString( "POST_CONTENT"))
                if(preStr.length() > 30) {
                    preStr=preStr.substring(0,15)+ "..." //자르고 ... 붙이기
                };
                pb.setPOST_CONTENT(preStr); //게시글내용 미리보기
                //----------------------------------------

                pb.setVisit_cnt(rs.getInt( "Visit_cnt"))) //게시글조회수
                pb.setPOST_UPLOADTIME(rs.getString( "POST_UPLOADTIME"))) //게시글업로드타임

                //위젯에 띄울 내 회원정보
                pb.setMEM_id(rs.getString( "MEM_ID"))) //게시글 쓴 회원 id
                pb.setMEM_PIC(rs.getString( "MEM_PIC"))) //게시글 쓴 회원 사진

                //조회된 결과를 PostBean객체에 저장.
                myPostList.add(pb);
                //저장하면서 생성된 것을 이제 List에 담아냄.(ArrayList)
                //반복문이 실행될 때마다 게시글 1개씩 누적 시킴.
            }
            while (rs.next());
            //rs.next때문에 어레이 리스트 다음 값으로 넘어간다.(차례차례 읽어옴)
        }
    }
    catch (Exception ex) {
        System.out.println( "selectMyPostList 에러 : " + ex))
    }
    finally {
        close(rs);
        close(pstmt);
    }
    return myPostList;
}

6) VO

vo에 있는 PostBean의 정보는 이전글 참고. 아래 두가지를 추가했다.

private String MEM_ID;
private String MEM_PIC;

결과창

2. 게시글 목록을 클릭하면 게시글 상세페이지로 이동

동일하게 상세보기 페이지로 연결해주면 된다. 그럼 상세보기 페이지이지만 위젯 내역은 똑같이 보이니 페이지가 이동하지 않은 상태로 내용만 바뀐 것처럼 보인다.

  <a class="btn btn-primary" href="postViewAction.me?postViewAction.me?postno=${myPostList.POST_NO}">Read more →</a>

 

3. 위젯에 내 프로필 사진과 ID를 띄움

1번 항목 참조.

 

나만 내 게시글 삭제하기

 

4. 세션 ID = 게시글 쓴 사람 이면 삭제버튼이 보이게 하기

요걸 버튼으로 사용해보자.

세션 ID를 어떻게 가져올까 하다가...공부하는 겸 해서 자바스크립트 단에서 display : none 처리로 간단하게 해보기로 했다.

자바스크립트에 java 코드를 사용해본다. 서버 session에 있는 id값을 가져왔다.

<div class="text-muted fst-italic mb-2">${postObj.POST_UPLOADTIME} 
by <b id="memId">${postObj.MEM_ID}</b></div>

<!--회원id를 b태그로 감싸서 id를 부여해줬다.-->

<script>
        var sessionId = '<%=(String)session.getAttribute("id")%>';
        var post_writer = document.getElementById('memId').innerText;
        console.log(typeof(sessionId),typeof(post_writer)); //string,string
        //세션 id가 포스트작성자가 아니면, 수정버튼과 삭제버튼 안보임.
        if (sessionId != post_writer){
        	 document.getElementById("post_update").style.display ='none';
        	 document.getElementById("post_delete").style.display ='none';
        	 console.log("내 게시글 아님. 수정 불가");
        };
		
</script>

세션 아이디와 다름
세션 아이디와 같음

물론 좋은 방법은 아니다.

말 그대로 css로 감춘 것이기 때문에 스크립트에 노출되어 있으며, display : none 속성을 브라우저에서 없애주면 버튼이 보여지게 된다.

개발자 도구에서 버튼 발굴(?) 가능

하지만 이렇게 한 이유는 귀찮은 건 아니고 자바스크립트에서 세션값을 가져오는 방법을 사용해보기 위함이며, 수정 화면에 이동할 시, session에 있는 사용자가 수정권한이 있는지 컨트롤러 단에서 다시 확인할 것이기 때문이다.

컨트롤러 단에서 이걸 어떻게 받을까 고민하다가 postNo와 같이 get 방식으로 mem_id값도 보내주기로 했다.(2번 참고)

 

5. 게시글 삭제 기능 구현

삭제기능만 우선 구현해보자.

1) JSP

삭제버튼 클릭 시 해당 게시글 번호와 작성자를 쿼리스트링으로 보내줌

<a class="badge bg-secondary text-decoration-none link-light" href="postDeleteAction.me?writer=${postObj.MEM_ID}&postno=${postObj.POST_NO}" id="post_delete">삭제</a>

get 방식으로 보낼 때 파라미터에 작성자 id값도 함께 보내준다. 컨트롤러 단에서 확인할 것이기 때문!!

쿼리스트링을 보낼 때에는 &로 묶어서 보내준다.

2) Controller

//-------------------- 내 게시글을 삭제하는 postDeleteAction 페이지 생성 ---------------------------				
else if (command.equals("/member/postDeleteAction.me")) {
    action = new PostDeleteAction();
    // PostDeleteAction, 삭제 후 페이지 표시.
    try {
        forward = action.execute(req, resp);
        System.out.println( "게시글 삭제"))
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

3) Action

로그인 상태인지, 사용자가 게시글 작성자가 맞는지를 확인한다.

브라우저 alert를 띄우기 위해 resp.getWriter()를 이용해서 println으로 스크립트를 띄워주었다.

가져온 작성자 id값과 게시글 번호를 통해 분기한다.

package action;
import java.io.PrintWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import svc.PostDeleteService;
import vo.ActionForward;

public class PostDeleteAction implements Action {

	@Override
	public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {

		HttpSession session = req.getSession();
		String id = (String) session.getAttribute("id");
		// 로그인하면, id는 session에 저장되어 있다.
		String post_writer = req.getParameter("writer");
		int postNo = Integer.parseInt(req.getParameter("postno"));
		System.out.println("writer"+post_writer);

		ActionForward forward = null;
		// 로그인 상태인지 확인 -> 아니면 로그인화면 고고
		if (id == null) {
			forward = new ActionForward();
			forward.setRedirect(true);
			forward.setPath("./memberLogin.me");
			
		// 사용자가 작성자가 맞는지 확인 -> 아니면 alert를 띄우고 해당 포스트로 다시 이동
		} else if (!id.equals(post_writer)) {
			resp.setContentType("text/html;charset=UTF-8");
			PrintWriter out = resp.getWriter();
			out.println("<script>");
			out.println("alert('작성자가 아닌 사람은 게시글을 삭제할 수 없습니다.')");
			out.println("location.href='./postViewAction.me?postno="+postNo+"'");
			out.println("</script>");		

		//사용자가 작성자면 삭제가 가능하다.
		} else {
			//Service에 삭제한 게시물 번호를 함께 넘겨준다.
			PostDeleteService postDeleteService = new PostDeleteService();
			boolean deleteResult = postDeleteService.deletePost(postNo);
			
			// delete 하면 내 블로그로 이동
			if (deleteResult) {
				resp.setContentType("text/html;charset=UTF-8");
				PrintWriter out = resp.getWriter(); 
				out.println("<script>");
				out.println("alert('삭제되었습니다.');");
				out.println("location.href='./myBlogAction.me'");
				out.println("</script>");

			// delete 실패하면 alert 발생 후 해당 포스트로 다시 이동
			} else {
				resp.setContentType("text/html;charset=UTF-8");
				PrintWriter out = resp.getWriter(); 
				out.println("<script>");
				out.println("alert('삭제 실패');");
				out.println("location.href='./postViewAction.me?postno="+postNo+"'");
				out.println("</script>");
			}
		}
		return forward;	
	}
}

4) Service

DB연결해서 커넥션 풀 열고 닫기. 게시글 번호는 계속 가지고 간다.

package svc;

import static db.JdbcUtil.close;
import static db.JdbcUtil.commit;
import static db.JdbcUtil.getConnection;
import static db.JdbcUtil.rollback;
import java.sql.Connection;
import DAO.PostDAO;

public class PostDeleteService {

	public boolean deletePost(int postNo) {
		boolean deleteResult = false;
		Connection con = getConnection();
		PostDAO postDAO = PostDAO.getInstance();
		postDAO.setConnection(con);
		int deleteCount = postDAO.deletePost(postNo);

		//지우면 지웠다고 결과 1 리턴 아니면 롤백
		if (deleteCount > 0) { 
			commit(con);
			deleteResult = true;
		} else {
			rollback(con);
		}
		close(con);
		return deleteResult;
	}

}

5) DAO

내 블로그 게시글 목록을 가져온다. 목록이므로 미리보기처럼 보일 수 있게 게시글 내용은 15자 이내로 자르고, 회원 테이블에서 ID값과 pic을 가져와서 넣어준다.

//=========================== 게시글을 삭제하는 SQL로직 ===============================
// PostDeleteService에서 게시글 삭제 시 DB와 JSP를 연결할 때 인자로 쓰임.
public int deletePost(int postNo) {
    //우클릭 Create method
    // 해당 게시글을 삭제하는 SQL문(DB 이름 확인하기***)
    String sql =  "delete from post_info where post_No=?"
    int deleteCount = 0; //삭제 유무

    try {
        pstmt = con.prepareStatement(sql);
        pstmt.setInt(1, postNo); //가져온 게시글 번호 보내주기
        pstmt.executeUpdate();
        deleteCount = 1;
    }
    catch(Exception ex) {
        System.out.println( "삭제 안됨"))
        deleteCount = 0;
    }
    finally {
        close(rs);
        close(pstmt);
    }
    return deleteCount;
}

6) VO

vo에 있는 PostBean의 정보는 이전글 참고.

결과창 : 유저가 자기 게시글을 삭제함

css로 버튼을 감췄기 때문에 display:none을 풀어서(?) 삭제 버튼을 활성화시킬 수도 있다. 이 때 alert가 발생하면서 다시 해당 페이지로 이동한다.

결과창 : 유저가 다른사람 게시글을 삭제할 경우 alert 발생

 

 

▼ 진행중인 gitHub 링크를 남깁니다.

 

GitHub - k-haein/BlogPrj: 회원가입/로그인/게시글 등록 등의 블로그를 처음부터 만듭니다.

회원가입/로그인/게시글 등록 등의 블로그를 처음부터 만듭니다. Contribute to k-haein/BlogPrj development by creating an account on GitHub.

github.com

 

반응형
LIST

댓글