[Spring Boot] 부트스트랩 적용해보기

DANI·2023년 10월 1일
0
post-thumbnail

📕 부트스트랩이란?

부트스트랩(Bootstrap)은 디자이너의 도움 없이도 개발자 혼자서 상당히 괜찮은 수준의 웹 페이지를 만들수 있게 도와주는 프레임워크이다. 부트스트랩은 트위터(Twitter)를 개발하면서 만들어졌고 현재 지속적으로 관리되고 있는 오픈소스 프로젝트이다.

부트스트랩 다운로드 https://getbootstrap.com/docs/5.2/getting-started/download/

bootstrap.min.css 파일을 카피하여 스태틱 디렉터리에 저장

  • 📁 압축파일 내 경로 : bootstrap-5.2.3-dist.zip/bootstrap-5.2.3-dist/css/bootstrap.min.css
  • 📁 옮겨올 경로 : /sbb/src/main/resources/static/bootstrap.min.css

옮겨왔으면 sbb 프로젝트에서 우클릭 후 refresh




💻 부트스트랩 적용해보기

부트스트랩 클래스설명
card, card-body, card-text부트스트랩 Card 컴포넌트
badge부트스트랩 Badge 컴포넌트
form-control부트스트랩 Form 컴포넌트
border-bottom아래방향 테두리 선
my-3상하 마진값 3
py-2상하 패딩값 2
p-2상하좌우 패딩값 2
d-flex justify-content-end컴포넌트의 우측 정렬
bg-light연회색 배경
text-dark검은색 글씨
text-start좌측 정렬
btn btn-primary부트스트랩 버튼 컴포넌트

💾 question_list 파일 수정


<!-- 부트스트랩 적용 -->
<link rel="stylesheet" type="text/css" th:href="@{/bootstrap.min.css}">
<div class="container py-1"> <!-- 부트스트랩 적용 -->
	<table class = "table"> <!-- 부트스트랩 적용 -->
    	<thead class = "table-info"> <!-- 부트스트랩 적용 -->
        	<tr>
				<th>번호</th> <!-- 테이블 항목 추가 -->
            	<th>제목</th>
            	<th>작성일시</th>
        	</tr>
    	</thead>
    	<tbody>
       		<tr th:each="questionlist, loop : ${questionList}"> <!-- loop구문 사용 -->
				<td th:text="${loop.count}"></td>
            	<td>
					<a th:href="@{|/question/detail/${questionlist.id}|}" th:text="${questionlist.subject}"></a>
				</td>
                <!-- questionlist.createDate값을 포맷함 -->
            	<td th:text="${#temporals.format(questionlist.createDate, 'yyyy-MM-dd HH-mm')}"></td>
        	</tr>
    	</tbody>
	</table>
</div>


💡 부트스트랩을 적용하여 수정한 부분


<link rel="stylesheet" type="text/css" th:href="@{/bootstrap.min.css}">

<div class="container my-3">

class="container my-3" : 부트스트랩 스타일시트에 정의되어 있는 클래스
여기서 사용된 부트스트랩 클래스인 my-3은 위아래 방향 마진 3을 의미한다. py-2는 위아래 padding 2를 의미한다. d-flex justify-content-end 는 컴포넌트의 우측 정렬을 의미한다.

<table class = "table">
   👉 기본적으로 class에 "table"을 추가하여 Bootstrap table을 사용할 수 있다.
<thead class = "table-info">
   👉 색상을 지정함

https://getbootstrap.com/docs/5.2/content/tables/ 부트스트랩 참고



💡 그냥 수정한 부분


✅ 테이블 항목으로 <th>번호</th>를 추가했다. 번호는 loop.count를 사용하여 표시했다.

<td th:text="${#temporals.format(questionlist.createDate, 'yyyy-MM-dd HH-mm')}"></td>

#temporals.format(날짜객체, 날짜포맷) : 날짜객체를 날짜포맷에 맞게 변환한다.


💻 "http://localhost:8080/question/list" 접속해보기




질문 페이지가 예쁘게 수정되었다! 상세페이지에도 부트스트랩을 적용해보자!

💾 question_detail 파일 수정


