• 비디오

 

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Document</title>

</head>

<body>

    <h1>SUMMER BEACH</h1>

    <video width="400" height="220" controls autoplay>

        <source src="media/Beach.mp4" type="video/mp4">

        <source src="media/Beach.webm" type="video/webm">

    </video>

</body>

</html>

 


 

  • 오디오

 

 

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>멀티미디어 재생</title>

    <style>

        #con{

            width: 600px;

            margin: 0 auto;

            padding: 20px;

        }

    </style>

</head>

<body>

    <div id="con">

        <h1>오디오 재생하기</h1>

        <audio src="media/bgsound2.mp3" controls>

        </audio>

    </div>

</body>

</html>

 

 

 

'Learning > HTML&JavaScript' 카테고리의 다른 글

자바스크립트  (0) 2020.07.24
CSS3 선택자  (0) 2020.07.24
HTML5 시멘틱 태그  (0) 2020.07.24
CSS 레이아웃  (0) 2020.07.21
CSS와 박스 모델  (0) 2020.07.21
  • <header>: 머리말

  • <nav>: 네비게이션 링크

  • <section>: 주제별 콘텐츠 영역

  • <article>: 콘텐츠 내용

  • <aside>: 본문 이외의 내용

  • <iframe>: 외부 문서 삽입

  • <footer>: 제작 정보와 저작권 정보

  • <address>: 제작자 정보와 연락처 정보

 

 


 

<!doctype html>

<html lang="ko">

<head>

<meta charset="utf-8">

<title>요안도라</title>



<link href="css/style3.css" rel="stylesheet" type="text/css"><!--[if lt IE 9]>

<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

<![endif]-->

</head>



<body>

    <div class="container">

    <header>

        <h1>Joandora</h1>

        <h2>가장 제주다운 수산리집</h2>

    </header>

    <nav class="navi">

        <ul>

            <li><a href="#">이용 안내</a></li>

            <li><a href="#">객실 소개</a></li>

            <li><a href="#">예약 방법</a></li>

            <li><a href="#">예약 하기</a></li>

        </ul>

    </nav>

    <section class="content">

        <h2>요안도라 소개</h2>    

        <h3>¤ 요안도라는 게스트 하우스(Guest House) 형식의 농어촌 민박입니다</h3>

        <p>성산의 날씨는 다음주 내내 높은 구름에 햇살 가득이라고 합니다. 목요일이면 섭씨 27도까지 오른다고 하지만, 늘 부는 바람이 쾌적한 균형을 잡아 마당에 마당에 나가 앉아 있는 시간이 많아질듯 합니다.</p>

        <p>오늘은 사진에 보이는 긴 돌담을 따라 들어오는 요안도레 올레 입구에 특곤색의 대문을 달았습니다.</p>

        <p>내일은 두달 여동안 밖거리에 만든 데스트 하우스에 연백색의 황토 페인트를 칠할 예정입니다.<br>

        그리고 이것저것 사소한 저이를 마치고 나면, 나이 드시고 젊고 한 미지의 새식구들을 설렘으로 만나고 함께하고, 도시의 바븐 생활로 소원해진 오래된 친구와의 우정을 이 제주에서 새롭게 열어나가기 위해 요안도라를 세상에 알리려고 합니다.</p>

        <img src="images/banner2.png" width="700" height="233" alt="요안도라">

    </section>

    <aside class="sidebar">

        <h3>¤ 알립니다</h3>

        <p>게스트하우스 예약은 전화 070-###-#### 로 직접 통화하시는게 가장 정확하고 빠릅니다.

        인터넷 전화이므로 시외 전화 요금이 부과되지 않습니다. </p>

        <img src="images/2.jpg" alt="">

        <img src="images/1.jpg" alt="">

        <img src="images/4.jpg" alt="">

    </aside>

    <footer>

        <address>

            <p>제주특별자치도 남제주군 성산읍 수산리 000 번지 요안도라 </p>

            <p>yoan##@naver.com</p>

        </address>

            <p> Copyright ⓒ. All rights reserved.</p>      

    </footer>

    </div>

</body>

</html>

 

@charset "utf-8";

body {
	font: 14px 맑은 고딕;
}
.container {
	position:absolute;
	width: 960px;
	margin : 0 auto;
	background-color:#fff;
	border:1px solid #E7E7E7
}
header {
	position:relative;
	height: 280px;
	background-image: url('../images/bg.png');
	background-repeat: no-repeat;
	background-position: left top;
}
header h1{
	position:absolute;
	right:20px;
	bottom:70px;
	font-size:3em;		
	color:#FFC;	
	text-shadow:1px 2px 2px #000;		
}
header h2{
	position:absolute;
	right:20px;
	bottom:30px;
	font-size:2em;
	color:#FF0;	
	text-shadow:0px 1px 1px #000;	
}
.navi{
	position:relative;
	background:#271717;
	margin-top:-15px;
	width:960px;
	height:60px;
}

.navi ul{
	list-style: none; 
	height:40px;
	padding-top:10px;
	padding-bottom:5px;
}
.navi ul li {
	display:inline;
	font-size:15px;
}
.navi a, .navi a:visited {
	padding: 10px 5px 5px 35px;
	display: inline;
	color:#fff;
	width: 150px; 
	text-decoration: none;

}
.navi a:hover, .navi a:active, .navi a:focus {
		text-shadow:0px 2px 2px #000;
		color:#FC0;
}

.sidebar {
	float: right;
	width: 200px;
	height:550px;
	background-color:#DFD;
	padding-top:20px;
	padding-left:10px;
	padding-right:10px;
}

.sidebar img {
	margin-bottom: 5px;
	border: 1px solid #ccc;
	opacity:0.5; 
	text-align:center;
}

