43일차 내용 정리

채공부·2025년 7월 23일

CSS & BootStrap

column 의 정렬

align-items

align-items-start : 위 정렬
align-items-center : 가운데 정렬
align-items-end : 아래 정렬
align-items-stretch : 늘리기 = default 값

<div class="container">
	<h1>column 의 정렬</h1>
	<div class="row align-items-start">
 		<div class="col">1</div>
		<div class="col">2</div>
	</div>
	<div class="row align-items-center">
		<div class="col">1</div>
		<div class="col">2</div>
	</div>
	<div class="row align-items-end">
		<div class="col">1</div>
		<div class="col">2</div>
	</div>
</div>
⭐ 자식의 정렬을 부모가 결정

align-self

align-self-start
align-self-center
align-self-end

justify-content

  • 수평 정렬

justify-content-start : 좌측 정렬
justify-content-center : 가운데 정렬
justify-content-end : 우측 정렬
justify-content-around :어떤 칼럼의 주변을 똑같이 설정
justify-content-between : 칼럼의 사이를 공간을 똑같이 설정
justify-content-evenly : 주변의 공간을 다 똑같이 설정

⭐ 부모가 자식의 수평 정렬 지정 가능

card

  • card 형태의 레이아웃
<div class="container">
	<h1>Card Component 사용해 보기</h1>
	<div class="row">
		<div class="col-3">
			<div class="card">
				<img class="card-img-top" src="images/1.jpg"/>
				<div class="card-body">
					<h3 class="card-title">제목</h3>
					<p class="card-text">Lorem ipsum dolor sit amet consectetur adipisicing elit.
                       Quidem iusto quos animi, quaerat tempora inventore similique, ipsam quisquam repudiandae voluptatibus perferendis vel alias vero hic ipsum recusandae labore!
                       Perferendis, nulla.</p>
					<a href="#" class="btn btn-success">자세히 보기</a>
				</div>
			</div>
		</div>
	</div>
</div>

댓글 레이아웃

.card-body img{
	width:50px;
	height:50px;
}
<div class="container">
    <h1>댓글 출력 레이아웃 sample</h1>
    <div class="card mb-3">
        <div class="card-body d-flex">
            <img class="rounded-circle me-3" src="images/1.jpg" alt="프로필 이미지">
            <div class="flex-grow-1">
                <div class="d-flex justify-content-between">
                    <div>
                        <strong>작성자: 유재석</strong>
                        <span>수신자: 전체</span>
                    </div>
                    <small>25.07.25 12:00</small>
                </div>
                <pre>이건 첫번째 댓글입니다</pre>
                <button class="btn btn-sm btn-outline-primary show-reply-btn">댓글</button>
                <!-- 댓글 입력 폼 (처음에는 숨김)-->
                <div class="d-none form-div">
                    <form action="comment-save.jsp" method="post">
                        <textarea class="form-control mb-2" rows="2" placeholder="댓글을 입력하세요"></textarea>
                        <button type="submit" class="btn btn-sm btn-success">등록</button>
                        <button type="reset" class="btn btn-sm btn-secondary cancel-reply-btn">취소</button>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
 // 모든 댓글 버튼에 이벤트 등록
document.querySelectorAll(".show-reply-btn").forEach(item=>{
	// 매개변수에 전달된 item 은 댓글 button 의 참조값이다
	item.addEventListener("click", ()=>{
		// 클릭한 버튼의 다음 형제 요소의 class 모곡에서 d-none 을 제거
		item.nextElementSibling.classList.remove("d-none");
		// 클릭한 버튼의 class 목록에 d-none 을 추가
		item.classList.add("d-none");
    });
});

document.querySelectorAll(".cancel-reply-btn").forEach(item=>{
	item.addEventListener("click", ()=>{
		// 가장 가까운 부모 요소 중에 클래스 속성이 form-div 인 요소
		const formDiv =  item.closest(".form-div");
      	// formDiv 에 d-none 클래스를 추가해서 안 보이게 하고
		formDiv.classList.add("d-none");
      	// formDiv 의 이전 형제 요소(댓글 버튼)에 d-none 클래스를 제거해서 보이게 한다
		// previousElementSibling : 이전 형제 요소
		formDiv.previousElementSibling.classList.remove("d-none");
	});
});

JAVA & JSP

게시판

댓글 & 대댓글

  • view.jsp 에 댓글 코드 추가
<div class="card my-3">
    <div class="card-header bg-primary-subtle text-white">
        댓글을 입력해 주세요
    </div>
    <div class="card-body">
        <!-- 원글의 댓글을 작성할 폼 -->
        <form action="save-comment.jsp" method="post">
            <!-- 숨겨진 입력값 -->
            <input type="hidden" name="parentNum" value="<%=dto.getNum() %>"/>
            <input type="hidden" name="targetWriter" value="<%=dto.getWriter() %>" />

            <div class="mb-3">
                <label for="commentContent" class="form-label">댓글 내용</label>
                <textarea id="commentContent" name="content" rows="5" class="form-control" placeholder="댓글을 입력하세요"></textarea>
            </div>

            <button type="submit" class="btn bg-primary-subtle text-white">등록</button>
        </form>
    </div>
</div>
  • CommentDto 생성
public class CommentDto {
	private int num;
	private String writer;
	private String content;
	private String targetWriter;
	private int groupNum;
	private int parentNum;
	private String deleted;
	private String createdAt;
	
