41일차 내용 정리

채공부·2025년 7월 21일

CSS

width : 100%
width : 50%
width : 25%

@media

  • 조건을 설정하여 적용하는 css
<link rel="stylesheet" href="css/responsive.css">
<style>
	.box{
		width : 100px;
		height : 100px;
		border : 1px solid red;
	}
</style>

    <div class="box color color-sm color-md"></div>
/* 화면의 폭과 상관없이 적용할 css */
.color{
    background-color:yellow;
}
/* 화면의 폭이 최소 576px 이상일 때 적용할 css*/
@media(min-width:576px){
    .color-sm{
        background-color:yellowgreen;
    }
}
@media(min-width:768px){
    .color-md{
        background-color:blue;
    }
}
⭐ 선택자의 구체성이 동일한 경우 나중에 작성한 css가 적용

JSP & JAVA

게시판

페이징

SELECT *
FROM
	(SELECT result1.*, ROWNUM AS num  2. 행번호 부여
    FROM
    	(SELECT num, writer, title    1. 정렬
        FROM board
        ORDER BY num DESC) result1)
WHERE rnum BETWEEN 1 AND 5			  3. 원하는 행만 SELECT

startRowNum & endRowNum 을 구하는 일반식만 작성하면 해결

startRowNum : 공차수열 일반화
endRowNum : 등비수열 일반화

  • BoardDto 재정의
public class BoardDto {
	private int num;
	private String writer;
	private String title;
	private String content;
	private int viewCount;
	private String createdAt;
	// 페이징 처리를 위한 필드
	private int startRowNum;
	private int endRowNum;
	