.sidebar img:hover{
	border:1px solid #000;	
	opacity:1.0;
}
.content {
	background-color: #FFFFFF;	
	padding-top:5px;
	padding-left:10px;
	width: 720px;
	float: left;
}

footer {
	padding: 10px 0;
	background-color:#030;
	color:#fff;
	text-align:center;
	clear: both;
}

header, section, footer, aside, article, figure {
	display: block;
}

.banner {
	margin: 0 10px 15px 10px;
	padding:0;	
}

 

 


 

<!DOCTYPE html>
<html lang="ko">
<head>
	<meta charset="utf-8">
	<title>HTML5 레이아웃</title>
<style>
	h1{font-size: 2em;}
	h2{font-size: 1.5em;}
	h3{font-size: 1.0em;}
	p{
		line-height: 20px;
		font-size: 12px;
	}
	body{
		font-family: "맑은 고딕", "고딕", "굴림";
	}
	#con{
		width: 800px;
		margin: 0 auto;
	}
	header{
		width: 100%;
		height: 150px;
		background-color: #f46075;
		background-image: url(images/nav2.png);
		background-repeat: no-repeat;
		background-position: right center;
	}
	header nav{
		float: left;
		width: 70%;
		margin-top: 50px;
	}
	nav ul{
		list-style-type: none;
	}
	nav ul li{
		display: inline;
		float: left;
		font-weight: bold;
		margin: 10px;
	}
	nav ul li a{
		color: white;
		text-decoration: none;
	}
	a:hover{
		color: yellow;
	}
	section{
		float: left;
		width: 580px;
		padding: 5px;
	}
	section article{
		float: left;
		height: 250px;
		width: 220px;
		margin: 5px;
		padding: 15px;
		border: 1px dotted #ccc;
	}
	aside{
		float: right;
		width: 250px;
		height: auto;
		border: 1px solid darkgreen;
		text-align: center;
	}
	.at1, .at2, .at3, .at4{
		transition: 2s;
		-webkit-transition: 2s;
		-moz-transition: 2s;
		-o-transition: 2s;
		-ms-transition: 2s;
	}
	.at1:hover{
		background-color: #cf9;
		border:1px solid green;
	}
	.at2:hover{
		background-color: #a2d0ff;
		border:1px solid blue;
	}
	.at3:hover{
		background-color: #ebcbfe;
		border:1px solid purple;
	}
	.at4:hover{
		background-color: #fc3;
		border:1px solid red;
	}
	footer{
		clear: both;
		width: 800px;
		margin-bottom: 0;
		background-color: #333;
		color: white;
		text-align: center;
		height: 50px;
	}
</style>
</head>
<body>
	<header>
		<nav>
			<ul>
				<li><a href="#">애완견 종류</a></li>
				<li><a href="#">입양하기</a></li>
				<li><a href="#">건강돌보기</a></li>
				<li><a href="#">더불어살기</a></li>
			</ul>
		</nav>
	</header>
	<section>
		<div id="con"></div>
			<h2>강아지 용품 준비하기</h2>
			<article class="at1">
				<h3>강아지 집 </h3>
				<p>강아지가 편히 쉴 수 있는 포근한 집이 필요합니다. 강아지의 집은 강아지가 다 큰 후에도 계속 쓸 수 있는 집으로 구입하세요.집을 구입하실 때는 박음질이 잘 되어 있는지, 세탁이 간편한 제품인지 꼭 확인하시고 고르시는 것이 좋습니다.</p>
			</article>
			<article class="at2">
				<h3>강아지 먹이 </h3>
				<p>강아지의 먹이는 꼭 어린 강아지용으로 나와있는 사료를 선택하세요. 강아지들은 사람에 비해 성장속도가 8배정도 빠르답니다. 따라서 강아지에게는 성장속도에 맞는 사료를 급여하셔야 합니다. 사람이 먹는 음식을 먹게 되면 양념과 향신료에 입맛이 익숙해지고, 비만이 될 가능성이 매우 높아집니다. 강아지용 사료는 생후 12개월까지 급여하셔야 합니다.</p>
			</article>
			<article class="at3">
				<h3>밥그릇, 물병 </h3>
				<p>밥그릇은 쉽게 넘어지지 않도록 바닥이 넓은 것이 좋습니다.물병은 대롱이 달린 것으로 선택하세요. 밥그릇에 물을 주게 되면 입 주변에 털이 모두 젖기 때문에 비위생적이므로 대롱을 통해서 물을 먹을 수 있는 물병을 마련하시는 것이 좋습니다.</p>
			</article>
			<article class="at4">
				<h3>이름표, 목줄</h3> 
				<p>강아지를 잃어버릴 염려가 있으니 산책할 무렵이 되면 이름표를 꼭 목에 걸어주도록 하세요. 그리고 방울이 달린 목걸이를 하고자 하실 때는 신중하셔야 합니다. 움직일 때마다 방울이 딸랑 거리면 신경이 예민한 강아지들에게는 좋지 않은 영향을 끼칠 수 있기 때문입니다.</p>
			</article>
		</div>
	</section>
	<aside>
		<img src="images/1.png" alt="리트리버">
		<img src="images/2.png" alt="코카">
		<img src="images/3.png" alt="비글">
	</aside>
	<footer>
		<p>Copyright 2012 funnycon</p>
	</footer>
</body>
</html>

 

 

 


<!DOCTYPE html>

<html lang="ko">

<head>

    <meta charset="utf-8">

    <title>애완견 돌보기</title>  

    <link rel="stylesheet" href="css/layout-result.css" type="text/css">

</head>

