이전까지 진행했던 실습은 기능만 넣어 API통신을 swagger를 통해 진행했다면 이제는 그 데이터를 유저가 볼수있는 view화면으로 출력시킬 수 있도록 진행할 것이다. 그래서 프로젝트를 새로 만들어 처음부터 진행할 것이다.
템플릿 엔진이란?
- 템플릿의 문법과 데이터(JSON, XML 등)를 이용해서 HTML 문서를 만들어주는 소프트웨어라 이해하면 된다.
템플릿 이란?
- 프로그램 로직을 표연하는 계층과 서비스를 사용하는 유저가 보는 데이터 출력을 위한 프리젠테이션 계층을 분리하기 위한 수단으로 Controller에서 View로 데이터를 보내면 데이터를 View에서 볼 수 있게 도와주는 것으로 Mustache 말고도 JSP, Thymeleaf가 있는데 JSP는 잘 사용 않하는 추세이다.
예제
[데이터]
"item" : "computer",
"price" : "<b>15000</b>"
---------
[템플릿]
{{item}}
{{name}}
{{price}}
{{{price}}}
---------
[결과]
computer
<,b>15000<,/b>
<b>15000</b>
서로 다른 파일
[a 파일]
header
---------
[b 파일]
body
---------
[c 파일]
footer
b파일 안에서 다른 파일 호출
{{>layout/a}}
body
{{>layout/c}}
------------
결과
header
body
footer
더 자세한 내용은 다음 블로그 참조 Mustache 정리
Spring intializer를 통해 기본 설정
github 등록 및 푸시
깃허브에 올리는 기초 설정 파일은 아래와 같다(이 외에는 올리지 말것)
.gitignore
application.yml
build.gradle
gradlew
gradlew.bat
settings.gradle
SpringMustacheBbsApplication.java
SpringMustacheBbsApplicationTests.java
@Controller
public class MustacheController {
@GetMapping("/hi/{id}")
public String mustacheCon2(@PathVariable("id") String id, Model model){
model.addAttribute("username","rok"); // username이라는 변수에 rok값을 넣어 model에 저장
model.addAttribute("id",id); // greetings라는 이름의 view를 리턴(이때 model을 보내줌)
return "greetings";
}
}
실행결과
※ 만약 html만 데이터가 바뀐경우 Ctrl + F9를 통해 빠르게 적용 가능
📣 이때 만약 한글이 깨진다면 application.yml파일에 추가
server: port: 8080 servlet: encoding: force-response: true
공식 홈페이지 : https://getbootstrap.com/
부트 스트랩에 있는 디자인과 반응형 코드를 사용하기 위해서는 부트스트랩과 내 코드를 연동시켜줘야 하므로 다음 코드를 입력해줘야 한다.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<h1>Hello, world!</h1>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
</body>
</html>
적용화면
📌 부트스트랩은 모바일, PC, 태블릿 등 반응형이기 때문에 모양이 제한될 수 있다. 따라서 사용자는 Grid사용법을 익히고 커스터마이징을 해야한다. 하지만 나는 백엔드를 배우기 때문에 자세히는 다루지 않을 것이다.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap demo</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
</head>
<body>
<nav class="navbar navbar-expand-lg bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="#">Navbar</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Link</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown"
aria-expanded="false">
Dropdown
</a>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li>
<hr class="dropdown-divider">
</li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
<li class="nav-item">
<a class="nav-link disabled">Disabled</a>
</li>
</ul>
<form class="d-flex" role="search">
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success" type="submit">Search</button>
</form>
</div>
</div>
</nav>
{{>layout/header}}
<div>
<h1>{{id}} {{username}} Hello!</h1>
<button type="button" class="btn btn-primary">버튼1</button>
<button type="button" class="btn btn-secondary">버튼2</button>
<button type="button" class="btn btn-success">버튼3</button>
<ul class="list-group">
<li class="list-group-item">An item</li>
<li class="list-group-item">A second item</li>
<li class="list-group-item">A third item</li>
</ul>
</div>
{{>layout/footer}}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"
integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3"
crossorigin="anonymous"></script>
</body>
<footer>
<div class="mb-5 container-fluid">
<hr>
<p>@ RokBoard <a href="localhost:8080">Privacy</a> <a href="#">Terms</a></p>
</div>
</footer>
</html>
ArticleController
@Controller
@Slf4j
@RequestMapping("/articles")
public class ArticleController {
@GetMapping("/new")
public String newArticleForm(){
return "articles/new";
}
@PostMapping("/posts")
public String createArticle(ArticleDto form){
log.info(form.toString());
return "";
}
}
ArticleDto
@Getter
@ToString
public class ArticleDto {
private Long id;
private String title;
private String content;
public ArticleDto(Long id, String title, String content) {
this.id = id;
this.title = title;
this.content = content;
}
}
Form 파일
{{>layouts/header}}
<form action="/articles/posts" method="post">
<input type="text" name="title">
<input type="text" name="content">
<button type="submit" class="btn btn-primary">Submit</button>
<a href="/articles">back</a>
</form>
{{>layouts/footer}}
결과
전체적인 흐름