게시글 검색 기능
검색어 색션에 검색어를 입력하면 해당하는 게시글만 보이게 하자.
[ 만들 기능 ]
1. 게시글 전체 검색 기능
2. 내 블로그에서 내 게시글로만 검색기능
1. 블로그 게시글 전체 검색 기능
검색을 블로그 메인 페이지에서 진행하면 전체 게시글 중에 검색하고(내것도 나옴), 내 블로그 안에서 하면 내가 작성한 게시글들만 검색되게 해보자.
1) jsp
mainPage.jsp 에서 검색 시 form 으로 보내주도록 하자. 옵션값을 줘서 제목 또는 내용으로 검색할 수 있게 할 것이다.
<div class="card-header">블로그 전체 검색</div>
<div class="card-body">
<form method="get" action="searchWordAction.me">
<div class="input-group">
<select name="option">
<option value="01" selected="selected">제목</option>
<option value="02">내용</option>
</select>
<input class="form-control" type="text" id="searchWord" name="searchWord" placeholder="검색어를 입력하세요" aria-label="Enter search term..." aria-describedby="button-search" />
<button class="btn btn-primary" id="button-search" type="submit">검색</button>
</div>
</form>
</div>
</div>
form을 통해 입력한 값을 searchWordAction.me로 보내줄 것임.
2) Controller
어차피 메인페이지에 게시글 리스트 띄우는 방식과 동일하다. 조건만 바뀐 것일 뿐. PostListAction을 복사해서 약간만 수정해서 쓰도록 할 것이다.
//-------------------- 메인페이지에서 검색하기 ---------------------------
else if (command.equals("/member/searchWordAction.me")) {
//get 방식으로 던졌고 아래 Action 페이지에서 getParameter로 받을 수 있음.
//name 값이 있어야 받음. id만 있어서는 못받음.
action = new SearchWordAction();
// SearchWordAction, 검색페이지
try {
forward = action.execute(req, resp);
System.out.println("검색 표시");
} catch (Exception e) {
e.printStackTrace();
}
}
3) Action
request.getParameter는 전부 String 형태로 받아지므로 Int형으로 변환해준다. 옵션값과 키워드 값을 Service에 들려보낸다.
또한 검색이 다 되면 검색페이지로 데이터를 뿌릴꺼니까 mainPage_search.jsp를 하나 만들어서 거기다 뿌려주자.
public class SearchWordAction implements Action {
@Override
public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//session을 써서 서버 생성함.
HttpSession session = req.getSession();
// 로그인할 때는 setSession해서 가져오고
// 여기 리스트에서는 get으로 뿌린다
String sessionId = (String) session.getAttribute("id");
//option값과 검색어 값을 form에서 받아온다.
//URL 주소 뒤에 붙은 쿼리스트링은 getParameter로 가져온다.
int option = Integer.parseInt(req.getParameter("option"));
String searchWord = req.getParameter("searchWord");
System.out.println("검색어: "+searchWord);
ActionForward forward = null; //어디로 갈지?
//1. 로그인 상태인지 확인
if (sessionId == null) {
// 세션에 저장된 아이디가 없다면~
forward = new ActionForward();
forward.setRedirect(true);
forward.setPath("./memberLogin.me");
//2. 게시글 목록 보여짐
} else {
// 검색된 게시글 목록 표시.
forward = new ActionForward();
PostListService postListService = new PostListService();
//배열로 검색한 게시글목록을 가져온다.
ArrayList<PostBean> postSearchList = postListService.getSearchList(option,searchWord);
req.setAttribute("postSearchList", postSearchList);
//mainPage로 게시글 목록을 던져준다.
forward.setPath("./mainPage_search.jsp");
}
return forward;
}
}
▼ mainPage_search.jsp 전체 소스
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="vo.MemberBean"%>
<%@ page import="java.util.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- 빨간줄 그어지는데 jstl 설치 안해서 그럼. lib에 넣어준다. jsp 확장태그로 c로 쓴다.-->
<!DOCTYPE html>
<html lang="ko">
<head>
<!-- 부트스트랩 출처 : https://startbootstrap.com/template/blog-home -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Blog Home</title>
<!-- Favicon-->
<!-- <link rel="icon" type="image/x-icon" href="assets/favicon.ico" /> -->
<!-- Core theme CSS (includes Bootstrap)-->
<link href="../resources/css/mainPage.css" rel="stylesheet" />
</head>
<body>
<!-- Responsive navbar-->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#!">N Blog</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#!">About</a></li>
<li class="nav-item"><a class="nav-link" href="#!">Contact</a></li>
<li class="nav-item"><a class="nav-link" href="myBlogAction.me?id=${sessionScope.id}">MyBlog</a></li>
</ul>
</div>
</div>
</nav>
<!-- Page header with logo and tagline-->
<header class="py-5 bg-light border-bottom mb-4">
<div class="container">
<div class="text-center my-5">
<h1 class="fw-bolder"> 검색결과를 확인합니다.</h1>
<p class="lead mb-0">내 게시글을 포함한 모든 포스팅을 검색합니다.</p>
</div>
</div>
</header>
<!-- Page content-->
<div class="container">
<div class="row">
<!-- Blog entries-->
<div class="col-lg-8">
<br>
<form method="get" action="searchWordAction.me">
<div class="input-group">
<select name="option">
<option value="01" selected="selected">제목</option>
<option value="02">내용</option>
</select>
<input class="form-control" type="text" id="searchWord" name="searchWord" placeholder="검색어를 입력하세요" aria-label="Enter search term..." aria-describedby="button-search" />
<button class="btn btn-primary" id="button-search" type="submit">검색</button>
</div>
</form>
<br>
<c:forEach var="postSearchList" items="${postSearchList}">
<!-- Featured blog post -->
<div class="card mb-4">
<div class="card-body">
<a href="#!"><img class="card-img-top" src="../resources/img/thumbnail/${postSearchList.POST_THUMBNAIL}" alt="..." /></a>
<div class="small text-muted">${postSearchList.POST_UPLOADTIME} / 조회수 : ${postSearchList.visit_cnt}</div>
<h2 class="card-title">${postSearchList.POST_TITLE} ----- ${postSearchList.MEM_NO}</h2>
<p class="card-text">${postSearchList.POST_CONTENT}</p>
<a class="btn btn-primary" href="postViewAction.me?postno=${postSearchList.POST_NO}">Read more →</a>
</div>
</div>
</c:forEach>
<!-- Pagination-->
<nav aria-label="Pagination">
<hr class="my-0" />
<ul class="pagination justify-content-center my-4">
<li class="page-item disabled"><a class="page-link" href="#" tabindex="-1" aria-disabled="true">Newer</a></li>
<li class="page-item active" aria-current="page"><a class="page-link" href="#!">1</a></li>
<li class="page-item"><a class="page-link" href="#!">2</a></li>
<li class="page-item"><a class="page-link" href="#!">3</a></li>
<li class="page-item disabled"><a class="page-link" href="#!">...</a></li>
<li class="page-item"><a class="page-link" href="#!">15</a></li>
<li class="page-item"><a class="page-link" href="#!">Older</a></li>
</ul>
</nav>
</div>
<!-- Side widgets-->
<div class="col-lg-4">
<br>
<!-- Categories widget-->
<div class="card mb-4">
<div class="card-header">${sessionScope.id} 님</div>
<div class="card-body">
<div class="row">
<div class="col-sm-6">
<ul class="list-unstyled mb-0">
<li><a class="btn btn-primary" href="myBlogAction.me?id=${sessionScope.id}">내 블로그</a></li>
<li><a href="myBlog.jsp">오늘 ??명 방문 ></a></li>
<li></li>
</ul>
</div>
<div class="col-sm-6">
<ul class="list-unstyled mb-0">
<li><a class="btn btn-primary" href="postInsert.me">새 게시물 작성</a></li>
<li><a href="logout">로그아웃</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container"><p class="m-0 text-center text-white">Copyright © Your Website 2022</p></div>
</footer>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<!-- <script src="js/scripts.js"></script> -->
</body>
</html>
4) Service
기존에 메인페이지에 게시글 리스트를 뿌렸던 PostListService에 클래스를 하나 추가해주자.(getSearchList)
public class PostListService {
//메인페이지 게시글 리스트 가져오기.
public ArrayList<PostBean> getPostList(String sessionId) {
...
}
//메인페이지에서 검색했을 때 전체 검색된 목록 가져오기.
public ArrayList<PostBean> getSearchList(int option, String searchWord) {
//커넥션 풀 : DB와 미리 연결해놓은 커넥션 객체들을 풀에 저장해뒀다가 클라에서 요청오면 객체 빌려주고 볼일 끝나면 다시 반납받아 풀에 저장하는 방식
Connection con = getConnection();
// DB와 연결을 얻어내고.
PostDAO postDAO = PostDAO.getInstance();
// DB접속용 DAO 객체 참조 얻어오기.(싱글톤 패턴 : 인스턴스가 1개만 생성됨)
// import static db.JdbcUtil.*;
postDAO.setConnection(con);
// 얻어온 커넥션 저장. -> 연결해서 할일 함.
ArrayList<PostBean> postList = postDAO.selectPostSearchList(option, searchWord);
//커넥션으로 DB에서 게시글 목록 받아서 배열에 저장
close(con);
// 사용을 마친 커넥션 반환
return postList;
// 게시글 목록 리턴.
}
5)DAO
가져온 옵션값에 따라 검색하는 SQL문을 달리해준다. SQL의 like 구문을 사용해 키워드를 검색한다.
//=========================== 메인페이지에서 전체게시글 검색하는 SQL로직 ===============================
public ArrayList<PostBean> selectPostSearchList(int option, String searchWord) {
String sql = "";
//옵션값에 따라 SQL문을 달리한다.
if(option == 01) {
//메인페이지에서 전체게시글 검색하는 SQL문(DB 이름 확인하기***)
sql = "select * from post_info where POST_TITLE like ?";
}else if(option == 02) {
sql = "select * from post_info where POST_CONTENT like ?";
}else {}
ArrayList<PostBean> PostSearchList = new ArrayList<PostBean>();
PostBean pb = null;
try {
pstmt = con.prepareStatement(sql);
//검색어가 어디에있던지 검색되게끔 앞뒤에 %를 붙여줌.
pstmt.setString(1, "%"+searchWord+"%");
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")); //게시글비디오
String preStr=rs.getString("POST_CONTENT");
pb.setPOST_CONTENT(preStr); //게시글내용 미리보기
pb.setVisit_cnt(rs.getInt("Visit_cnt")); //게시글조회수
pb.setPOST_UPLOADTIME(rs.getString("POST_UPLOADTIME")); //게시글업로드타임
//조회된 결과를 PostBean객체에 저장.
PostSearchList.add(pb);
//저장하면서 생성된 것을 이제 List에 담아냄.(ArrayList)
//반복문이 실행될 때마다 게시글 1개씩 누적 시킴.
} while (rs.next());
//rs.next때문에 어레이 리스트 다음 값으로 넘어간다.(차례차례 읽어옴)
}
} catch (Exception ex) {
System.out.println("PostSearchList 에러 : " + ex);
} finally {
close(rs);
close(pstmt);
}
return PostSearchList;
}
전체적으로 검색하기 위해 %%로 묶어서 검색하려고 하는데 어렵더라... 구글링해서 찾아낸 답...WOW
String sql = "select * from post_info where POST_TITLE like '%?%'"; //에러
//구글링 한건데 미쳤다...
sql="select * from table where name like ?";
pstmt=conn.prepareStatement(sql);
pstmt.setString(1,"%"+name+"%");
2. 내 블로그에서 내 게시글로만 검색기능
로직이 동일하다. SQL문 조건만 다를 뿐.
1) jsp
<div class="card-header">내 블로그에서 검색</div>
<div class="card-body">
<form method="get" action="searchWordMyAction.me">
<div class="input-group">
<select name="option">
<option value="01" selected="selected">제목</option>
<option value="02">내용</option>
</select>
<input class="form-control" type="text" id="searchWord" name="searchWord" placeholder="검색어를 입력하세요" aria-label="Enter search term..." aria-describedby="button-search" />
<button class="btn btn-primary" id="button-search" type="submit">검색</button>
</div>
</form>
</div>
▼ myBlog_search.jsp 전체 소스
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="vo.MemberBean"%>
<%@ page import="java.util.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- 빨간줄 그어지는데 jstl 설치 안해서 그럼. lib에 넣어준다. jsp 확장태그로 c로 쓴다.-->
<!DOCTYPE html>
<html lang="ko">
<head>
<!-- 부트스트랩 출처 : https://startbootstrap.com/template/blog-home -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>myBlog</title>
<!-- Favicon-->
<!-- <link rel="icon" type="image/x-icon" href="assets/favicon.ico" /> -->
<!-- Core theme CSS (includes Bootstrap)-->
<link href="../resources/css/mainPage.css" rel="stylesheet" />
</head>
<body>
<!-- Responsive navbar-->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#!">N Blog</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item"><a class="nav-link" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#!">About</a></li>
<li class="nav-item"><a class="nav-link" href="#!">Contact</a></li>
<li class="nav-item"><a class="nav-link active" aria-current="page" href="#">MyBlog</a></li>
</ul>
</div>
</div>
</nav>
<!-- 블로그 헤더 및 블로그 배경화면 -->
<header class="py-5 bg-light border-bottom mb-4" style="background-image: url('https://www.urbanbrush.net/web/wp-content/uploads/edd/2022/01/urbanbrush-20220105101328484351.jpg')">
<div class="container">
<div class="text-center my-5">
<h1 class="fw-bolder"> 검색결과를 확인합니다.</h1>
<p class="lead mb-0">내 게시글을 검색합니다.</p>
</div>
</div>
</header>
<!-- Page content-->
<div class="container">
<div class="row">
<!-- 왼쪽 블로그 소개 위젯-->
<div class="col-lg-3">
<!-- Side widget-->
<div class="card mb-4">
<img class="card-img-top" src="../resources/img/blog/${mySearchList[0].MEM_PIC}" alt="..." />
<div class="card-header">${mySearchList[0].MEM_ID}</div>
<div class="card-body">블로그 소개글 쓰는 곳.맛집을 좋아하는 ㅇㅇ의 블로그입니다! 이미지는 일단 고정으로 박아뒀지롱...</div>
</div>
<!-- Categories widget-->
<div class="card mb-4">
<div class="card-header">카테고리?</div>
<div class="card-body">
<div class="row">
<div class="col-sm-6">
<ul class="list-unstyled mb-0">
<li><a href="postEdit.jsp">내 블로그</a></li>
<li><a href="#">오늘 ??명 방문 ></a></li>
<li></li>
</ul>
</div>
<div class="col-sm-6">
<ul class="list-unstyled mb-0">
<li><a href="postInsert.me">새글작성</a></li>
<li><a href="logout">로그아웃</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- 오른쪽 Blog 게시글 내용-->
<div class="col-lg-9">
<form method="get" action="searchWordMyAction.me">
<div class="input-group">
<select name="option">
<option value="01" selected="selected">제목</option>
<option value="02">내용</option>
</select>
<input class="form-control" type="text" id="searchWord" name="searchWord" placeholder="검색어를 입력하세요" aria-label="Enter search term..." aria-describedby="button-search" />
<button class="btn btn-primary" id="button-search" type="submit">검색</button>
</div>
</form>
<br>
<c:forEach var="mySearchList" items="${mySearchList}">
<!-- Featured blog post -->
<div class="card mb-4">
<div class="card-body">
<a href="#!"><img class="card-img-top" src="../resources/img/thumbnail/${mySearchList.POST_THUMBNAIL}" alt="..." /></a>
<div class="small text-muted">${mySearchList.POST_UPLOADTIME} / 조회수 : ${mySearchList.visit_cnt}</div>
<h2 class="card-title">${mySearchList.POST_TITLE} ----- ${mySearchList.MEM_NO}</h2>
<p class="card-text"> ${mySearchList.POST_CONTENT} </p>
<a class="btn btn-primary" href="postViewAction.me?&postno=${mySearchList.POST_NO}">Read more →</a>
</div>
</div>
</c:forEach>
</div>
</div>
</div>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container"><p class="m-0 text-center text-white">Copyright © Your Website 2022</p></div>
</footer>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<!-- <script src="js/scripts.js"></script> -->
</body>
</html>
2) controller
//-------------------- 내블로그에서 내 게시글 검색하기 ---------------------------
else if (command.equals("/member/searchWordMyAction.me")) {
//get 방식으로 던졌고 아래 Action 페이지에서 getParameter로 받을 수 있음.
//name 값이 있어야 받음. id만 있어서는 못받음.
action = new SearchWordMyAction();
// SearchWordMyAction, 검색페이지
try {
forward = action.execute(req, resp);
System.out.println("검색 표시");
} catch (Exception e) {
e.printStackTrace();
}
}
3) Action
세션 ID 값까지 총 3개의 값을 보내줘야함.
public class SearchWordMyAction implements Action {
@Override
public ActionForward execute(HttpServletRequest req, HttpServletResponse resp) throws Exception {
//session을 써서 서버 생성함.
HttpSession session = req.getSession();
// 세션에서 id값 가지고 있기.
String sessionId = (String) session.getAttribute("id");
//option값과 검색어 값을 form에서 받아온다.
//URL 주소 뒤에 붙은 쿼리스트링은 getParameter로 가져온다.
int option = Integer.parseInt(req.getParameter("option"));
String searchWord = req.getParameter("searchWord");
System.out.println("검색어: "+searchWord);
ActionForward forward = null; //어디로 갈지?
// 내 게시글 목록 및 내용 표시.
forward = new ActionForward();
MyPostListService myPostListService = new MyPostListService();
//배열로 게시글 목록을 가져온다. id는 같이 던져줘야 읽음.
ArrayList<PostBean> mySearchList = myPostListService.getMySearchList(sessionId,option,searchWord);
req.setAttribute("mySearchList", mySearchList);
//검색된 게시글 목록을 던져준다.
forward.setPath("./myBlog_search.jsp");
return forward;
}
}
4) Service
public class MyPostListService {
public ArrayList<PostBean> getMyPostList(String sessionId) {
...
}
//내 게시글 검색
public ArrayList<PostBean> getMySearchList(String sessionId, int option, String searchWord) { //리스트이므로 배열로 가져온다.
//커넥션 풀 : DB와 미리 연결해놓은 커넥션 객체들을 풀에 저장해뒀다가 클라에서 요청오면 객체 빌려주고 볼일 끝나면 다시 반납받아 풀에 저장하는 방식
Connection con = getConnection();
// DB와 연결을 얻어내고.
PostDAO postDAO = PostDAO.getInstance();
// DB접속용 DAO 객체 참조 얻어오기.(싱글톤 패턴 : 인스턴스가 1개만 생성됨)
// import static db.JdbcUtil.*;
postDAO.setConnection(con);
// 얻어온 커넥션 저장. -> 연결해서 할일 함.
ArrayList<PostBean> mySearchList = postDAO.selectMySearchList(sessionId,option, searchWord); //selectMyPostList는 PostDAO에서 받아온다.
//커넥션으로 DB에서 게시글 목록 받아서 배열에 저장
close(con);
// 사용을 마친 커넥션 반환
return mySearchList;
// 게시글 목록 리턴.
}
}
5) DAO
where m.mem_id = [세션ID값] AND POST_CONTENT like [키워드]
조건 두개를 AND로 묶어서 검색한다.
//=========================== 내 블로그 게시글을 검색하는 SQL로직 ===============================
public ArrayList<PostBean> selectMySearchList(String sessionId, int option, String searchWord) {
// ArrayList: 객체 배열 비슷, 컬렉션 프로임워크
// 여러 개의 게시글 정보를 저장한다.
String sql = "";
if(option == 01) {
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 = ? AND POST_TITLE like ?";
}else if(option == 02) {
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 = ? AND POST_CONTENT like ?";
}else {}
ArrayList<PostBean> mySearchList = new ArrayList<PostBean>();
PostBean pb = null; //Bean(vo)은 그릇이다. 뭘 가져올지는 vo에 목록이 있다.
try {
pstmt = con.prepareStatement(sql);
//세션 id값 가져와서 SQL 문에 넣어줌.
pstmt.setString(1, sessionId);
//검색어가 어디에있던지 검색되게끔 앞뒤에 %를 붙여줌.
pstmt.setString(2, "%"+searchWord+"%");
...
▼ 진행중인 gitHub 링크를 남깁니다.
'Project > 블로그 프로젝트' 카테고리의 다른 글
네이버 블로그 만들기 프로젝트(8) - 게시글 수정하기(이미지 업로드 포함) (2) | 2022.12.13 |
---|---|
네이버 블로그 만들기 프로젝트(7) - 게시글에 사진 첨부하기(multipart로 ajax 통신) (2) | 2022.12.13 |
네이버 블로그 만들기 프로젝트(6) - Naver SmartEditor 2.0으로 게시글 만들기(+DB연결) (2) | 2022.11.04 |
네이버 블로그 만들기 프로젝트(5) - 내 블로그 페이지 만들기 / 나만 내 게시글 삭제하기 (1) | 2022.10.28 |
네이버 블로그 만들기 프로젝트(4) - 게시글 상세페이지 연결 (1) | 2022.10.27 |
댓글