<body>

    <header>

        <nav>

            <ul>

                <li><a href="#">애완견 종류</a></li>

                <li><a href="#">입양하기</a></li>

                <li><a href="#">건강돌보기</a></li>

                <li><a href="#">더불어살기</a></li>

            </ul>

        </nav>

    </header>

    <article>

        <h2>애완견 종류</h2>

        <section>

            <h3>활달한 강아지</h3>

            <dl>

                <dt>요크셔 테리어</dt>

                <dd>생기있고 활달한 성질을 가지고 있으며 자신보다 몸집이 큰 개나 집에 들어온 침입자를 겁내는 일이 없어 좋은 번견이고 우리나라 최고의의 가정견으로 자리 잡고 있다.</dd>

                <dt>말티즈</dt>

                <dd>애정이 많고, 충실하며 활발한 성격을 소유하고있다. 이 종은 1급 가정견으로 요크셔테리어와 함께 우리나라 최고의 가정견으로 자리잡고 있다.</dd>

                <dt>포메 라이언</dt>

                <dd>활기차고 명랑한 개로 유명하고, 걷는 모습이 우아하다.충실하고 우호적인 성격이 가장 먼저 거론된다. </dd>

                <dt>골든 리트리버</dt>

                <dd>이 견종은 충성심이 강하고 성격이 활달하여 어린아이나 여성이 상대하기에 적합한 견종이다.참을성 또한 강하여 현재는실내에서도 많이 길러지고 있다.</dd>

            </dl>

        </section>

        <section>

            <h3>온순한강아지</h3>

            <dl>

                <dt>쉬즈</dt>

                <dd>얼굴에서 풍기는 모습처럼 온순, 쉽게 친숙해지고 우호적이며,어린아이나 여성들이 기르기에 적합한 견종이다.</dd>

                <dt>퍼그</dt>

                <dd>매우 사려가 깊고 사랑스러운 견종이며 그다지 손질이 필요하지 않고 식사량에 비해 많은 운동량이 필요하지 않다.</dd>

                <dt>래브라도 리트리버</dt>

                <dd>침착하고 영리하여 어린이들을 안심하고 맡길 수 있다. 사람을 즐겁게 해주려는 성질이 있다 공을 가지고 노는 것을 가장  좋아한다. 현재 맹인 안내견과 마약견으로 사용중이다. 온순한 강아지를 좋아하는 분에게는 적합한 견종이다.</dd>

            </dl>

        </section>

        <section>

            <h3>사납지만 복종적인 강아지</h3>

            <dl>

                <dt>미니어쳐핀셔</dt>

                <dd>경계심이 강하고 영리하며 작은 몸집에 비해 매우 용감하다. 주인에게 매우 복종적이며 작은 몸집에 보디가드 역할을 충실히 수행한다.</dd>

                <dt>푸들</dt>

                <dd>사납진 않으나, 상당히 복종적이며, 지능지수가 애완견종 중 가장 뛰어나다.</dd>

                <dt>폭스테리어</dt>

                <dd>가정에서 키우기에 적합한 품종이다.  보호본능이 강하고 정이 많다. 하지만 사냥을 하던 본능이 조금은 남아있어 사나운 면이 있다. 이종을 좋은 품종으로 기르기 위해서는 어릴 때부터 엄한 훈련이 필요하기도 하다.</dd>

            </dl>

        </section>

    </article>

    <aside>

        <h3>건강한 강아지는</h3>

        <ul>

            <li>코가 젖어있고 눈꼽이 없어야 합니다.</li>

            <li>털에 윤기가 있는 것을 골라야 합니다.</li>

            <li>입에서 고약한 냄새가 나면 병이 있다는 증거입니다.</li>

            <li>가장 활발하게 움직이는 녀석을 고르는게 좋습니다.</li>

            <li>강아지들 중에서 적당한 체구를 유지한 강아지가 좋습니다.</li>

        </ul>

    </aside>

    <footer>

        <p>Copyright 2012 funnycom</p>

    </footer>

</body>

</html>

body{
    font-family: "맑은 고딕", "고딕", "굴림";
}
header{
    width: 80%;
    margin-right: auto;
    margin-left: auto;
    background-color: #069;
    padding: 10px;
    text-align: center;
    overflow: hidden; /*크기보다 내용이 많은 경우 넘쳐나는 부분을 감춤*/
}
header nav{
    width: 60%;
    margin-left: auto;
    margin-right: auto;
}
nav ul{
    list-style-type: none;
}
nav ul li{
    display: inline;
    margin: 15px;
}
nav ul li a{
    color: white;
    text-decoration: none;
}
article{
    width: 80%;
    margin-right: auto;
    margin-left: auto;
    border: 5px solid #333;
    padding: 5px;
    overflow: hidden;
}
article section{
    width: 30%;
    height: 650px;
    float: left;
    margin: 5px;
    padding: 5px;
    border: 1px dotted #333;
}
section h3{
    background: url(../images/bg-note.png) no-repeat left center;
    padding-left: 30px;
}
aside{
    clear: both;
    margin: 0 auto;
    width: 80%;
    height: auto;
    padding: 10px;
    background-color: #99cc33;

}
footer{
    clear: both;
    width: 80%;
    margin-left: auto;
    margin-right: auto;
    padding: 10px;
    background-color: #333;
    color: white;
    text-align: center;
}

 

 

'Learning > HTML&JavaScript' 카테고리의 다른 글

