[스프링부트 시리즈17] 부트스트랩으로 화면 꾸미기

Featured image

부트스트랩으로 화면 꾸미기


부트스트랩(Bootstrap)은 트위터(Twitter)를 개발하면서 만들어졌으며 현재 지속적으로 관리되고 있는 오픈소스 프로젝트로, 웹 디자이너의 도움 없이도 개발자 혼자서 상당히 괜찮은 수준의 웹 페이지를 만들 수 있게 도와주는 프레임워크이다. 다음과 같이 질문 목록 페이지와 상세 페이지에 부트스트랩을 적용하여 SBB 게시판 서비스를 좀 더 멋지게 만들어 보자.

부트스트랩 설치하기


1) 우선 다음 URL에서 부트스트랩을 내려받자.

https://getbootstrap.com/docs/5.3/getting-started/download/ 다운로드

부트스트랩은 3.x, 4.x, 5.x 등의 버전이 존재하고 메이저 번호(3, 4, 5)에 따라 사용 방법이 다르다. 이 책은 부트스트랩 버전 5 기준으로 실습을 진행한다.

1) 부트스트랩 파일 bootstrap-5.3.3-dist.zip 을 다운로드 받는다.

2) 압축 파일 안에 많은 파일들이 있는데 이 중에서 bootstrap.min.css 파일을 복사하여 스태틱 디렉터리에 저장하자. 경로

구분 파일 위치
압축 파일 내 경로 bootstrap-5.3.3-dist.zip/bootstrap-5.3.3-dist/css/bootstrap.min.css
붙여넣기 경로 workspace/sbb/src/main/resources/static/bootstrap.min.css

압축 파일 안에 자바스크립트 파일도 사용할 예정이므로 bootstrap-5.3.3-dist.zip 파일을 삭제하지 말자. bootstrap.min.css 파일은 STS 에디터에서 열지 말자. STS에서는 한 줄로 만들어진 이 커다란 파일을 읽을 경우 ‘응답 없음’ 오류가 발생할 수 있기 때문이다.

부트스트랩 적용하기


1) 먼저 질문 목록 템플릿에 부트스트랩을 적용해 보자.

[파일명:/templates/question_list.html]

<link rel="stylesheet" type="text/css" th:href="@{/bootstrap.min.css}">
<div class="container my-3">
    <table class="table">
        <thead class="table-dark">
            <tr>
                <th>번호</th>
                <th>제목</th>
                <th>작성일시</th>
            </tr>
        </thead>
        <tbody>
            <tr th:each="question, loop : ${questionList}">
                <td th:text="${loop.count}"></td>
                <td>
                    <a th:href="@{|/question/detail/${question.id}|}" th:text="${question.subject}"></a>
                </td>
                <td th:text="${#temporals.format(question.createDate, 'yyyy-MM-dd HH:mm')}"></td>
            </tr>
        </tbody>
    </table>
</div>

테이블 항목으로 ‘번호’를 추가했다. 번호는 loop.count를 사용하여 표시한다. loop.countquestionList의 항목을 th:each로 반복할 때 현재의 순서를 나타낸다. 그리고 날짜를 보기 좋게 출력하기 위해 타임리프의 #temporals.format 기능을 사용했다. #temporals.format#temporals.format(날짜 객체, 날짜 포맷)와 같이 사용하는데, 날짜 객체를 날짜 포맷에 맞게 변환한다.

우리는 가장 윗줄에 bootstrap.min.css를 사용할 수 있도록 링크를 추가했다. 그리고 위에서 사용한 class="container my-3", class="table", class="table-dark 등은 bootstrap.min.css에 이미 정의되어 있는 클래스들로 간격을 조정하고 테이블에 스타일을 지정하는 용도로 사용했다.

부트스트랩 문서
https://getbootstrap.com/docs/5.3/getting-started/introduction/

2) 다음과 같이 부트스트랩(Bootstrap)을 적용한 질문 목록 페이지를 볼 수 있을 것이다. 적용

3) 이어서 질문 상세 템플릿에도 다음처럼 부트스트랩(Bootstrap)을 적용하자.

[파일명:/templates/question_detail.html]

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

이번에는 수정 사항이 좀 많다. 부트스트랩으로 화면을 구성하다 보면 가끔 HTML 코드를 이렇게 많이 작성해야 한다. 하지만 어렵지 않으니 찬찬히 살펴보자. 질문이나 답변은 각각 하나의 덩어리이므로 부트스트랩의 card 컴포넌트를 사용했다. 부트스트랩의 card 컴포넌트는 어떤 내용을 그룹화하여 보여 줄 때 사용한다.

부트스트랩의 card 컴포넌트를 자세히 알고 싶다면 https://getbootstrap.com/docs/5.3/components/card/를 참고하자.

card 컴포넌트를 비롯하여 질문 상세 템플릿에서 부트스트랩 클래스를 많이 사용했다. 다음 표를 통해 살펴보자.

부트스트랩 클래스 설명
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 HTML 요소를 오른 정렬하는 클래스
bg-light 연회색으로 배경을 지정하는 클래스
text-dark 글자색을 검은색으로 지정하는 클래스
text-start 글자를 왼쪽으로 정렬하는 클래스
btn btn-primary 버튼 컴포넌트를 적용하는 클래스

그리고 질문과 답변 덩어리를 살펴보면 style="white-space: pre-line;"과 같은 스타일을 지정해 주었다. style="white-space: pre-line;"은 CSS 스타일 속성으로, 사용자가 입력한 대로 줄 바꿈이 적용되도록 만들어 준다.

4) 부트스트랩을 적용한 질문 상세 화면을 완성했다. 상세