|
Back-End/네트워크 2020. 11. 10. 18:50
IPv4란 ??
IPv4는 Internet protocol version 4 의 약어로, 인터넷 프로토콜의 4번째 버전이다.
전 세계적으로 사용된 첫 번째 인터넷 프로토콜로, IETF (인터넷 표준화 기구) RFC 791 (1981년 9월) 에 문서화되어 있다.
또한 IPv6를 제외하고, 현재 인터넷에서 사용되는 유일한 프로토콜이다.
한편 인터넷 프로토콜 (IP : Internet protocol) 은 인터넷상의 한 컴퓨터에서 다른 컴퓨터로 데이터를 보내는 데 사용되는
프로토콜을 일컫는다. 인터넷상의 각 컴퓨터, 즉 호스트들은 다른 컴퓨터와 구별될 수 있드록 적어도 한 개 이상의
고유한 주소를 갖는다.
IPv4의 주소체계는 네 개로 나눠진 최대 12자리의 번호로 이루어져 있다.
예를 들면, '210.113.39.224' 이다. 32비트로 이루어진 IPv4는 최대 약 40억 개의 서로 다른 주소를 부여할 수 있다.
그러나 기하급수적으로 늘어나는 사용자 수요를 감안할 때, 현재 사용되고 있는 IPv4 체계로는 개수가 부족해서 수요를
충족 시킬수 없다. 그에 따라서 128비트 주소체계를 갖는 IPv6가 등장하였다.
|
IPv6에 대해서
IPv6란 ??
무한히 제공 가능한 IP 주소
IPv4는 약 43억개의 주소가 이용 가능한 반면, IPv6는 거의 무한대의 주소 할당이 가능하다.
따라서 모든 네트웍 연결이 필요한 모든 디바이스에 독립적인 IP 주소를 부여하여 차세대 PC, RFID, 텔레매틱스, USN 같은
새로운 서비스 제공에 필요한 주소 할당이 가능하다.
|
IPv6와 IPv4의 특성 비교
보안 기능 강화
IPv6는 전자상거래의 가능성을 확대하는 동시에 전자상거래 트랜잭션에 대한 신뢰도를 강화하는
보안표준을 응용에 도입한다. IPv4는 설계시 보안은 고려되지 않았으며 이후 IPsec등의 표준이 추가됨
IP 주소의 자동 설정 기능
IPv6의 노드는 주소 자동설정기능을 사용하여 로컬 IPv6 주소를 자체적으로 생성한다.
이 경우 LAN 상의 MAC (Medium Access Control) 주소를 네트워크 라우터가 제공한 프리픽스와 결합하여 고유의 IP 주소를 생성한다.
서버가 주소를 승인하거나 배포할 필요가 없기 때문에 서버를 수동으로 설정할 필요가 없으며 이를 위한 숙련된 인력이 더 이상
필요 없기 때문에 기업의 네트워크 관리 및 유지 비용이 감소된다.
|
IPv6 주소의 종류
유니캐스트 (Unicast)
유니캐스트 주소는 유니 캐스트 주소 종류의 범위 내에서 단일 인터페이스를 식별한다.
유니 캐스트 주소로 지정된 패킷은 적절한 유니 캐스트 라우팅 토폴로지를 통해 단일 인터페이스로 배달된다.
로드 균형 시스템 (Load Balancing System) 을 수용할 수 있드록 여러 인터페이스가 호스트에서 IPv6에 대한
단일 인터페이스로 나타나기만 한다면 이들 인터페이스가 동일한 주소를 사용하는 것을 허용한다.
유니캐스트 전송 방식은 하나의 송신자가 다른 하나의 수신자로 데이터를 전송하는 방식으로 일반적인
인터넷 응용프로그램이 모두 유니캐스트 방식을 사용한다.
멀티캐스트 (Multicast)
멀티캐스트 주소는 여러 인터페이스를 식별한다.
멀티캐스트 주소로 지정된 패킷은 적절한 멀티캐스트 라우팅 토폴로지를 통해 주소로 식별되는 모든 인터페이스에 배달된다.
브로드캐스트 전송방식은 하나의 송진자가 같은 서브네트웍 상의 모든 수신자에게 데이터를 전송하는 방식인 반면
멀티캐스트 전송방식은 하나 이상의 송신자들이 특정한 하나 이상의 수신자들에게 데이터를 전송하는 방식으로 실시간 음성,
화상 회의, 게임, 메신저, 애플리케이션 등에 사용될 것이다.
애니캐스트 (Anycast)
애니 캐스트 주소로 지정된 패킷은 적절한 멀티캐스트 라우팅 토폴로지를 통해 주소로 식별되는 가장 가까운 인터페이스인
단일 인터페이스로 배달된다.
"가장 가까운" 인터페이스란 라우팅 거리가 가깝다는 것을 의미한다.
멀티캐스트 주소는 여러 인터페이스로 배달되는 일 대 다 통신에 사용되며, 애니 캐스트 주소는 단일 인터페이스로
배달되는 일 대 일 통신에 사용된다.
모든 경우에 IPv6 주소는 노드가 아닌 인터페이스를 식별한다.
노드는 해당 인터페이스 중 하나에 할당된 유니 캐스트 주소로 식별된다.
|
IPv6의 장점
1. 확장된 헤더에 선택사항들을 기술할 수 있으며, 이것은 수신지에서만 검색되므로 네트웍 속도가 전반적으로 빨라진다.
전체 헤더 길이는 두배로 늘었지만, 헤더 필드의 수를 12개에서 8개로 단순화 시킴으로써 헤더 처리 속도를 개선하는 효과를 가져왔다.
2. IPv4 헤더의 옵션 필드에서 사용되던 헤더들을 확장헤더 형식으로 변경함으로써 전송 경로상의 포워딩 효율이 높아졌고,
향후 확장헤더들을 이용한 새로운 응용서비스의 적용을 위한 융통성을 제공할 수 있도록 하였다.
3. IPv6 에서는 자동적으로 주소 설정이 가능한 자동 네트워킹 기능을 포함하고 있으므로, 단말기의 이동에 따라
주소를 재 설정하는 절차에 따른 사용자의 불편을 해소하였다.
4. IP주소를 32비트에서 128비트로 확장함에 따라 주소공간이 크게 증가하고 체계적으로 주소를 할당할 수 있도록
주소 체계를 개선하였다. 또한 멀티 캐스트 주소 체계를 강화하고 멀티캐스트 라우팅의 확장성이 향상도었다.
5. IPv6 에서는 인증, 보안 관련 기능을 지원하기 위하여 보안 관련 확장 헤더를 규정하고, 보안 기능을
반드시 구현하여야 할 기본 기능으로 채택함으로써, 보안 서비스 제공을 위한 효율을 향상시켰다.
패킷의 출처 인증, 데이터 무결성의 보장 및 비밀의 보장 등을 위한 매커니즘을 지정할 수 있다.
|
출처
https://terms.naver.com/entry.nhn?docId=3448168&cid=58469&categoryId=58469
Back-End/네트워크 2020. 11. 10. 18:50
IP란??
[Internet protocol] 의 약자로 인터넷에서 해당 컴퓨터의 주소.
인터넷에 연결되어 있는 각 컴퓨터는 숫자로 이루어진 고유 주소를 갖고 있습니다.
이것을 IP 주소라고 부릅니다.
|
IP주소의 사용 이유??
각각의 Host들을 구분하기위해 사용되며, 부여받은 IP는 자기 고유의 IP가 되기에 다른 사람이 사용하면 안됩니다.
하지만 현재 사용되는 IPv4방식의 IP수는 한정되어 있기에 모든 Host에게 고유의 IP를 할당하지 못합니다.
또한 하나의 호스트에 하나의 IP만 사용되는 것이 아니기 때문에 (EX - 한대의 컴퓨터에 여러개의 랜카드 장착)
여러개의 IP를 사용한다고 보면 되고,
일반 가정에서는 고정이 아닌 유동 IP주소로 설정되어 있다.
그 이유는 가정에서 사용하는 PC등이 전원이 OFF되면 IP를 부여하지 말아야 하기 때문 (IP주소의 개수는 정해져 있어서...)
개수 부족현상을 방지하기 위함이다.
|
IP 구조
IP Address 32bit (4byte) 길이로 구성된 논리적인 주소체계로서 형태는 000.000.000.000 (ex. 184. 51. 65. 127) 로 표기합니다.
여기서는 '.(dot)' 으로 구분된 Octet(8bit / 1byte) 4개가 조합되어 IP주소를 나타내게 됩니다.
그런데 실제 IP는 2진수로 표기되어 00000000 000000000 000000000 이와 같은 형태로 구분되어 사람이 이해하고
외우기가 어렵기에 10진수로 나타내는 표기법을 사용하는 것입니다.
IP주소의 이러한 표기법은 dot-decimal notice 또는 dotted - quad sequence라고 부릅니다.
이 숫자들을 2진수로 계산하면 8bit가 전부 '1' 이라고 가정하였을 때 255라는 숫자가 나온다는 것을 알 수가 있습니다.
따라서 각 옥탯 별로 IP는 0~255까지의 범위를 가지게 되며, 부여할 수 있는 IP의 개수는 256개가 되는 것입니다.
그래서 전체 IP의 수는 약 42억개 정도로 한정되어 있습니다.
|
물리적인 주소 체계
IP Address는 논리적 주소체계이고, 반대로 물리적인 주소체계도 존재합니다.
흔히 MAC (Media Access Control) 주소라고도 말합니다.
다른 이름으로는 Physical Address라고도 말합니다.
이러한 MAC address는 LAN (Local Area Network) 또는 Ethernet 이라 불리는 망에서 통신을 하기 위하여 사용됩니다.
LAN이라는 이름에서 알 수 있듯이 MAC는 자신이 속한 네트워크 안에서만 통신이 됩니다.
이후 네트워크를 빠져나가는 장치인 Router을 지나게 되면 IP를 이용하여 통신하게 됩니다.
|
IP 주소의 Network ID와 Host ID
하나의 IP 주소에는 Network ID와 Host ID가 존재하고 있습니다.
먼저 Network ID는 인터넷 상에서 모든 Host 들을 전부 관리하기 힘들기에 한 Network의 범위를 지정하여 관리하기
쉽게 만들어 낸 것입니다.
그리고 Host ID는 호스트들을 개별적으로 관리하기 위해 사용하게 된 것입니다.
따라서 우리가 인터넷을 사용할 때 Routing으로 목적지를 알아내고 찾아가는 등의 역할을 할 때에는
Network ID와 Host ID가 합쳐진 IP 주소를 보게 됩니다.
서브넷 마스크에 대해 알고자 할때 이 부분이 매우 중요합니다.
Subnet mask를 활용하여 Network ID를 올리거나 낮출 수 있게 됩니다.
반대로 Host ID는 줄어들거나 늘어날 수 있게 됩니다.
라우터끼리의 통신에서는 IP를 사용하기에 Network ID와 Host ID를 보고 목적지가 어떤 네트워크에 속하는지 알 수 있게 됩니다.
|
IP Class의 개념
IP Class의 경우 A, B, C, D, E Class로 나누어 Network ID와 Host ID를 구분하게 됩니다.
A Class의 경우 처음 8bit (1byte)가 Network ID이며, 나머지 24bit(3byte)가 Host ID로 사용됩니다.
비트가 0으로 시작하기에 네트워크 할당은 0~127입니다. 즉, 128곳에 가능하며, 최대 호스트 수는 16,777,214개 입니다.
B Class의 경우 처음 16bit(2byte) 가 Network ID이며, 나머지 16bit(2byte) 가 Host ID로 사용됩니다.
비트가 10으로 시작하기에 네트워크 할당은 16,384 곳에 가능하며, 최대 호스트 수는 65,534개 입니다.
C Class의 경우 처음 24bit(3byte) 가 Network ID이며, 나머지 8bit(1byte) 가 Host ID로 사용됩니다.
비트가 110으로 시작하기에 네트워크 할당은 2,097,152 곳에 가능하며, 최대 호스트 수는 254개 입니다.
D Class와 E Class는 실제로 거의 사용되지 않습니다.
D Class는 Multicast (멀티캐스트), E Class는 미래에 사용하기 위해 남겨둔 것으로 예약되어 있습니다.
|
Class를 구분하는 방법
각각의 Class를 구분하는 방법은 의외로 간단하게 제일 첫 번째 옥텟 (Octet) 으로 구분하실 수 있습니다.
만약 IP가 164.58.94.125라고 할 때 첫번째 Octet는 164가 되는 것입니다.
IP 주소에서 쓸 수 있는 숫자의 범위는 0~255로 되어 있기에 첫 번째 Octet에서 0~255까지의 숫자를 5개로 나누어서
A, B, C, D, E Class로 구분 되는 것입니다.
A Class : 0 ~127 (0.0.0.0 ~ 127.255.255.255)
B Class : 128 ~ 191 (128.0.0.0 ~ 191.255.255.255)
C Class 192 ~ 223 (192.0.0.0 ~ 233.255.255.255)
D Class 224 ~ 239 (224.0.0.0 ~ 239.255.255.255)
E Class 240 ~ 255 (240.0.0.0 ~ 255.255.255.255)
또한 특정 IP들은 어떠한 목적에 의해 사용될 수 없습니다.
예를 들어 사설 IP 대역이나 Loop Back Address, Network Address, Broadcast Address 등은 어떠한 목적으로 사용되는
IP 들이기에 일반적으로 할당하여 사용하실 수 없다는 점을 유의하면 됩니다.
|
출처
https://blog.naver.com/wonsbsa/221517500161
Back-End/Data Base 2020. 3. 21. 21:58
UNION 쿼리는 2개 이상의 테이블을 결합해서 결과값을 출력할 때 중복된 값을 제거할 수 있는 쿼리입니다.
아래와 같이 두가지의 테이블이 있다고 가정할때 OBJECTID컬럼의 C,D,F는 중복이 되므로 한번만 출력을 해야 합니다.
그럴경우에는 아래와 같이 쿼리를 작성후 실행하면 중복된 값이 없는 결과가 출력됩니다.
단, 두 테이블간에 컬럼의 갯수를 맞춰줘야 되므로, objecttable테이블에 null값이 들어간 groupid라는 컬럼을 새로 만들어서 사용했습니다.
| SELECT GROUPID, OBJECTID, OBJECTNM, ORDERSEQ FROM ( SELECT GROUPID, OBJECTID, OBJECTNM, ORDERSEQ FROM mappingtable WHERE GROUPID = 200 UNION SELECT NULL AS GROUPID , OBJECTID, OBJECTNM, ORDERSEQ FROM objecttable WHERE OBJECTID NOT IN (SELECT OBJECTID FROM mappingtable WHERE GROUPID = 200) ); | cs |
UNION으로 합칠 테이블의 검색값중에 WHERE가 들어가 있는 경우에는 검색값이 두줄이상 되면 에러가 발생이 되기때문에 NOT IN을 추가로 넣었습니다.
Back-End/Data Base 2020. 1. 26. 12:04
테이블 생성 1
| CREATE TABLE MASTERTABLE( CODE VARCHAR2(50), CODE_NAME VARCHAR2(50), USE_YN VARCHAR2(50), CONSTRAINT CODEC PRIMARY KEY(CODE) //CODE를 기본키로 설정 ); INSERT INTO MASTERTABLE VALUES('COM001','검색조건','Y'); SELECT * FROM MASTERTABLE; | cs |
테이블 생성 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | CREATE TABLE DATAILTABLE( CODE VARCHAR2(50), DECODE VARCHAR2(50), DECODE_NAME VARCHAR2(50), USE_YN VARCHAR2(50), CONSTRAINT DECODEC PRIMARY KEY(DECODE), //DECODE를 기본키로 설정 CONSTRAINT CODE_DATAIL FOREIGN KEY(CODE) REFERENCES MASTERTABLE(CODE) //CODE를 다른 테이블을 참조하는 외래키로 설정 ); INSERT INTO DATAILTABLE VALUES('COM001','DECODE01','글번호','Y'); INSERT INTO DATAILTABLE VALUES('COM001','DECODE02','글제목','Y'); INSERT INTO DATAILTABLE VALUES('COM001','DECODE03','글쓴이','N'); SELECT * FROM DATAILTABLE; | cs |
두개의 테이블을 Join해서 CODE가 COM001이고, USE_YN이 Y인 DECODE_NAME를 검색해보기
Back-End/Data Base 2020. 1. 23. 11:19
- JOIN -
하나이상의 테이블로 부터 연관된 테이블(컬럼)을 검색할 수 있는 방법이다.
또한 JOIN에서 ON과 WHERE의 차이점은 JOIN하는 범위가 다르다.
또한 PK(PrimaryKEY) & FK(Foreign KEY)의 값에 연관에 의해 보통 JOIN이 성립하지만,
어떤 경우에는 이러한 PK,FK 관계가 없어도 논리적인 값들의 연관만으로 JOIN이 성립되기도 한다.
- JOIN의 종류 -
- EQUIJOIN : column 간의 값들이 서로 정확히 일치하는 경우에 사용, 일반적으로 PK, FK 관계에 의함
- NON-EQUIJOIN : 한 컬럼의 값이 다른 컬럼의 값과 정확히 일치하지 않는 경우에 사용
- OUTER JOIN : JOIN 조건을 만족하지 않는 경우에도 모든 행들을 다 보려는 경우에 사용
- SELF JOIN : 같은 테이블에 있는 행들을 JOIN 하고자 하는 경우에 사용
JOIN에 대한 조건이 생략되거나 잘못 기술되면, 한 테이블에 있는 모든 행들과 JOIN되고,
이런 결과를 Cartesian product (모든 케이스가 다 JOIN 되는 것) 이라고 하는데, 이런 상황을 방지하기 위해서는 반드시 JOIN시에 WHERE를 써야 한다.
1. EQUIJOIN
서로 다른 테이블에서 같은 값을 이용해 데이터를 출력한다.
EQUIJOIN(INNER JOIN)의 기본 구조
SELECT 테이블명.컬럼명, 테이블명.컬럼명,...
FROM 테이블1, 테이블2
WHERE 테이블1.컬럼1 = 테이블2.컬럼2;
|
2. NON-EQUIJOIN
연산자 외에 다른 연산자를 사용하여 조인하는 방법이다.
즉 한 컬럼의 값이 다른 컬럼의 값과 정확히 일치하지 않는 경우 '=' 연산자 외의 다른 연산자를 사용하여
JOIN하는 방법을 말한다. 즉, 정확한 값의 비교가 아니라 값의 범위를 비교해야 할 때 사용한다.
SELECT 테이블.컬럼명, 테이블.컬럼명
FROM 테이블1, 테이블2
WHERE 테이블1.컬럼 BETWEEN 테이블2.컬럼 AND 테이블2.컬럼
|
3. OUTER JOIN
OUTER JOIN을 하는 경우에는 (+) 연산자를 사용한다.
(+)를 사용하는 위치는 JOIN할 데이터가 부족한 쪽 (즉, 상대 테이블과 비교할 데이터가 존재하지 않는쪽) 에 위치시킨다.
(+)는 WHERE절에서 비교연산자 기준으로 좌변 또는 우변의 어느 한쪽에 위치 시킨다.
OUTER JOIN에서 IN이나 OR을 사용할 수 없다.
4. SELF JOIN
하나의 테이블을 마치 여러개인 것처럼 사용할 수 있다.
반드시 테이블에 대한 ALIAS를 각기 다르게 지정해야 한다.
칼럼의 이름 앞에 반드시 테이블의 ALIAS를 붙여야 한다.
SELF JOIN의 횟수는 제한되어 있지 않다.
SET 연산자의 종류
UNION : 각 QUERY 결과의 합집합
UNION ALL : 각 QUERY 결과의 합집합에 공통부분을 더함
INTERSECT : 각 QUERY결과의 교집합
MINUS : 첫번째 QUERY 결과와 두번째 QUERY 결과의 차집합
SET연산자의 기본적인 구조
SELECT 컬럼1, 컬럼2 ...
FROM 테이블 1...
SET 연산자
SELECT 컬럼1', 컬럼2 ...
FROM 테이블2...
ORDER BY ;
|
첫번째 SELECT 구문에서 기술된 컬럼들과 두번째 SELECT 구문에서 기술된 컬럼들은 그 개수와 타입이 일치해야 한다.
FROM절 뒤에 기술된 테이블은 서로 다를 수도, 같은 수도 있다.
컬럼 HEADING는 첫번째 SELECT 구문의 컬럼명이 출력된다.
ORDER BY 절은 마지막에 한번만 기술한다.
출처 : https://songc92.tistory.com/43
Back-End/Spring 2019. 9. 28. 13:35
메뉴바에 디자인 넣어보는 중. 부트스트랩은 반응형웹에도 사용이 되기때문에 웹페이지의 크기에 따라 항목이 다르게 나온다.
(수정중)
menu.jsp
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 | <!DOCTYPE html> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- views/include/menu.jsp --> <%@ include file="header.jsp"%> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js%22"></script> </head> <center> <body> <nav class="navbar navbar-inverse"> <div class="container-fluid"> <div class="navbar-header"> <a class="navbar-brand" href="#">Hs-Project</a> </div> <div> <!-- 다른 기능들 링크가 걸려있는 메뉴 페이지 --> <ul class="nav navbar-nav"> <li class="active"><a href="${path}/home">Home</a> </ul> <li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">게시판<span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="${path}/board/list.do">회원 게시판</a></li> <li><a href="${path}/board/best_list.do">베스트 게시물 게시판</a></li> </ul></li> <!-- 어떠한 아이디로든 로그인되지 않았을 경우에만 회원가입 링크를 출력시킨다. --> <c:if test="${sessionScope.user_id == null and sessionScope.navername == null and sessionScope.kakaonickname == null and sessionScope.facebookname == null and sessionScope.admin_id == null}"> <li><a href="${path}/member/email.do">회원가입</a></li> </c:if> <!-- 관리자가 로그인 하지 않았을 경우에만 로그인 링크를 출력시킴 --> <c:if test="${sessionScope.user_id == null and sessionScope.navername == null and sessionScope.kakaonickname == null and sessionScope.facebookname == null and sessionScope.admin_id == null}"> <li><a href="${path}/admin/admin_login_view.do">관리자 로그인</a></li> </c:if> <li><a href="${path}/board/admin_board_list.do">공지사항</a></li> <c:if test="${sessionScope.admin_id != null}"> <li class="dropdown"><a class="dropdown-toggle" data-toggle="dropdown" href="#">관리자 메뉴<span class="caret"></span></a> <ul class="dropdown-menu"> <li><a href="${path}/admin/admin_member_forced_eviction_view.do">회원 강제 탈퇴</a></li> <li><a href="${path}/admin/admin_member_info.do">회원 정보</a></li> </ul></li> </c:if> </div> </div> </nav> </body> </center> </html> | cs |
출처 http://blog.naver.com/PostView.nhn?blogId=aroma104&logNo=220461569593&parentCategoryNo=&categoryNo=34&viewDate=&isShowPopularPosts=true&from=search
Back-End/Spring 2019. 9. 27. 15:25
조회수가 50이 넘는 게시물은 제목 옆에 hit 애니메이션이 출력되도록 하고,
추천수 상위 3개의 글은 1위,2위,3위 애니메이션이 출력되도록 설정, 나머지 4위~10위 까지는 이달의 추천글 애니메이션이 출력되도록 함.
그리고 마우스 커서를 올리면 게시글의 색상이 변하도록 구현함
bestboard.jsp
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 | <%@ 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> <%@ include file="../include/header.jsp"%> <%@ include file="../include/menu.jsp"%> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
디자인 관련 (css 관련 코드들)
<link rel = "stylesheet" href = "/css/bootstrap.css"> <style> #container { width: 70%; margin: 0 auto; /* 가로로 중앙에 배치 */ padding-top: 10%; /* 테두리와 내용 사이의 패딩 여백 */ } #list { text-align: center; } #write { text-align: right; } /* Bootstrap 수정 */ .table > thead { background-color: #b3c6ff; } .table > thead > tr > th { text-align: center; } .table-hover > tbody > tr:hover { background-color: #e6ecff; } .table > tbody > tr > td { text-align: center; } .table > tbody > tr > #title { text-align: left; } div > #paging { text-align: center; } .hit { animation-name: blink; animation-duration: 1.5s; animation-timing-function: ease; animation-iteration-count: infinite; /* 위 속성들을 한 줄로 표기하기 */ /* -webkit-animation: blink 1.5s ease infinite; */ } /* 애니메이션 지점 설정하기 */ /* 익스플로러 10 이상, 최신 모던 브라우저에서 지원 */ @keyframes blink { from {color: white;} 30% {color: yellow;} to {color: red; font-weight: bold;} /* 0% {color:white;} 30% {color: yellow;} 100% {color:red; font-weight: bold;} */ } </style>
<script> //게시판 목록 페이지로 이동하게 하는 함수 function list(page){ console.log("페이지를 이동합니다."); location.href="list.do?curPage="+page; }; </script> <%@ include file="../include/login.jsp"%><br> <center> <div id = "list"> <b>베스트 게시물 게시판</b> </div> <div> <!-- 해당 table 클래스는 마우스를 올려놓았을때 게시글의 색깔이 파란색으로 변하도록 하는 클래스 --> <table class="table table-striped table table-hover"> <center> <thead> <tr> <!-- width옆에 %는 테이블에서 차지할 비율을 나타낸것 --> <th width="20%"><span style="color: green; font-weight: bold;">추천수 순위</span></th> <th width="10%">게시글 번호</th> <th width="15%">제목</th> <th width="15%">작성자</th> <th width="15%">내용</th> <th width="15%">날짜</th> <th width="5%">조회수</th> <th width="5%">추천수</th> </tr> </thead> <tbody> <!-- forEach var = "개별데이터" items = "집합데이터" --> <c:forEach var = "row" items = "${map.list}" varStatus="status"> <!-- 컨트롤러에서 map안에 list를 넣었기 때문에 이렇게 받는다. --> <tr> <td> <center> <!-- hit를 사용해서 추천수 상위 1~3위 까지는 순위 애니메이션이 출력되도록 함 --> <c:if test="${row.rk <= 3 }"> <span class = "hit" size = "7">${row.rk}위!!</span> </c:if> <!-- hit를 사용해서 추천수 상위 1~3위 까지는 이달의 추천글 애니메이션이 출력되도록 함 --> <c:if test="${row.rk >= 4 }"> <span class = "hit" size = "4">이달의 추천글!!</span> </c:if> </font> </center> </td> <!-- 게시글 순위 --> <td><center>${row.member_bno}</center></td> <!-- 글번호 --> <!-- 클릭하면 컨트롤러의 view.do로 이동하고, 게시물번호, 페이지 번호, 검색옵션, 키워드를 같이 넘긴다 --> <!-- 조회수가 50이 넘는 글은 제목옆에 hit라는 애니메이션이 출력되도록 함 --> <td id ="title"> <a href="best_board_view.do?member_bno=${row.member_bno}">${row.title}</a> <c:if test="${row.viewcnt >= 50 }"> <span class = "hit">hit!!</span> </c:if> </td> <td>${row.user_id}</td> <!-- 작성자의 이름 --> <td>${row.content}</td> <!-- 글의내용 --> <td>${row.reg_date}</td> <!-- 날짜의 출력형식을 변경함 --> <td><center>${row.viewcnt}</center></td> <!-- 조회수 --> <td><center>${row.recommend}</center></td> <!-- 추천수 --> </tr> </c:forEach> </tbody> </table> </div> <form name="form1" method="post" action="list.do"> <select name="search_option"> <option value="user_id" <c:if test="${map.search_option == 'user_id'}">selected</c:if> >작성자</option> <option value="title" <c:if test="${map.search_option == 'title'}">selected</c:if> >제목</option> <option value="content" <c:if test="${map.search_option == 'content'}">selected</c:if> >내용</option> <option value="all" <c:if test="${map.search_option == 'all'}">selected</c:if> >작성자+내용+제목</option> </select> <input name="keyword" value="${map.keyword}"> <input type="submit" value="조회"> </form> </center> <br><br><%@ include file="../include/Botton.jsp"%> </body> </html> | cs |
Back-End/Spring 2019. 9. 26. 17:34
회원 게시판에 있는 게시글 중에 추천수 상위 10개의 글만 '베스트 게시물 게시판' 으로 옮겨서 출력하기.
만약 추천수가 동일하다면 조회수 순으로 순위를 매기도록 구현함.
menu.jsp (메뉴 출력 view)
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 | <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!-- views/include/menu.jsp --> <%@ include file="header.jsp"%> <center> <!-- 다른 기능들 링크가 걸려있는 메뉴 페이지 --> ㅣ <a href="${path}/home">메인페이지</a> ㅣ <!-- 어떠한 아이디로든 로그인되지 않았을 경우에만 회원가입 링크를 출력시킨다. --> <c:if test = "${sessionScope.user_id == null and sessionScope.navername == null and sessionScope.kakaonickname == null and sessionScope.facebookname == null and sessionScope.admin_id == null}"> <a href="${path}/member/email.do">회원가입</a> ㅣ </c:if> <a href="${path}/board/list.do">회원 게시판</a> ㅣ <a href="${path}/board/best_list.do">베스트 게시물 게시판</a> ㅣ <!-- 관리자가 로그인 하지 않았을 경우에만 로그인 링크를 출력시킴 --> <c:if test = "${sessionScope.user_id == null and sessionScope.navername == null and sessionScope.kakaonickname == null and sessionScope.facebookname == null and sessionScope.admin_id == null}"> <a href="${path}/admin/admin_login_view.do">관리자 로그인</a> ㅣ </c:if> <a href="${path}/board/admin_board_list.do">공지사항</a> ㅣ <br> <br> <c:if test = "${sessionScope.admin_id != null}"> 관리자 메뉴 : ㅣ <a href="${path}/admin/admin_member_forced_eviction_view.do">회원 강제 탈퇴</a> ㅣ <a href = "${path}/admin/admin_member_info.do">회원 정보</a> ㅣ </c:if> </center> | cs |
bestboard.jsp (베스트 게시글 목록 페이지)
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 | <%@ 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> <%@ include file="../include/header.jsp"%> <%@ include file="../include/menu.jsp"%> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> //게시판 목록 페이지로 이동하게 하는 함수 function list(page){ console.log("페이지를 이동합니다."); location.href="list.do?curPage="+page; }; </script> <%@ include file="../include/login.jsp"%><br> <center> <h2>베스트 게시물 게시판</h2> <table border = "1" width = "800px" align = "top"> <center> <tr> <th>추천수 순위</th> <th>회원 게시글 번호</th> <th>제목</th> <th>작성자</th> <th>내용</th> <th>날짜</th> <th>조회수</th> <th>추천수</th> <!-- forEach var = "개별데이터" items = "집합데이터" --> <c:forEach var = "row" items = "${map.list}"> <!-- 컨트롤러에서 map안에 list를 넣었기 때문에 이렇게 받는다. --> <tr> <td>${row.rk}</td> <!-- 게시글 순위 --> <td>${row.member_bno}</td> <!-- 글번호 --> <!-- 클릭하면 컨트롤러의 view.do로 이동하고, 게시물번호, 페이지 번호, 검색옵션, 키워드를 같이 넘긴다 --> <td> <a href="best_board_view.do?member_bno=${row.member_bno}">${row.title}</a> <c:if test="${row.rcnt > 0}"> <span style="color:red;">( ${row.rcnt} )</span> </c:if> </td> <td>${row.user_id}</td> <!-- 작성자의 이름 --> <td>${row.content}</td> <!-- 글의내용 --> <td>${row.reg_date}</td> <!-- 날짜의 출력형식을 변경함 --> <td>${row.viewcnt}</td> <!-- 조회수 --> <td>${row.recommend}</td> <!-- 추천수 --> </tr> </c:forEach> </table> <form name="form1" method="post" action="list.do"> <select name="search_option"> <option value="user_id" <c:if test="${map.search_option == 'user_id'}">selected</c:if> >작성자</option> <option value="title" <c:if test="${map.search_option == 'title'}">selected</c:if> >제목</option> <option value="content" <c:if test="${map.search_option == 'content'}">selected</c:if> >내용</option> <option value="all" <c:if test="${map.search_option == 'all'}">selected</c:if> >작성자+내용+제목</option> </select> <input name="keyword" value="${map.keyword}"> <input type="submit" value="조회"> </form> </center> <br><br><%@ include file="../include/Botton.jsp"%> </body> </html> | cs |
bestboardview.jsp (베스트 게시글 상세보기 페이지)
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 | <%@ 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> <%@ include file="../include/header.jsp" %> <%@ include file="../include/menu.jsp" %> <script src="${path}/include/js/common.js"></script> <script src="${path}/ckeditor/ckeditor.js"></script> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(function(){ //목록 버튼 $("#btnList").click(function(){ location.href="best_list.do"; }); //추천하기 버튼 $("#btnRecommend").click(function(){ if(confirm("해당 글을 추천하시겠습니까?")){ document.form1.action="recommend.do"; document.form1.submit(); alert("해당 글을 추천하였습니다.") } }); }); </script> <h2>베스트 게시물 보기</h2> <!-- 게시물을 작성하기 위해 컨트롤러의 insert.do로 맵핑 --> <form id="form1" name="form1" method="post" action="${path}/board/insert.do"> <input type = "hidden" id = "member_bno" name = "member_bno" value = "${dto.member_bno }"> <div>제목 <input name="title" id="title" size="80" value="${dto.title}" placeholder="제목을 입력하세요"><br><br> <!-- placeholder은 제목을 입력할 수 있도록 도움말을 출력함 --> </div> <div>조회수 : ${dto.viewcnt} </div><br><br> <div style="width:800px;"> <textarea id="content" name="content" rows="3" cols="80" placeholder="내용을 입력하세요">${dto.content}</textarea></div><br><br> </form> <!-- 마찬가지로 내용을 입력하도록 도움말을 출력함 --> <script> // ckeditor 적용 //id가 content인 태그 (글의 내용을 입력하는 태그)를 ck에디터를 적용한다는 의미 CKEDITOR.replace("content",{ height: "300px" }); CKEDITOR.replace("r_content",{ height: "300px" }); </script> <div style = "width:700px; text-align:center;"> <!-- 수정, 삭제에 필요한 글번호를 hidden 태그에 저장한다. --> <input type = "hidden" name = "member_bno" value = "${dto.member_bno }"> <!-- 관리자에게는 삭제 버튼을 표시한다. --> <c:if test = "${sessionScope.admin_id != null}"> <button type = "button" id = "btnDelete">삭제</button> </c:if> <!-- 로그인이 되어있고, 본인 글이 아닐경우에만 추천할 수 있도록 버튼을 출력 --> <c:if test = "${sessionScope.user_id != null and sessionScope.user_id != dto.user_id or sessionScope.navername != null and sessionScope.navername != dto.user_id or sessionScope.kakaonickname != null and sessionScope.kakaonickname != dto.user_id or sessionScope.facebookname != null and sessionScope.facebookname != dto.user_id}"> <button type = "button" id = "btnRecommend">추천하기</button> </c:if> <!-- 관리자에게도 추천 버튼 출력 --> <!-- 관리자에게는 삭제 버튼을 표시한다. --> <c:if test = "${sessionScope.admin_id != null}"> <button type = "button" id = "btnRecommend">추천하기</button> </c:if> <!-- 글목록은 본인이 아니어도 확인 가능하게 한다. --> <button type = "button" id = "btnList">목록</button><br><br> <body> <br><br><%@ include file="../include/Botton.jsp"%> </body> </html> | cs |
MemberBoardController.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 | package com.example.hansub_project.controller.board; import java.io.PrintWriter; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.servlet.ModelAndView; import com.example.hansub_project.Member_Pager; import com.example.hansub_project.controller.member.MemberController; import com.example.hansub_project.model.board.dto.MemberBoardDTO; import com.example.hansub_project.model.board.dto.MemberBoardReplyDTO; import com.example.hansub_project.model.member.dto.MemberDTO; import com.example.hansub_project.service.board.MemberBoardService; import com.example.hansub_project.service.member.MemberService; @Controller //게시판 관련 컨트롤러를 선언함 public class MemberBoardController { @Inject //서비스를 호출하기위해서 의존성을 주입함 MemberBoardService memberboardservice; @Inject MemberService memberservice; //로깅을 위한 변수 private static final Logger logger= LoggerFactory.getLogger(MemberBoardController.class); //베스트 게시판 게시글 출력 @RequestMapping("/board/best_list.do") //세부적인 url mapping public ModelAndView best_list(//RequestParam으로 옵션, 키워드, 페이지의 기본값을 각각 설정해준다. ) throws Exception{ List<MemberBoardDTO> list = memberboardservice.bestlistAll(); ModelAndView mav = new ModelAndView(); Map<String,Object> map = new HashMap<>(); //넘길 데이터가 많기 때문에 해쉬맵에 저장한 후에 modelandview로 값을 넣고 페이지를 지정 map.put("list", list); //map에 list(게시글 목록)을 list라는 이름의 변수로 자료를 저장함. mav.addObject("map", map); //modelandview에 map를 저장 mav.setViewName("board/bestboard"); //자료를 넘길 뷰의 이름 return mav; //게시판 페이지로 이동 } //베스트 게시판 게시물 세부 내용 확인 @RequestMapping(value = "/board/best_board_view", method= {RequestMethod.GET, RequestMethod.POST}) public ModelAndView best_board_view(@RequestParam int member_bno, HttpSession session) throws Exception{ //조회수 증가 쿼리 memberboardservice.increaseViewcnt(member_bno, session); ModelAndView mav = new ModelAndView(); mav.setViewName("board/bestboardview"); //view로 자료를 넘기기위해서 mav에 값들을 저장해서 view.jsp로 리턴시킨다. mav.addObject("dto", memberboardservice.read(member_bno)); //상세보기를 한번 클릭하면 조회수를 1증가시킨다. return mav; //view로 넘어가서 출력이 된다. } } | cs |
MemberBoardServiceImpl.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 | package com.example.hansub_project.service.board; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.inject.Inject; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Service; import com.example.hansub_project.model.board.dao.MemberBoardDAO; import com.example.hansub_project.model.board.dto.MemberBoardDTO; @Service //서비스 빈으로 설정함 public class MemberBoardServiceImpl implements MemberBoardService { @Inject //dao를 호출하기 때문에 의존성을 주입한다. MemberBoardDAO memberboarddao; @Override public void create(MemberBoardDTO dto) throws Exception { memberboarddao.create(dto); //dto를 매개값으로 dao를 호출한다. } //게시물 읽기 @Override public MemberBoardDTO read(int member_bno) throws Exception { return memberboarddao.read(member_bno); } //게시글 수정 @Override public void update(MemberBoardDTO dto) throws Exception { memberboarddao.update(dto); } //게시물 삭제 관련 메소드 @Override public void delete(int member_bno) throws Exception { memberboarddao.delete(member_bno); } @Override public List<MemberBoardDTO> listAll(String search_option, String keyword,int start, int end) throws Exception { return memberboarddao.listAll(search_option, keyword, start, end); } //조회수를 증가하게하는 쿼리 //조회수 처리를 할때 일정 시간이 지난후 다시 클릭할때만 조회수가 증가하도록 설정 @Override public void increaseViewcnt(int member_bno, HttpSession session) throws Exception { long update_time = 0; //null을 방지하기 위해 초기값을 null로 설정함 if(session.getAttribute("update_time_"+member_bno)!=null) { //최근에 조회수를 올린 시간이 null이 아니면 update_time = (long)session.getAttribute("update_time_"+member_bno); } long current_time = System.currentTimeMillis(); //일정 시간이 경과한 후에 조회수를 증가시킨다. if(current_time - update_time > 5 * 1000) { //조회수가 1증가했을때로부터 5000초 후에 다시 클릭을 해야 조회수가 다시 1 증가한다는 말이다. //조회수 증가 처리 memberboarddao.increateViewcnt(member_bno); //조회수를 올린 시간을 저장함 session.setAttribute("update_time_"+member_bno, current_time); } } @Override public int countArticle(String search_option, String keyword) throws Exception { return memberboarddao.countArticle(search_option,keyword); } //게시글 추천관련 메소드 구현 @Override public void recommend(int member_bno) throws Exception { memberboarddao.recommend(member_bno); } //베스트 게시판 게시글 목록 출력 @Override public List<MemberBoardDTO> bestlistAll() throws Exception { return memberboarddao.bestlistAll(); } } | cs |
MemberBoardDAOImpl.java (게시판 DAO 중 일부)
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 | package com.example.hansub_project.model.board.dao; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import org.apache.ibatis.session.SqlSession; import org.springframework.stereotype.Repository; import com.example.hansub_project.model.board.dto.MemberBoardDTO; import com.example.hansub_project.model.member.dao.MemberDAO; @Repository //dao 선언 public class MemberBoardDAOImpl implements MemberBoardDAO { @Inject //db에 접속하기 위해 의존관계를 주입 SqlSession sqlSession; //게시글 쓰기 @Override public void create(MemberBoardDTO dto) throws Exception { sqlSession.insert("memberboard.insert",dto); } //게시글 수정 @Override public void update(MemberBoardDTO dto) throws Exception { sqlSession.update("memberboard.update", dto); } //게시물 삭제 관련 @Override public void delete(int member_bno) throws Exception { sqlSession.delete("memberboard.deleteArticle", member_bno); //mapper로 게시글 번호를 넘긴다. } //게시물 목록을 리턴 @Override public List<MemberBoardDTO> listAll(String search_option, String keyword, int start, int end) throws Exception { Map<String,Object> map = new HashMap<>(); map.put("search_option", search_option); map.put("keyword", keyword); map.put("start", start); //맵에 자료 저장 map.put("end", end); //매개변수는 시작 레코드의 번호, 끝 번호, 옵션과 키워드가 들어간다. return sqlSession.selectList("memberboard.listAll", map); } //조회수 증가처리를 하는 메소드 @Override public void increateViewcnt(int member_bno) throws Exception { sqlSession.update("memberboard.increaseViewcnt", member_bno); } @Override public int countArticle(String search_option, String keyword) throws Exception { Map<String,String> map=new HashMap<>(); map.put("search_option", search_option); map.put("keyword", "%"+keyword+"%"); return sqlSession.selectOne("memberboard.countArticle",map); } //게시글 상세정보 @Override public MemberBoardDTO read(int member_bno) throws Exception { return sqlSession.selectOne("memberboard.read", member_bno); } //추천수 증가처리 메소드 @Override public void recommend(int member_bno) throws Exception { sqlSession.update("memberboard.recommend", member_bno); } //베스트 게시글 게시판 게시글 목록 출력 @Override public List<MemberBoardDTO> bestlistAll() throws Exception { return sqlSession.selectList("bestboard.bestlistAll"); } } | cs |
bestboardMapper.xml (베스트 게시판 관련 게시글 목록 출력 Mapper)
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 | <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- 다른 mapper와 중복되지 않도록 네임스페이스 기재 --> <mapper namespace="bestboard"> <!-- 베스트게시물 게시판에 출력되는 목록 mapper -->
<!-- 순위를 출력할때 먼저 추천수 기준으로 순위를 매기고 추천수가 동일한 경우에는 조회수를 기준으로 순위를 다시 매겨서 중복이 없도록 출력한다. -->
<select id="bestlistAll" resultType="com.example.hansub_project.model.board.dto.MemberBoardDTO"> select member_bno, user_id, reg_date, viewcnt, title, rcnt, content, recommend, row_number() over (order by recommend desc, viewcnt desc) as rk from ( select recommend, member_bno, user_id, reg_date, viewcnt, title, rcnt, content from member_board order by recommend desc ) <![CDATA[where rownum <= 10]]> </select> </mapper> | cs |
|