CSS3 선택자  (0) 2020.07.24
HTML 멀티미디어  (0) 2020.07.24
CSS 레이아웃  (0) 2020.07.21
CSS와 박스 모델  (0) 2020.07.21
스타일과 스타일시트 글꼴  (0) 2020.07.17
  • 게시판 하단에 페이지 표시하기

    • 한 페이지당 몇 개의 게시글을 표시할 것인가?

      • int pageSize=5  (5개의 게시글)

 

    • 글이 하나만 있더라도 페이지는 1로 표시된다.

      • String pageNum (String으로 pageNum을 reqest 받아옴)

      • int currentPage (현재 페이지. String pageNum을 int형으로 변환)

 

    • 10개의 게시글이 있다고 가정했을때 1페이지에는 6~10번째, 2페이지에는 1~5번째 게시글이 표시된다.

    • 페이지당 표시되는 게시글의 첫번째를 startRow, 마지막번째를 endRow라고 한다.

      • startRow=(currentPage-1)*pageSize+1; (현재 페이지가 1이라면 startRow는 1)

      • endRow=currentPage*pageSize; (현재 페이지가 1이라면 endRow는 5)

 

    • 페이지가 없었던 기존: 게시글 전체를 arr에 담아 화면에 표시했다.

    • 페이지가 있는 지금: arr에 startRow와 endRow인자를 사용하여 표시

      • 검색이 아닌 전체보기: arr=dao.boardList(startRow, endRow)

      • 검색 전체보기: arr=dao.boardList(field, word, startRow, endRow)

 

    • 하단에 페이지 숫자를 몇 개씩 표시할 것인가?

      • int pageBolck=3 (123 456 처럼 3개씩)

 

    • 게시글 양에 따라 필요한 페이지의 수는?

      • int pageCount=count/pageSize+(count%pageSize==0? 0:1)

      • 11=53/5+(53%5==0)

 

    • 시작페이지 

      • int startPage=(int)((currentPage-1)/pageBlock)*pageBlock+1;

 

    • 마지막페이지

      • int endPage=startPage+pageBlock-1;

      • 만약 마지막페이지가 필요한 페이지보다 크다면: endPage=pageCount;

 

    • '이전' 이란 표시는 언제 생겨나는가?

      • 시작페이지가 필요한 페이지보다 클때

      • startPage>pageBlock

 

    • 페이지 표시

      • for문을 돌려서 starPage에서 endPage까지 1씩 커지도록함

 

    • '다음' 이란 표시는 언제 생겨나는가?

      • 마지막페이지가 필요한 페이지보다 작을때

      • endPage<pageCount

 

    • DB에서 boardList로 값 가져오기

      • 최신글부터 표시되어야 함

        • select * from board order by num desc;

      • 그러나 num은 일정하지 않은 변수(게시글 삭제를 하면). 따라서 rownum이라는 키워드를 이용

        • select rownum rn, aa.* from(select * from board order by num desc) aa;

        • board 테이블을 aa라는 테이블로 명명하고

        • rownum을 rn이라는 이름의 컬럼으로, aa와 함께 출력

      • 페이지당 필요한 게시글 수 만큼 뽑아와야 함.

        • select * from (

        • select rownum rn, aa.* from(

        • select * from board order by num desc) aa

        • ) where rn <=? and rn >=?;

        • ?에는 endrow와 startrow가 들어감

      • 검색한 게시글을 불러올 경우

        • select * from (

        • select rownum rn, aa.* from(

        • select * from board where filed like '%word%' order by num desc) aa

        • ) where rn <=? and rn >=?;

        • ?에는 endrow와 startrow가 들어감

 

 


 

 

  • 답글쓰기

    • 새 글을 쓸때 writeForm: 글 번호가 없다.

    • 답글을 쓸때 writeForm: 글 번호가 있다.

  • ref: 그룹 (새 글에는 새 그룹). 게시글 순서

  • re_step: 답글 순서

  • re_level: 답글의 답글 순서

 


 

 

  • list.jsp: 페이지 표시하도록 수정

 

 

 

<%@page import="com.board.BoardVO"%>

<%@page import="com.board.BoardDAO"%>

<%@page import="java.util.ArrayList"%>

<%@ 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>

<link rel="stylesheet"

href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">

<style>

div.divCss{

    text-align: right;

    background-color:  darkgray;

    padding-right: 20px;

}

a:hover { text-decoration: none;  }

a:link {text-decoration: none;  }

a:visited {text-decoration: none; }

</style>

</head>

<%

    request.setCharacterEncoding("utf-8");

    String pageNum=request.getParameter("pageNum");

    if(pageNum==null){

        pageNum="1";

    }

    int currentPage=Integer.parseInt(pageNum);

    

    BoardDAO dao=BoardDAO.getInstance();

    int pageSize=5; //한페이지당 5개씩

    int startRow=(currentPage-1)*pageSize+1;

    int endRow=currentPage*pageSize;

    String field="", word="";

    ArrayList<BoardVO> arr=null;

    int count=0;

    if(request.getParameter("word")!=null&&!request.getParameter("word").equals("")){ //검색일때

        field=request.getParameter("field");

        word=request.getParameter("word");

        arr=dao.boardList(field,word,startRow,endRow);

        count=dao.boardCount(field,word);

    }else{ //검색아닐때

        arr=dao.boardList(startRow,endRow);

        count=dao.boardCount();

    }

    

    String userid=(String)session.getAttribute("userid");

%>

<body>

<div align="right">

<%

    if(userid!=null){

%>

    <%=userid %>님 반갑습니다.

    <a href="../member/logout.jsp">로그아웃</a>

<%

    }

%>      

    <br>전체 게시글 수: <span id="cntSpan"><%=count %></span><br>

    <a href="writeForm.jsp">글쓰기</a>

</div>

    <table class="table table-striped">

    <thead>

        <tr>

            <th scope="col">번호</th>

            <th>제목</th>

            <th>작성자</th>

            <th>작성일</th>

            <th>조회수</th>

            <th>IP주소</th>

        </tr>

    </thead>

    <tbody>

