최원종의 개발 블로그

블로그 프로젝트 뼈대 코드 본문

Spring boot 입문

블로그 프로젝트 뼈대 코드

chl6698 2026. 4. 29. 17:15

프로젝트 생성


application.yml

spring:
  profiles:
    active:
      - dev

application-dev.yml

server:
  servlet:
    encoding:
      charset: utf-8
      force: true
  port: 80

logging:
  level:
    root: INFO #모든 라이브러리는 INFO 이상만 출력
    com.example: DEBUG # 내 프로젝트는 DEBUG 이상 모두 출력


spring:
  #데이터베이스 연결 설정 (MySQL)
  datasource:
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:test
    username: sa
    password:

  h2:
    console:
      enabled: true

  jpa:
    hibernate:
      # create 애플리케이션 시작시 테이블 새로 생성
      # 기존 데이터는 모드 삭제됨 (개발용)
      ddl-auto: create
    #SQL 쿼리를 콘솔에 출력 (개발용)
    show-sql: true
    properties:
      hibernate:
        # SQL 쿼리를 보기 좋게 포맷팅
        format_sql: true
    # data.sql 파일을 하이버네이트 초기화 이후에 실행
    defer-datasource-initialization: true

  # 초기 데이터 설정
  sql:
    init:
      data-locations:
        - classpath:db/data.sql

 


 

DB 데이터베이스 생성

create database myblog;

 

h2 DB 사용 방법

server:
  servlet:
    encoding:
      charset: utf-8
      force: true
  port: 8080

logging:
  level:
    root: INFO #모든 라이브러리는 INFO 이상만 출력
    com.tenco: DEBUG # 내 프로젝트는 DEBUG 이상 모두 출력

spring:
  #데이터베이스 연결 설정 (MySQL)
  datasource:
#    driver-class-name: com.mysql.cj.jdbc.Driver
#    url: jdbc:mysql://localhost:3306/myblog?serverTimezone=Asia/Seoul
#    username: root
#    password: root
    driver-class-name: org.h2.Driver
    url: jdbc:h2:mem:test
    username: sa
    password:
  h2:
    console:
      enabled: true

#      초기 데이터 설정
#  sql:
#    init:
#      data-locations:
#        - classpath:db/data.sql

  jpa:
    hibernate:
      # create 애플리케이션 시작시 테이블 새로 생성
      # 기존 데이터는 모드 삭제됨 (개발용)
      ddl-auto: create
    #SQL 쿼리를 콘솔에 출력 (개발용)
    show-sql: true
    properties:
      hibernate:
        # SQL 쿼리를 보기 좋게 포맷팅
        format_sql: true
    # data.sql 파일을 하이버네티트 초기화 이후에 실행
    defer-datasource-initialization: true

 

아래 주소로 H2 데이터베이스로 접근 가능

http://localhost:8080/h2-console

 

db/data.sql 파일에 예시 데이터 넣기

insert into board_tb(title, content, username, created_at) values('제목1','내용1','ssar',now());
insert into board_tb(title, content, username, created_at) values('제목2','내용2','ssar',now());
insert into board_tb(title, content, username, created_at) values('제목3','내용3','cos',now());
insert into board_tb(title, content, username, created_at) values('제목4','내용4','love',now());

 

header.mustache

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Blog</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"/>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
</head>

<body class="d-flex flex-column min-vh--100">
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
    <div class="container-fluid">
        <a class="navbar-brand" href="/">Tencoding</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="collapsibleNavbar">
            <ul class="navbar-nav">
                <li class="nav-item">
                    <a class="nav-link" href="/join-form">회원가입</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/login-form">로그인</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/board/save-form">글쓰기</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/user/update-form">회원정보보기</a>
                </li>
                <li class="nav-item">
                    <a class="nav-link" href="/logout">로그아웃</a>
                </li>
            </ul>
        </div>
    </div>
</nav>

 

footer.mustache

<div class="bg-light p-5 text-center">
    <h4>Created by Tencoding</h4>
    <h5>☎ 010-1234-1234</h5>
    <button class="btn btn-outline-primary">고객센터</button>
    <button class="btn btn-outline-primary">오시는길</button>
</div>
</body>

</html>

 

board/detail.mustache