	// setter, getter 
	public int getNum() {
		return num;
	}
	public void setNum(int num) {
		this.num = num;
	}
	public String getWriter() {
		return writer;
	}
	public void setWriter(String writer) {
		this.writer = writer;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public int getViewCount() {
		return viewCount;
	}
	public void setViewCount(int viewCount) {
		this.viewCount = viewCount;
	}
	public String getCreatedAt() {
		return createdAt;
	}
	public void setCreatedAt(String createdAt) {
		this.createdAt = createdAt;
	}
	public int getStartRowNum() {
		return startRowNum;
	}
	public void setStartRowNum(int startRowNum) {
		this.startRowNum = startRowNum;
	}
	public int getEndRowNum() {
		return endRowNum;
	}
	public void setEndRowNum(int endRowNum) {
		this.endRowNum = endRowNum;
	}
}
  • 특정 page 에 해당하는 row 만 select 해서 리턴하는 메소드
  • BoardDto 객체에 startRowNum 과 endRowNum 을 담아와서 select
public List<BoardDto> selectPage(BoardDto dto){
	List<BoardDto> list=new ArrayList<>();
	
	//필요한 객체를 담을 지역변수를 미리 만든다 
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	try {
		conn = new DbcpBean().getConn();
		String sql = """
			SELECT *
			FROM
				(SELECT result1.*, ROWNUM AS rnum
				FROM	
					(SELECT num, writer, title, viewCount, createdAt
					FROM board
					ORDER BY num DESC) result1)
			WHERE rnum BETWEEN ? AND ?
		""";
		pstmt = conn.prepareStatement(sql);
		pstmt.setInt(1, dto.getStartRowNum());
		pstmt.setInt(2, dto.getEndRowNum());

		rs = pstmt.executeQuery();

		while (rs.next()) {
			BoardDto dto2=new BoardDto();
			dto2.setNum(rs.getInt("num"));
			dto2.setWriter(rs.getString("writer"));
			dto2.setTitle(rs.getString("title"));
			dto2.setViewCount(rs.getInt("viewCount"));
			dto2.setCreatedAt(rs.getString("createdAt"));
				
			list.add(dto2);
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		try {
			if (rs != null)
				rs.close();
			if (pstmt != null)
				pstmt.close();
			if (conn != null)
				conn.close();
		} catch (Exception e) {
		}
	}
	return list;
}
  • list.jsp
<%
	// 기본 페이지 번호는 1 로 설정하고
	int pageNum = 1;
	// 페이지 번호를 읽어와서
	String strPageNum = request.getParameter("pageNum");
	// 전달되는 페이지 번호가 있다면
	if(strPageNum != null){
		// 해당 페이지 번호를 숫자로 변경해서 사용한다
		pageNum = Integer.parseInt(strPageNum);
	}
	
	// 한 페이지에 몇개 씩 표시할 것인지
	final int PAGE_ROW_COUNT = 5;
	
	// 보여줄 페이지의 시작 ROWNUM
	int startRowNum = 1+(pageNum-1)*PAGE_ROW_COUNT; // 공차 수열
	// 보여줄 페이지의 끝 ROWNUM
	int endRowNum= pageNum*PAGE_ROW_COUNT; // 등비 수열
	
	// dto 에 select 할 row 의 정보를 담고
	BoardDto dto = new BoardDto();
	dto.setStartRowNum(startRowNum);
	dto.setEndRowNum(endRowNum);
	
	// 해당 row 만 select 한다
	List<BoardDto> list = BoardDao.getInstance().selectPage(dto);
	
	// 글 목록 얻어오기
	// List<BoardDto> list = BoardDao.getInstance().selectAll();
%>
<style>
	ul a {
		text-decoration:none;
	}
	
	/* ul 요소이면서 클래스 속성의 값이 pagination 인 요소에 적용할 css */
	ul.my-pagination{
		list-style-type:none; /*ul 의 disc 없애기*/
		padding-left:0; /*왼쪽 padding 제거*/
		display:flex; /*자식 요소(li)를 flex 레이아웃으로 배치하기 위해 (가로배치)*/
		gap:10px; /*자식 요소 끼리 공간 부여하기*/
		justify-content:center; /*가로로 배치된 상태에서 가운데 정렬*/
	}
	
	.active{
		font-weight:bold;
		color:red;
		text-decoration:underline;
	}
</style>
<jsp:include page="/WEB-INF/include/navbar.jsp">
<jsp:param value="board" name="thisPage"/>
</jsp:include>
<div class="container pt-1">
	<a class="btn btn-outline-primary btn-sm" href="new-form.jsp">
	새 글 작성 <i class="bi bi-pencil-square"></i>
	</a>
	<h1>게시글 목록 입니다</h1>
	<table class="table table-bordered">
		<thead>
			<tr> 
				<th>글번호</th>
				<th>작성자</th>
				<th>제목</th>
				<th>조회수</th>
				<th>작성일</th>
			</tr>
		</thead>
		<tbody>
			<%for(BoardDto tmp : list) {%>
				<tr>
					<td><%=tmp.getNum()%></td>
					<td><%=tmp.getWriter()%></td>
					<td>
						<a href="view.jsp?num=<%=tmp.getNum()%>"><%=tmp.getTitle()%></a>
					</td>
					<td><%=tmp.getViewCount()%></td>
					<td><%=tmp.getCreatedAt()%></td>
				</tr>
			<%} %>
		</tbody>
	</table>
	<ul class="my-pagination">
		<%for(int i=1; i<=5; i++){%>
			<li>
				<a class="<%=i==pageNum ? "active":"" %>" href="list.jsp?pageNum=<%=i%>"><%=i %></a>
			</li>
		<%} %>
	</ul>
</div>
  • 전체 글의 갯수를 리턴하는 메소드
public int getCount() {
	int count = 0;
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	try {
		conn = new DbcpBean().getConn();
		// 글의 전체 갯수를 ROWNUM 중에서 가장 큰 값
		String sql = """
				SELECT MAX(ROWNUM) AS count
				FROM board
				""";
		pstmt = conn.prepareStatement(sql);

		rs = pstmt.executeQuery();

		if (rs.next()) {
			count = rs.getInt("count");
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		try {
			if (rs != null)
				rs.close();
			if (pstmt != null)
				pstmt.close();
			if (conn != null)
				conn.close();
		} catch (Exception e) {
		}
	}
	return count;
}
  • list.jsp 코드 수정
⚠️ 정수를 정수로 나누면 소수점이 버려진 정수가 나온다    
// 하단 페이지에를 몇개 씩 표시할 것인지
final int PAGE_DISPLAY_COUNT = 5;

//하단 시작 페이지 번호 
int startPageNum = 1 + ((pageNum-1)/PAGE_DISPLAY_COUNT)*PAGE_DISPLAY_COUNT;
//하단 끝 페이지 번호
int endPageNum = startPageNum+PAGE_DISPLAY_COUNT-1;
//전체 글의 갯수
int totalRow = BoardDao.getInstance().getCount();
//전체 페이지의 갯수 구하기
int totalPageCount = (int)Math.ceil(totalRow/(double)PAGE_ROW_COUNT);
//끝 페이지 번호가 이미 전체 페이지 갯수보다 크게 계산되었다면 잘못된 값이다.
if(endPageNum > totalPageCount){
	endPageNum=totalPageCount; //보정해 준다. 
}	
<ul class="pagination">
	<%for(int i=startPageNum; i<=endPageNum; i++){%>
		<li>
			<a class="<%=i==pageNum ? "active":"" %>" href="list.jsp?pageNum=<%=i%>"><%=i %></a>
		</li>
	<%} %>
</ul>

화살표 표시
> : &rsaquo;
< : &lsaquo;
>> : &raquo
<< : &laquo;

  • > & < 로 페이지 이동
<ul class="pagination">
	<!-- startPagNum 이 1이 아닐 때 이전 page 가 존재하기 때문에 -->
	<%if(startPageNum != 1) {%>
		<li>
			<a href="list.jsp?pageNum=<%=startPageNum-1%>">&lsaquo;</a>
		</li>
	<%} %>
	<%for(int i=startPageNum; i<=endPageNum; i++){%>
		<li>
			<a class="<%=i==pageNum ? "active":"" %>" href="list.jsp?pageNum=<%=i%>"><%=i %></a>
		</li>
	<%} %>
	<!-- endPageNum 이 totalPageNum 보다 작을 때 다음 page 가 있다 -->
	<%if(endPageNum < totalPageCount) {%>
		<li>
			<a href="list.jsp?pageNum=<%=endPageNum+1%>">&rsaquo;</a>
		</li>
	<%} %>
</ul>
<%if(startPageNum != 1) {%>
- prev 링크를 조건부로 출력

<%for(int i=startPageNum; i<=endPageNum; i++){%>
- page 번호를 반복문 돌면서 출력

<%if(endPageNum < totalPageCount) {%>
- next 링크를 조건부로 출력 
  • bootstarp 으로 list.jsp 를 css
<ul class="pagination">
	<!-- startPagNum 이 1이 아닐 때 이전 page 가 존재하기 때문에 -->
	<%if(startPageNum != 1) {%>
		<li class="page-item">
			<a class="page-link" href="list.jsp?pageNum=<%=startPageNum-1%>">&lsaquo;</a>
		</li>
	<%} %>
	<%for(int i=startPageNum; i<=endPageNum; i++){%>
		<li class="page-item">
			<a class="page-link <%=i==pageNum ? "active":"" %>" href="list.jsp?pageNum=<%=i%>"><%=i %></a>
		</li>
	<%} %>
	<-- endPageNum  totalPageNum 보다 작을  다음 page  있다 -->
	<%if(endPageNum < totalPageCount) {%>
		<li class="page-item">
			<a class="page-link" href="list.jsp?pageNum=<%=endPageNum+1%>">&rsaquo;</a>
		</li>
	<%} %>
</ul>

조회수

  • 특정 글의 조회수를 증가시키는 메소드
public boolean addViewCount(int num) {
	Connection conn = null;
	PreparedStatement pstmt = null;
	int rowCount = 0;
	try {
		conn = new DbcpBean().getConn();
		String sql = """
				UPDATE board
				SET viewCount = viewCount+1
				WHERE num = ?
				""";
		pstmt = conn.prepareStatement(sql);
		pstmt.setInt(1, num);
		rowCount = pstmt.executeUpdate();
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		try {
			if (pstmt != null)
				pstmt.close();
			if (conn != null)
				conn.close();
		} catch (Exception e) {
		}
	}
	if (rowCount > 0) {
		return true;
	} else {
		return false;
	}
}
  • view.jsp 코드 추가
<%
	// 만일 본인 글 자세히 보기가 아니면 조회수를 1 증가 시킨다
	if(!dto.getWriter().equals(userName)){
		BoardDao.getInstance().addViewCount(num);
	}
%>

프로필 이미지 출력

  • BoardDto 코드 추가
// 프로필 이미지 출력을 위한 필드
private String profileImage;

public String getProfileImage() {
	return profileImage;
}
public void setProfileImage(String profileImage) {
	this.profileImage = profileImage;
}
  • BoardDao의 getByNum 메소드 수정
public BoardDto getByNum(int num) {
	BoardDto dto = null;
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	try {
		conn = new DbcpBean().getConn();
		String sql = """
				SELECT writer, title, content, viewCount,
				TO_CHAR(b.createdAt, 'YY"년" MM"월" DD"일" HH24:MI') AS createdAt,
				profileImage
				FROM board b
				INNER JOIN users u ON b.writer = u.userName
				WHERE b.num = ?
				""";
		pstmt = conn.prepareStatement(sql);
		pstmt.setInt(1, num);
		rs = pstmt.executeQuery();

		if (rs.next()) {
			dto = new BoardDto();
			dto.setNum(num);
			dto.setWriter(rs.getString("writer"));
			dto.setTitle(rs.getString("title"));
			dto.setContent(rs.getString("content"));
			dto.setViewCount(rs.getInt("viewcount"));
			dto.setCreatedAt(rs.getString("createdAt"));
				dto.setProfileImage(rs.getString("profileImage"));
		}
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		try {
			if (rs != null)
				rs.close();
			if (pstmt != null)
				pstmt.close();
			if (conn != null)
				conn.close();
		} catch (Exception e) {
		}
	}
	return dto;
}
  • view.jsp 코드 수정
<tr>
	<th>작성자</th>
	<td>
		<%if(dto.getProfileImage() == null) {%>
			<i style="font-size:100px;" class="bi bi-person-circle"></i>
		<%} else{%>	
			<img src="${pageContext.request.contextPath }/upload/<%=dto.getProfileImage() %>" 
				style="width:100px;height:100px;border-radius:50%;"/>
		<%} %>
		<%=dto.getWriter()%>
	</td>
</tr>

새로운 폴더에 GitHub 저장소 clone하기

<기본 설정>
1. 다운 받은 apache 폴더를 다른COM 폴더에 복사하기
2. 다른COM > other_webwork 로 workspace
3. Servers 탭을 선택 후 빈 공간에 NEW > Server 선택
4. Apache > Tomcat 10.1 > Next 선택
5. Broswe 버튼을 눌러 압축 해제한 apache tomcat 폴더를 찾아 선택 후 finish
6. server.xml 파일에서 source 탭을 선택 후 64라인에 port 번호를 8888 로 설정한 후 저장
7. content.xml 에 </Context> 안에 해당 코드 넣기
 <Resource name="jdbc/myoracle" auth="Container"
             type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
             url="jdbc:oracle:thin:@127.0.0.1:1521:xe"
             username="scott" password="TIGER" maxTotal="20" maxIdle="10"
             maxWaitMillis="-1"/>
8. Servers 탭에서 run 을 클릭해 server 실행

<저장소 clone>
1. clone할 저장소 위치 복사
2. clone할 폴더 위치에 Git Bash 실행
3. git clone 저장소_위치
4. 해당 폴더에서 clone 결과 확인
5. eclipes git mode 에서 add 
6. Add an existing local Git repository 을 선택해 clone 된 Local 저장소를 찾아 등록
7. 찾은 저장소를 check 후에 add click
8. git mode 에서 Working Tree 에서 import할 프로젝트를 선택해서 import Projects 클릭
9. import 할 프로젝트 확인 후 finish
10. Java EE mode 로 전향 후 import 된 프로젝트를 확인
11. 해당 Project 에서 Properties 를 click
12. Project Facets > Convert to faceted form 에서
	Dynamic Web Module 을 선택해 Runtime 에 Tomcat을 check 하고 Apply and Close
    (JAVA 가 21 version인지 확인 필수)
profile
학원 공부 내용 정리

0개의 댓글