<%

    for(BoardVO vo: arr){

%>

        <tr>

            <th scope="row"><%=vo.getNum()%></th>       

            <td><a href="boardView.jsp?num=<%=vo.getNum()%>"><%=vo.getSubject() %></a></td>        

            <td><%=vo.getWriter() %></td>       

            <td><%=vo.getReg_date()%></td>      

            <td><%=vo.getReadcount() %></td>    

            <td><%=vo.getIp() %></td>   

        </tr>       

<%

    }

%>  

    </tbody>

    </table>

<br><br>

<form action="list.jsp" name="search" method="get">

    <table align=center>

        <tr>

            <td>

            <select name="field" size=1>

                <option value="subject">제목

                <option value="writer">작성자

            </select>

            <input type="text" size=16 name="word">

            <input type="submit" value="찾기">

            </td>

        </tr>

    </table>

</form>

<div align="center">

<%

    

    if(count>0){ //  11= 53/5 + (53%5==0) 53개 게시물을 한페이지당 5개씩 보여준다면 11개의 페이지가 필요

        int pageCount=count/pageSize+(count%pageSize==0? 0:1);

        int pageBlock=3; //123 456 등 3페이지씩 표시

        int startPage=(int)((currentPage-1)/pageBlock)*pageBlock+1; //시작페이지

        int endPage=startPage+pageBlock-1; //마지막 페이지 12

        if(endPage>pageCount){

            endPage=pageCount; //endPage=11;

        }

        

        if(startPage>pageBlock){ //이전

%>

            <a href="list.jsp?pageNum=<%=startPage-pageBlock%>&field=<%=field%>&word=<%=word %>">[이전]</a>

<%

        }

        for(int i=startPage;i<=endPage;i++){ //for

%>

            <a href="list.jsp?pageNum=<%=i%>&field=<%=field%>&word=<%=word %>"><%=i%></a>

<%

        }

        if(endPage<pageCount){ //다음

%>

            <a href="list.jsp?pageNum=<%=startPage+pageBlock%>&field=<%=field%>&word=<%=word %>">[다음]</a>

<%

        }

    }

%>

</div>

</body>

</html>

 


 

 

  • writeForm.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>

</head>

<%

    request.setCharacterEncoding("utf-8");

    int num=0, ref=1, re_step=0, re_level=0; //새글

    if(request.getParameter("num")!=null){ //답글

        num=Integer.parseInt(request.getParameter("num"));

        ref=Integer.parseInt(request.getParameter("ref"));

        re_step=Integer.parseInt(request.getParameter("re_step"));

        re_level=Integer.parseInt(request.getParameter("re_level"));

    }

%>

<body>

<form action="writePro.jsp" method="post">

<input type="hidden" name="num" value=<%=num %>>

<input type="hidden" name="ref" value=<%=ref %>>

<input type="hidden" name="re_step" value=<%=re_step %>>

<input type="hidden" name="re_level" value=<%=re_level %>>

<table border=1>

    <tr>

        <td>이름</td>

        <td><input type="text" name="writer"></td>

    </tr>

    <tr>

        <td>제목</td>

        <td>

<%

        if(request.getParameter("num")!=null){ //답글

%>

            <input type="text" name="subject" value="[답글]">

<%

        }else{ //새글

%>

            <input type="text" name="subject">

<%

        }

%>

        </td>

    </tr>

    <tr>

        <td>이메일</td>

        <td><input type="text" name="email"></td>

    </tr>

    <tr>

        <td>내용</td>

        <td><textarea cols="50" rows="20" name="content"></textarea></td>

    </tr>

    <tr>

        <td>비밀번호</td>

        <td><input type="password" name="passwd"></td>

    </tr>

    <tr>

        <td colspan="2" align="center">

        <input type="submit" value="글쓰기">

        <input type="reset" value="다시 작성">

        <input type="button" value="목록보기" onclick="location.href='list.jsp'">

        </td>

    </tr>

</table>

</form>

</body>

</html>

 

 

  • boardView.jsp: ref, re_step, re_level 값을 불러오고 각종 버튼에 jsp연결 시키기, 댓글쓰기 란 만들기 (제이쿼리 주소 붙여넣고 스크립트 안에 ajax으로 commentInser.jsp 연결)

 

<%@page import="com.board.BoardVO"%>

<%@page import="com.board.BoardDAO"%>

<%@ 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>

<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<%

    request.setCharacterEncoding("utf-8");

    int num=Integer.parseInt(request.getParameter("num"));

    BoardDAO dao=BoardDAO.getInstance();

    BoardVO board=dao.boardView(num);

    int ref=board.getRef();

    int re_step=board.getRe_step();

    int re_level=board.getRe_level();

    

    String userid=(String)session.getAttribute("userid");

%>

</head>

<script>

function del(){

    if(confirm("정말 삭제할까요?")){

        location.href="deletePro.jsp?num=<%=num%>";

    }

}

</script>

<body>

<h2>글 내용 보기</h2>

<table border=1 width=500>

<input type="hidden" name="num" id="num" value="<%=num%>">

    <tr>

        <td>글번호</td>

        <td><%=board.getNum() %></td>

        <td>조회수</td>

        <td><%=board.getReadcount() %></td>

    </tr>

    <tr>

        <td>작성자</td>

        <td><%=board.getWriter() %></td>

        <td>작성일</td>

        <td><%=board.getReg_date() %></td>

    </tr>

    <tr>

        <td>글제목</td>

        <td colspan="3"><%=board.getSubject() %></td>

    </tr>

    <tr>

        <td>글내용</td>

        <td colspan="3"><%=board.getContent() %></td>

    </tr>

    <tr>

        <td colspan="4">

        <input type="button" value="글수정" onclick="location.href='updateForm.jsp?num=<%=num%>'">

        <input type="button" value="글삭제" onclick="del()">

        <input type="button" value="답글쓰기" onclick="location.href='writeForm.jsp?num=<%=num%>&ref=<%=ref%>&re_step=<%=re_step%>&re_level=<%=re_level%>'">

        <input type="button" value="글목록" onclick="location.href='list.jsp'">

        </td>

    </tr>