{{> layout/header}}
<div class="container p-5">

    <!-- 수정삭제버튼 섹션 -->
    <!-- d-flex justify-content-end: 버튼들을 오른쪽 정렬 -->
    <div class="d-flex justify-content-end">
        <!--
        수정 버튼: GET 방식으로 수정 폼 페이지로 이동
        {{! board.id}}: 현재 게시글의 ID를 URL에 포함
        RESTful URL 패턴: /board/{id}/update-form
        -->
        <a href="/board/{{board.id}}/update-form" class="btn btn-warning me-1">수정</a>

        <!--
        삭제 버튼: POST 방식으로 삭제 요청
        form을 사용하는 이유: DELETE 동작은 GET이 아닌 POST/DELETE 방식 사용
        RESTful URL 패턴: /board/{id}/delete
        -->
        <form action="/board/{{board.id}}/delete" method="post">
            <button class="btn btn-danger">삭제</button>
        </form>
    </div>

    <!-- 작성자 정보 표시 -->
    <div class="d-flex justify-content-end">
        <!-- {{! board.username}}: Board 객체의 getUsername() 메서드 호출 -->
        <b>작성자</b> : {{board.username}}
    </div>

    <!-- 게시글 내용 섹션 -->
    <div>
        <!-- 게시글 제목 -->
        <h2><b>{{board.title}}</b></h2>
        <hr />
        <!-- 게시글 본문 -->
        <div class="m-4 p-2">
            <!--
            {{! board.content}}: 게시글 내용 출력
            HTML 태그가 포함된 내용은 {{! board.content}} 형태로 사용 (이스케이프 해제)
            보안상 사용자 입력 내용은 기본적으로 HTML 태그를 이스케이프 처리
            -->
            {{board.content}}
        </div>
    </div>

    <!-- 댓글 섹션 (향후 구현 예정) -->
    <div class="card mt-3">
        <!-- 댓글 등록 폼 -->
        <div class="card-body">
            <!--
            댓글 등록 폼: POST 방식으로 댓글 저장
            향후 댓글 기능 구현시 사용할 예정
            현재는 정적 HTML로만 구성
            -->
            <form action="/reply/save" method="post">
                <textarea class="form-control" rows="2" name="comment" placeholder="댓글을 입력하세요"></textarea>
                <div class="d-flex justify-content-end">
                    <button type="submit" class="btn btn-outline-primary mt-1">댓글등록</button>
                </div>
            </form>
        </div>

        <!-- 댓글 목록 헤더 -->
        <div class="card-footer">
            <b>댓글리스트</b>
        </div>

        <!-- 댓글 목록 (현재는 정적 더미 데이터) -->
        <div class="list-group">
            <!-- 댓글 아이템 1 -->
            <div class="list-group-item d-flex justify-content-between align-items-center">
                <div class="d-flex">
                    <!-- 댓글 작성자 배지 -->
                    <div class="px-1 me-1 bg-primary text-white rounded">cos</div>
                    <!-- 댓글 내용 -->
                    <div>댓글 내용입니다</div>
                </div>
                <!-- 댓글 삭제 버튼 -->
                <form action="/reply/1/delete" method="post">
                    <button class="btn">🗑</button>
                </form>
            </div>

            <!-- 댓글 아이템 2 -->
            <div class="list-group-item d-flex justify-content-between align-items-center">
                <div class="d-flex">
                    <div class="px-1 me-1 bg-primary text-white rounded">ssar</div>
                    <div>댓글 내용입니다</div>
                </div>
                <form action="/reply/1/delete" method="post">
                    <button class="btn">🗑</button>
                </form>
            </div>
        </div>
    </div>
</div>

{{> layout/footer}}

 

board/save-from.mustache

{{> layout/header}}

<div class="container p-5">
    <div class="card">
        <div class="card-header"><b>글쓰기 화면입니다</b></div>
        <div class="card-body">
            <!--
            action="/board/save": 폼 제출시 /board/save 경로로 요청
            method="post": HTTP POST 방식으로 데이터 전송
            GET: URL에 데이터 노출, POST: 요청 본문에 데이터 숨김
            -->
            <form action="/board/save" method="post">
                <!--
                name 속성: 서버에서 받을 때 사용하는 변수명
                name="username" → 컨트롤러에서 String username으로 받음
                -->
                <div class="mb-3">
                    <input type="text" class="form-control" placeholder="Enter username" name="username">
                </div>
                <div class="mb-3">
                    <input type="text" class="form-control" placeholder="Enter title" name="title">
                </div>
                <div class="mb-3">
                    <!-- textarea: 여러 줄 텍스트 입력 가능 -->
                    <textarea class="form-control" rows="5" name="content"></textarea>
                </div>
                <!-- 버튼 클릭시 폼이 제출됨 -->
                <button class="btn btn-primary form-control">글쓰기완료</button>
            </form>
        </div>
    </div>
</div>

{{> layout/footer}}

 

실행 화면

더보기

목록화면

 회원수정 화면

 회원가입 화면

로그인 화면

글쓰기 화면

상세 보기 화면