	// 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 getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getTargetWriter() {
		return targetWriter;
	}
	public void setTargetWriter(String targetWriter) {
		this.targetWriter = targetWriter;
	}
	public int getGroupNum() {
		return groupNum;
	}
	public void setGroupNum(int groupNum) {
		this.groupNum = groupNum;
	}
	public int getParentNum() {
		return parentNum;
	}
	public void setParentNum(int parentNum) {
		this.parentNum = parentNum;
	}
	public String getDeleted() {
		return deleted;
	}
	public void setDeleted(String deleted) {
		this.deleted = deleted;
	}
	public String getCreatedAt() {
		return createdAt;
	}
	public void setCreatedAt(String createdAt) {
		this.createdAt = createdAt;
	}
}
  • CommentDao 생성
public class CommentDao {
	private static CommentDao dao;
	static {
		dao = new CommentDao();
	}
	// 생성자를 private 로 해서 외부에서 객체 생성하지 못하도록
	private CommentDao() {}
	// 자신의 참조값을 리턴해주는 static 메소드를 제공한다
	public static CommentDao getInstance() {
		return dao;
	}
{
  • 저장할 댓글의 글 번호를 리턴해주는 메소드
public int getSequence() {
    int num = 0;
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;

    try {
        conn = new DbcpBean().getConn();
        String sql = """
            SELECT comments_seq.NEXTVAL AS num FROM DUAL
        """;
        pstmt = conn.prepareStatement(sql);
        rs = pstmt.executeQuery();

        if (rs.next()) {
            num = rs.getInt("num");
        }
    } 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 num;
}
  • 댓글 정보를 DB 에 저장하는 메소드
public boolean insert(CommentDto dto) {
    Connection conn = null;
    PreparedStatement pstmt = null;
    int rowCount = 0;

    try {
        conn = new DbcpBean().getConn();
        String sql = """
            INSERT INTO comments
            (num, writer, targetWriter, content, parentNum, groupNum)
            VALUES(?, ?, ?, ?, ?, ?)
        """;
        pstmt = conn.prepareStatement(sql);
        pstmt.setInt(1, dto.getNum());
        pstmt.setString(2, dto.getWriter());
        pstmt.setString(3, dto.getTargetWriter());
        pstmt.setString(4, dto.getContent());
        pstmt.setInt(5, dto.getParentNum());
        pstmt.setInt(6, dto.getGroupNum());

        rowCount = pstmt.executeUpdate();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            if (pstmt != null) pstmt.close();
            if (conn != null) conn.close();
        } catch (Exception e) {
        }
    }
}
  • save-comment.jsp 생성
<%
	// 폼 전송되는 댓글 정보를 얻어낸다
	int parentNum = Integer.parseInt(request.getParameter("parentNum"));
	String targetWriter = request.getParameter("targetWriter");
	String content = request.getParameter("content");
	// 댓글 작성자 정보는 session 으로부터 얻어낸다
	String writer = (String) session.getAttribute("userName");
	// 저장할 댓글의 글 번호를 미리 얻어낸다
	int num = CommentDao.getInstance().getSequence();
	// 저장할 댓글 정보를 dto 에 담고
	CommentDto dto = new CommentDto();
	dto.setNum(num);
	dto.setWriter(writer);
	dto.setTargetWriter(targetWriter);
	dto.setContent(content);
	dto.setParentNum(parentNum);
	dto.setGroupNum(num); // 원글의 댓글은 자신의 글번ㄴ호가 댓글의 그룹번호
	// DB 에 저장하고
    boolean isSuccess = CommentDao.getInstance().insert(dto);
%>
  • CommentDto 에 프로필 이미지를 출력하기 위한 필드 추가
private String profileImage;

public String getProfileImage() {
	return profileImage;
}
public void setProfileImage(String profileImage) {
	this.profileImage = profileImage;
}
  • 원글(parentNum) 에 달린 모든 댓글을 리턴하는 메소드
public List<CommentDto> selectList(int parentNum) {
    List<CommentDto> list = new ArrayList<>();
    Connection conn = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
        conn = new DbcpBean().getConn();
        String sql = """
            SELECT num, writer, targetWriter, content, deleted, groupNum,
                   createdAt, profileImage
            FROM comments
            INNER JOIN users ON comments.writer = users.userName
            WHERE parentNum = ?
            ORDER BY groupNum DESC, num ASC
            """;
        pstmt = conn.prepareStatement(sql);
        pstmt.setInt(1, parentNum);
        rs = pstmt.executeQuery();

        while (rs.next()) {
            CommentDto dto = new CommentDto();
            dto.setNum(rs.getInt("num"));
            dto.setWriter(rs.getString("writer"));
            dto.setTargetWriter(rs.getString("targetWriter"));
            dto.setContent(rs.getString("content"));
            dto.setParentNum(parentNum);
            dto.setGroupNum(rs.getInt("groupNum"));
            dto.setDeleted(rs.getString("deleted"));
            dto.setCreatedAt(rs.getString("createdAt"));
            dto.setProfileImage(rs.getString("profileImage"));

            list.add(dto);
        }
    } 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;
}
  • view.jsp 코드 추가
<%
	// 댓글 목록 DB 에서 읽어오기
	List<CommentDto> commentList = CommentDao.getInstance().selectList(num);
%>
profile
학원 공부 내용 정리

0개의 댓글