</table>

<br><br><br><br>

<div align="center">

    <textarea rows="5" cols="50" id="msg"></textarea>

    <input type="button" value="댓글쓰기" id="commentBtn">

</div>

<div id="area"></div>

<script>

var init=function(){

    $.getJSON("commentList.jsp?num="+$("#num").val(), function(data){

        var htmlStr="<table>";

        $.each(data, function(key,val){

            htmlStr+="<tr>";

            htmlStr+="<td>"+val.msg+"</td>";

            htmlStr+="<th>"+"작성자: "+val.userid+"</th>";

            htmlStr+="<td>"+val.reg_date+"</td>";

            if('<%=userid%>'==val.userid){

                htmlStr+="<td onclick='del()'><input type='button' value='삭제'></td>";

            }

            htmlStr+="</tr>";

        });

        htmlStr+="</table>";

        $("#area").html(htmlStr);

    }) //getJSON

}//init

function del(){

    if(confirm("정말 삭제할까요?")){

    }

}

$("#commentBtn").on("click",function(){

    $.ajax({

        type:"post",

        url :"commentInsert.jsp",

        data:  {"msg":$("#msg").val(), "num":$("#num").val()},

        success: function(resp){

            if(resp.trim()=="1"){

                alert("로그인 후 댓글쓰기");

                //location.href="../member/loginForm.jsp";

                location.href="/JSP_Project/member/loginForm.jsp";

            }else{

                //화면에 리스트 뿌리기

                init();

            }

            

        },

        error: function(e){

            alert("error:"+e);

        }

    });

});

init();

</script>

</body>

</html>


 

 

  • updateForm.jsp: 답글 표시, 목록보기에 list.jsp 연결

 

 

<%@page import="com.board.BoardVO"%>

<%@page import="com.board.BoardDAO"%>

<%@ 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>

<%

    request.setCharacterEncoding("utf-8");

    int num=Integer.parseInt(request.getParameter("num"));

    BoardDAO dao=BoardDAO.getInstance();

    BoardVO board=dao.boardView(num);

%>

</head>

<body>

<h1>글 수정하기</h1>

<form action="updatePro.jsp" method="post">

<input type="hidden" name="num" value="<%=num%>">

<table border=1>

    <tr>

        <td>이름</td>

        <td><%=board.getWriter()%></td>

    </tr>

    <tr>

        <td>제목</td>

        <td><input type="text" name="subject" value="<%=board.getSubject()%>"></td>

    </tr>

    <tr>

        <td>이메일</td>

        <td><input type="text" name="email" value="<%=board.getEmail()%>"></td>

    </tr>

    <tr>

        <td>내용</td>

        <td><textarea cols="50" rows="20" name="content"><%=board.getContent()%></textarea></td>

    </tr>

    <tr>

        <td>비밀번호</td>

        <td><input type="password" name="passwd"></td>

    </tr>

    <tr>

        <td colspan="2" align="center">

        <input type="submit" value="수정">

        <input type="reset" value="다시 작성">

        <input type="button" value="목록보기" onclick="location.href='list.jsp'">

        </td>

    </tr>

</table>

</form>

</body>