<link rel="stylesheet" type="text/css" th:href="@{/bootstrap.min.css}">
<div class="container my-3">
    <!-- 질문 -->
    <h2 class="border-bottom py-2" th:text="${question.subject}"></h2>
    <div class="card my-3">
        <div class="card-body">
            <div class="card-text" style="white-space: pre-line;" th:text="${question.content}"></div>
            <div class="d-flex justify-content-end">
                <div class="badge bg-light text-dark p-2 text-start">
                    <div th:text="${#temporals.format(question.createDate, 'yyyy-MM-dd HH:mm')}"></div>
                </div>
            </div>
        </div>
    </div>
    <!-- 답변의 갯수 표시 -->
    <h5 class="border-bottom my-3 py-2" 
        th:text="|${#lists.size(question.answerList)}개의 답변이 있습니다.|"></h5>
    <!-- 답변 반복 시작 -->
    <div class="card my-3" th:each="answer : ${question.answerList}">
        <div class="card-body">
            <div class="card-text" style="white-space: pre-line;" th:text="${answer.content}"></div>
            <div class="d-flex justify-content-end">
                <div class="badge bg-light text-dark p-2 text-start">
                    <div th:text="${#temporals.format(answer.createDate, 'yyyy-MM-dd HH:mm')}"></div>
                </div>
            </div>
        </div>
    </div>
    <!-- 답변 반복 끝  -->
    <!-- 답변 작성 -->
    <form th:action="@{|/answer/create/${question.id}|}" method="post" class="my-3">
        <textarea name="content" id="content" rows="10" class="form-control"></textarea>
        <input type="submit" value="답변등록" class="btn btn-primary my-2">
    </form>
</div>

수정된 부분이 많으니 질문부분부터 보자!

1. 🔍 질문 부분

    <!-- 질문 -->
    <h2 class="border-bottom py-2" th:text="${question.subject}"></h2>
    <div class="card my-3">
        <div class="card-body">
            <div class="card-text" style="white-space: pre-line;" th:text="${question.content}"></div>
            <div class="d-flex justify-content-end">
                <div class="badge bg-light text-dark p-2 text-start">
                    <div th:text="${#temporals.format(question.createDate, 'yyyy-MM-dd HH:mm')}"></div>
                </div>
            </div>
        </div>
    </div>

💡 부트스트랩을 적용한 부분


<h2 class="border-bottom py-2" th:text="${question.subject}"></h2>
   👉 아래방향 테두리 선에 상하 패딩값 2를 준다

<div class="card my-3">
   👉 Card 컴포넌트를 적용시키고 상하 마진값 3을 준다.

<div class="card-body">
   👉 Card-body

<div class="card-text" style="white-space: pre-line;" th:text="${question.content}"></div>
   👉 Card-text 부트스트랩의 컴포넌트
   👉 style="white-space: pre-line;"

💬 white-space는 스페이스와 탭, 줄바꿈, 자동줄바꿈을 어떻게 처리할지 정하는 속성


¹스페이스와 탭²줄바꿈³자동 줄바꿈
normal병합병합O
nowrap병합병합X
pre보존보존X
pre-wrap보존보존O
pre-line병합보존O
1. 연속된 스페이스와 탭의 처리 방법입니다. 
병합은 1개의 공백으로 바꾸는 것이고, 보존은 입력된 그대로 출력하는 것입니다.
2. 줄바꿈의 처리방법입니다. 
병합은 1개의 공백으로 바꾸는 것이고, 보존은 입력된 그대로 출력하는 것입니다.
3. 내용이 영역의 크기를 벗어날 때 처리방법입니다. 
O는 자동으로 줄바꿈하여 영역 내에 내용을 표시하는 것이고, 
X는 영역을 벗어나더라도 입력된 대로 출력하는 것입니다.

<div class="d-flex justify-content-end">
   👉 컴포넌트의 우측 정렬

<div class="badge bg-light text-dark p-2 text-start">
   👉 badge 부트스트랩의 컴포넌트 / bg-light 연회색 배경 / text-dark 검은색 글씨 / p-2 상하좌우 패딩값 2 / text-start 좌측정렬



답변 개수부분을 보자!