</html>

 

 

  • BoardDAO.java: 답글과 페이지에 따라 추가, 보기, 갱신 등 수정하기

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    package com.board;
     
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.ArrayList;
     
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.sql.DataSource;
     
    public class BoardDAO {
        
        //디비셋팅
        private static BoardDAO instance=new BoardDAO();
        
        public static BoardDAO getInstance() {
            return instance;
        }
        
        private Connection getConnection() throws Exception{
            Context initCtx=new InitialContext();
            Context envCtx=(Context) initCtx.lookup("java:comp/env");
            DataSource ds=(DataSource) envCtx.lookup("jdbc/member"); 
            return ds.getConnection();
        }
        
        //추가
        public void boardInsert(BoardVO board) { //새글 답글 구분
            Connection con=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            
            //부모글
            int num=board.getNum();
            int ref=board.getRef(); //게시글 순서
            int re_step=board.getRe_step(); //답글 순서
            int re_level=board.getRe_level(); //답글의 답글 순서
            
            int number=0;
            String sql=null;
            try {
                con=getConnection();
                ps=con.prepareStatement("select max(num) from board");
                rs=ps.executeQuery();
                if(rs.next()) { //기존 데이터가 있을때 ref를 최대값 +1 로 결정
                    number=rs.getInt(1)+1;
                }else { //기존 데이터가 없을때 ref를 1로 결정
                    number=1;
                }
                if(num!=0) { //답글
                    sql="update board set re_step=re_step+1 where ref=? and re_step>?";
                    ps=con.prepareStatement(sql);
                    ps.setInt(1, ref);
                    ps.setInt(2, re_step);
                    ps.executeUpdate();
                    re_step=re_step+1;
                    re_level=re_level+1;
                }else { //새글
                    ref=number;
                    re_step=0;
                    re_level=0;
                }
                //num, writer, subject, email, content, passwd, ip, readcount, ref, re_step, re_level
                sql="INSERT INTO BOARD(num,writer,subject,email,content,passwd,ip,readcount,ref,re_step,re_level)"
                        + "VALUES (board_seq.nextval,?,?,?,?,?,?,0,?,?,?)";
                ps=con.prepareStatement(sql);
                ps.setString(1, board.getWriter());
                ps.setString(2, board.getSubject());
                ps.setString(3, board.getEmail());
                ps.setString(4, board.getContent());
                ps.setString(5, board.getPasswd());
                ps.setString(6, board.getIp());
                ps.setInt(7, ref);
                ps.setInt(8, re_step);
                ps.setInt(9, re_level);
                ps.executeUpdate();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeConnection(con,ps,rs);
            }
        }
        
        //전체보기
        public ArrayList<BoardVO> boardList(int startRow, int endRow){
            Connection con=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            ArrayList<BoardVO> arr=new ArrayList<BoardVO>();
            try {
                con=getConnection(); //게시글은 최신순. 답글은 오래된 순.
                String sql="select * from ("
                            + "select rownum rn, aa.* from ("
                            + "select * from board order by ref desc, re_step asc) aa " 
                            + ") where rn <=? and rn >=?";
                ps=con.prepareStatement(sql);
                ps.setInt(1, endRow);
                ps.setInt(2, startRow);
                rs=ps.executeQuery();
                while(rs.next()) {
                    BoardVO board=new BoardVO();
                    board.setNum(rs.getInt("num"));
                    board.setEmail(rs.getString("email"));
                    board.setIp(rs.getString("ip"));
                    board.setReadcount(rs.getInt("readcount"));
                    board.setSubject(rs.getString("subject"));
                    board.setWriter(rs.getString("writer"));
                    board.setReg_date(rs.getString("reg_date"));
                    arr.add(board);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeConnection(con, ps, rs);
            }
            return arr;
        }
        
        //검색 전체보기
        public ArrayList<BoardVO> boardList(String field, String word, int startRow, int endRow){
            Connection con=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            ArrayList<BoardVO> arr=new ArrayList<BoardVO>();
            try {
                con=getConnection();
                String sql="select * from ("
                        + "select rownum rn, aa.* from ("
                        + "select * from board where "
                        +field+" like '%"+word+"%' order by ref desc, re_step asc) aa "
                        + ") where rn <=? and rn >=?";
                ps=con.prepareStatement(sql);
                ps.setInt(1, endRow);
                ps.setInt(2, startRow);
                rs=ps.executeQuery();
                while(rs.next()) {
                    BoardVO board=new BoardVO();
                    board.setNum(rs.getInt("num"));
                    board.setEmail(rs.getString("email"));
                    board.setIp(rs.getString("ip"));
                    board.setReadcount(rs.getInt("readcount"));
                    board.setSubject(rs.getString("subject"));
                    board.setWriter(rs.getString("writer"));
                    board.setReg_date(rs.getString("reg_date"));
                    arr.add(board);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeConnection(con, ps, rs);
            }
            return arr;
        }
        
        //상세보기
        public BoardVO boardView(int num) {
            Connection con=null;
            Statement st=null;
            ResultSet rs=null;
            BoardVO board=null;
            
            try {
                con=getConnection();
                st=con.createStatement();
                st.executeUpdate("update board set readcount=readcount+1 where num="+num);
                String sql="select * from board where num="+num;
                st=con.createStatement();
                rs=st.executeQuery(sql);
                if(rs.next()) {
                    board=new BoardVO();
                    board.setNum(rs.getInt("num"));
                    board.setContent(rs.getString("content"));
                    board.setEmail(rs.getString("email"));
                    board.setSubject(rs.getString("subject"));
                    board.setIp(rs.getString("ip"));
                    board.setPasswd(rs.getString("passwd"));
                    board.setRe_level(rs.getInt("re_level"));
                    board.setRe_step(rs.getInt("re_step"));
                    board.setRef(rs.getInt("ref"));
                    board.setReg_date(rs.getString("reg_date"));
                    board.setReadcount(rs.getInt("readcount"));
                    board.setWriter(rs.getString("writer"));
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                closeConnection(con, st, rs);
            }
            return board;
        }
        
        //수정
        public int boardUpdate(BoardVO board) {
            Connection con=null;
            PreparedStatement ps=null;
            ResultSet rs=null;
            
            int flag=0;
            String sql="";
            try {
                con=getConnection();
                sql="select passwd from board where num="+board.getNum();
                ps=con.prepareStatement(sql); //passwd 검색
                rs=ps.executeQuery();
                if(rs.next()) {
                    if(rs.getString("passwd").equals(board.getPasswd())) { //비번 일치
                        sql="UPDATE BOARD SET subject=?, email=?, content=?, reg_date=sysdate where num=?";
                        ps=con.prepareStatement(sql);
                        ps.setString(1, board.getSubject());
                        ps.setString(2, board.getEmail());
                        ps.setString(3, board.getContent());
                        ps.setInt(4, board.getNum());
                        flag=ps.executeUpdate(); //업데이트 된 수를 flag에 담는다.
                    }
                }
            }catch (Exception e) {
                e.printStackTrace();
            }finally {
                closeConnection(con, ps);
            }
            return flag;
        }
        
        //삭제
        public int boardDelete(int num) {
            int flag=0;
            Connection con=null;
            Statement st=null;
            try {
                con=getConnection();
                String sql="DELETE FROM board WHERE num="+num;
                st=con.createStatement();
                flag=st.executeUpdate(sql);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeConnection(con, st, null);
            }
            return flag;
        }
        
        //개수
        public int boardCount() {
            Connection con=null;
            Statement st=null;
            ResultSet rs=null;
            int count=0;
            try {
                con=getConnection();
                st=con.createStatement();
                String sql="select count(*) from board";
                rs=st.executeQuery(sql);
                if(rs.next()) {
                    count=rs.getInt(1);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeConnection(con, st, rs);
            }
            return count;
        }
        
        //검색 개수
            public int boardCount(String field, String word) {
                Connection con=null;
                Statement st=null;
                ResultSet rs=null;
                int count=0;
                try {
                    con=getConnection();
                    st=con.createStatement();
                    String sql="select count(*) from board where "+field+" like '%"+word+"%'";
                    rs=st.executeQuery(sql);
                    if(rs.next()) {
                        count=rs.getInt(1);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    closeConnection(con, st, rs);
                }
                return count;
            }
            
        //comment
            
        //commentInsert
        public void commentInsert(CommentVO cvo) {
            Connection con=null;
            PreparedStatement ps=null;
            try {
                con=getConnection();
                String sql="INSERT INTO commentboard(cnum, userid, msg, bnum)"
                        + "VALUES(comment_seq.nextval,?,?,?)";
                ps=con.prepareStatement(sql);
                ps.setString(1, cvo.getUserid());
                ps.setString(2, cvo.getMsg());
                ps.setInt(3, cvo.getBnum());
                ps.executeUpdate();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeConnection(con, ps);
            }
        }
        
        //commentList
        public ArrayList<CommentVO> commentList(int num){
            Connection con=null;
            Statement st=null;
            ResultSet rs=null;
            ArrayList<CommentVO> arr=new ArrayList<CommentVO>();
            
            try {
                con=getConnection();
                String sql="SELECT * FROM COMMENTBOARD where bnum="+num+" ORDER BY cnum DESC";
                st=con.createStatement();
                rs=st.executeQuery(sql);
                while(rs.next()) {
                    CommentVO comment=new CommentVO();
                    comment.setBnum(rs.getInt("bnum"));
                    comment.setCnum(rs.getInt("cnum"));
                    comment.setMsg(rs.getString("msg"));
                    comment.setReg_date(rs.getString("reg_date"));
                    comment.setUserid(rs.getString("userid"));
                    arr.add(comment);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                closeConnection(con, st, rs);
            }
            return arr;
        }
        
        //닫기 closeConnection
            private void closeConnection(Connection con, PreparedStatement ps) {
                try {
                    if(ps!=null) ps.close();
                    if(con!=null) con.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                } 
            }
            private void closeConnection(Connection con, Statement st, ResultSet rs) {
                try {
                    if(st!=null) st.close();
                    if(con!=null) con.close();
                    if(rs!=null) rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                } 
            }
    }
     
    cs
     
     

 


  • commentboard 이름의 테이블을 생성하여 댓글 DB만들기. 댓글번호 cnum을 기본키로 하고 board테이블의 num을 bnum이름으로 외래키로 참조한다.

 

 

cnum으로 쓸 시퀀스 생성

 


 

  • CommentVO.java: 댓글 자바빈즈

 

package com.board;

public class CommentVO {

    private int cnum;

    private String userid;

    private String reg_date;

    private String msg;

    private int bnum;

    public int getCnum() {

        return cnum;

    }

    public void setCnum(int cnum) {

        this.cnum = cnum;

    }

    public String getUserid() {

        return userid;

    }

    public void setUserid(String userid) {

        this.userid = userid;

    }

    public String getReg_date() {

        return reg_date;

    }

    public void setReg_date(String reg_date) {

        this.reg_date = reg_date;

    }

    public String getMsg() {

        return msg;

    }

    public void setMsg(String msg) {

        this.msg = msg;

    }

    public int getBnum() {

        return bnum;

    }

    public void setBnum(int bnum) {

        this.bnum = bnum;

    }

    

    

}

 

 


 

  • commentInsert.jsp: 댓글 입력 로직

 

<%@page import="com.board.BoardDAO"%>

<%@page import="com.board.CommentVO"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%

    request.setCharacterEncoding("utf-8");

    String msg=request.getParameter("msg");

    int num=Integer.parseInt(request.getParameter("num"));

    String userid=(String)session.getAttribute("userid");

    if(userid==null){ //로그인 안됨

        out.println("1");   

    }else{ //로그인

        CommentVO comment=new CommentVO();

        comment.setUserid(userid);

        comment.setMsg(msg);

        comment.setBnum(num);

        BoardDAO dao=BoardDAO.getInstance();

        dao.commentInsert(comment);

    }

%>

 

 


 

  • commentList.jsp: 댓글 목록

 

<%@page import="org.json.simple.JSONObject"%>

<%@page import="org.json.simple.JSONArray"%>

<%@page import="com.board.CommentVO"%>

<%@page import="java.util.ArrayList"%>

<%@page import="com.board.BoardDAO"%>

<%@ page language="java" contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<%

    request.setCharacterEncoding("utf-8");

    int num=Integer.parseInt(request.getParameter("num"));

    BoardDAO dao=BoardDAO.getInstance();

    ArrayList<CommentVO>arr=dao.commentList(num);

    JSONArray jarr=new JSONArray();

    for(CommentVO cb:arr){

        JSONObject obj=new JSONObject();

        obj.put("bnum",cb.getBnum());

        obj.put("cnum",cb.getCnum());

        obj.put("msg",cb.getMsg());

        obj.put("userid",cb.getUserid());

        obj.put("reg_date",cb.getReg_date());

        jarr.add(obj);

    }

    out.println(jarr.toString());

%>  


 

 

 

'Learning > JSP' 카테고리의 다른 글

JSTL  (0) 2020.07.27
서블릿  (0) 2020.07.27
게시판 1  (0) 2020.07.22
회원가입2  (0) 2020.07.22
회원가입  (0) 2020.07.20

+ Recent posts