2. 🔍 답변의 갯수 표시부분

    <!-- 질문 -->
    <h5 class="border-bottom my-3 py-2" 
        th:text="|${#lists.size(question.answerList)}개의 답변이 있습니다.|"></h5>

<h5 class="border-bottom my-3 py-2" th:text="|${#lists.size(question.answerList)}개의 답변이 있습니다.|"></h5>
   👉 아래방향 테두리 선에 상하 마진값3, 상하 패딩값 2를 준다





답변 반복 시작 부분을 보자

3. 🔍 답변 반복 시작부분

    <!-- 질문 -->
    <div class="card my-3" th:each="answer : ${question.answerList}">
        <div class="card-body">
            <div class="card-text" style="white-space: pre-line;" th:text="${answer.content}"></div>
            <div class="d-flex justify-content-end">
                <div class="badge bg-light text-dark p-2 text-start">
                    <div th:text="${#temporals.format(answer.createDate, 'yyyy-MM-dd HH:mm')}"></div>
                </div>
            </div>
        </div>
    </div>

💡 부트스트랩을 적용한 부분

<div class="card my-3" th:each="answer : ${question.answerList}">
<div class="card-body">
<div class="card-text" style="white-space: pre-line;" th:text="${question.content}"></div>
<div class="badge bg-light text-dark p-2 text-start"><div th:text="${#temporals.format(answer.createDate, 'yyyy-MM-dd HH:mm')}"></div>

질문 부분과 거의 비슷하다!





답변 작성부분을 보자!

4. 🔍 답변 작성부분

    <form th:action="@{|/answer/create/${question.id}|}" method="post" class="my-3">
        <textarea name="content" id="content" rows="10" class="form-control"></textarea>
        <input type="submit" value="답변등록" class="btn btn-primary my-2">
    </form>

class="form-control"
   👉 input, textaerea, select 등 하나의 요소를 감싸는 레벨과 클래스 ->.form-group이 있다. form-control 클래스는 input, textarea, select 요소에 삽입이 되어야한다.
class="btn btn-primary my-2" 부트스트랩의 버튼 컴포넌트


❓ margin과 padding의 차이는?


❗ Margin은 Object와 화면과의 여백(외부여백)을 말하며 Padding은 Object내의 내부여백을 의미합니다.





🔴 내가 변경해본 부트스트랩

<link rel="stylesheet" type="text/css" th:href="@{/bootstrap.min.css}">
<div class="container my-3">
    <!-- 질문 -->
    <div class="card my-3">
		<h2 class="card-header bg-info text-white border-bottom p-3" th:text="${question.subject}"></h2>
        <div class="card-body bg-light">
            <div class="card-text p-2" style="white-space: pre-line;" th:text="${question.content}"></div>
            <div class="d-flex justify-content-end">
                <div class="badge rounded-pill bg-info text-white">
                    <div th:text="${#temporals.format(question.createDate, 'yyyy-MM-dd HH:mm')}"></div>
                </div>
            </div>
        </div>
    </div>
    <!-- 답변의 갯수 표시 -->
    <div class="card my-3">
    	<h5 class="card-header bg-info text-white border-bottom p-3" 
        th:text="|${#lists.size(question.answerList)}개의 답변이 있습니다.|"></h5>
    <!-- 답변 반복 시작 -->
    
    	<div class="list-group list-group-flush" th:each="answer, loop : ${question.answerList}">
        	<div class="list-group-item bg-light">
           		<h8 class="card-text" style="white-space: pre-line;" th:text="${answer.content}"></h8>
           		<div class="badge bg-primary text-white" th:text="${loop.count}"></div>
            	<div class="d-flex justify-content-end">
                	<div class="badge rounded-pill bg-info text-white">
                    <div th:text="${#temporals.format(answer.createDate, 'yyyy-MM-dd HH:mm')}"></div>
                	</div>
            	</div>
        	</div>
    	</div>
    </div>
    <!-- 답변 반복 끝  -->
    <!-- 답변 작성 -->
    <form th:action="@{|/answer/create/${question.id}|}" method="post" class="my-5">
        <textarea name="content" id="content" rows="3" class="form-control"></textarea>
        <input type="submit" value="답변등록 " class="btn btn-primary my-2">
    </form>
</div>

🔵 결과 화면

0개의 댓글