안녕하세요:) 저번 시간에 이어서 SpringBoot & Handlebars로 화면 만들기 를 진행해보겠습니다.
이전 글을 보지 않으셨다면 따라오기 힘듭니다. 아래 이전 글 링크를 남겨드립니다.
Handlebars
Handlebars는 기존에 많이들 사용하시는 Freemarker, Velocity와 같은 서버 템플릿 엔진입니다.
JSP, Freemarker, Velocity 들은 몇 년 동안 업데이트가 안되고 있어서 SpringBoot에서는 권장하지 않는
템플릿 엔진입니다. 현재 꾸준히 업데이트가 되고 있는 엔진이 Thymeleaf, Handlebars입니다.
이중에 저희는 Handlebars를 사용해보도록 하겠습니다.
라이브러리 링크 남겨드립니다. handlebars-spring-boot-starter
의존성 추가
compile 'pl.allegro.tech.boot:handlebars-spring-boot-starter:0.3.2'
build.gradle에 다음과 같이 의존성을 추가합니다.
의존성만 추가하면 추가 설정 없이 설치가 됩니다!
메인 페이지 생성
Handlebars/Mustache 플러그인을 설치하면 문법 등 편하게 사용 가능하니 설치하여 사용토록 합시다!
<!DOCTYPE HTML>
<html>
<head>
<title>스프링부트 웹서비스</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
</head>
<body>
<h1>SpringBoot로 시작하는 웹 서비스</h1>
</body>
</html>
src/main/resources/templates에 main.hbs 파일을 생성하고 위의 코드를 작성해줍니다.
@Controller
@AllArgsConstructor
public class webController {
@GetMapping("/")
public String main() {
return "main";
}
}
src/main/java/com.zecgwon/webservice/web 에 webController를 추가해주고 코드를 작성합니다.
메인 페이지 테스트 코드 작성
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class WebControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void 메인페이지_로딩() {
//when
String body = this.restTemplate.getForObject("/", String.class);
//then
assertThat(body).contains("SpringBoot로 시작하는 웹 서비스");
}
}
URL 호출 시 제대로 페이지가 호출되는지에 대한 테스트입니다.
src/test/java/com.zecgwon/webservice/web 에 WebControllerTest 클래스를 생성해주고 위의 코드를
작성해주세요!
"SpringBoot로 시작하는 웹 서비스" < 해당 문자열이 포함되어 있는지 테스트해보죠!
테스트가 성공했습니다!!
이번엔 Application을 실제로 실행시켜보고 localhost:8080으로 접속해보면!
실제로 잘 노출이 됩니다!
게시글 등록
이번엔 화면에서 게시글 등록 기능을 구현해보겠습니다.
@AllArgsConstructor
@Service
public class PostsService {
private PostsRepository postsRepository;
@Transactional
public Long save(PostsSaveRequestDto dto){
return postsRepository.save(dto.toEntity()).getId();
}
}
src/main/java/com.zecgwon/webservice 하위에 service 패키지를 생성 후, PostsService 클래스를 생성해주세요.
코드는 위와 같습니다.
import static org.assertj.core.api.Assertions.assertThat;
@RunWith(SpringRunner.class)
@SpringBootTest
public class PostServiceTest {
@Autowired
private PostsService postsService;
@Autowired
private PostsRepository postsRepository;
@After
public void cleanup () {
postsRepository.deleteAll();
}
@Test
public void Dto데이터가_post테이블에_저장된다() {
//given
PostsSaveRequestDto dto = PostsSaveRequestDto.builder()
.author("zecgwon@gmail.com")
.content("테스트")
.title("테스트 타이틀")
.build();
//when
postsService.save(dto);
//then
Posts posts = postsRepository.findAll().get(0);
assertThat(posts.getAuthor()).isEqualTo(dto.getAuthor());
assertThat(posts.getContent()).isEqualTo(dto.getContent());
assertThat(posts.getTitle()).isEqualTo(dto.getTitle());
}
}
이젠 테스트 코드를 작성해보죠!
src/test/java/com.zecgwon/webservice 하위에 service 패키지를 생성 후,
PostServiceTest 클래스를 생성해주세요. 코드는 위와 같습니다.
@Getter
@Setter
@NoArgsConstructor
public class PostsSaveRequestDto {
private String title;
...
@Builder
public PostsSaveRequestDto(String title, String content, String author) {
this.title = title;
this.content = content;
this.author = author;
}
public Posts toEntity() {
...
}
}
테스트 코드가 하는 내용은 간단합니다.
Dto 클래스가 service.save 메서드에 전달되면, DB에 잘 저장되었는지 검증하는 것입니다.
위 테스트 코드를 돌리시려면 PostsSaveRequestDto에 Builder 가 필요합니다.
PostsSaveRequestDto에 Builder도 추가하겠습니다.
코드는 위와 같습니다.
테스트가 잘 통과했네요~
// @RestController 는 @ResponseBody 를 모든 메소드에 적용 해준다.
// hello 메소드의 결과는 HelloWorld 라는 문자열을 JSON 형태로 반환한다.
@RestController
@AllArgsConstructor
public class WebRestController {
//private PostsRepository postsRepository;
private PostsService postsService;
@GetMapping("/hello")
public String hello() {
return "HelloWorld";
}
@PostMapping("/posts")
public void savePosts(@RequestBody PostsSaveRequestDto dto){
//postsRepository.save(dto.toEntity());
postsService.save(dto);
}
}
WebRestController의 save 메서드를 service의 save로 교체하겠습니다.
입력화면 만들기!
백엔드 개발자가 CSS를 전부 구성하기엔 무리가 있기에 저희는 오픈소스 부트스트랩을 활용해보도록 합시다!
아래에 링크 남겨드립니다.
좀 퀄리티 있는 화면을 만들고 싶으시면 구글링 해보시면 많이 나와요 ㅎㅎㅎ
저희는 간단하게 해 볼 거니까 좀 더 퀄리티가 필요하시다면 구글링을 해보세요!
라이브러리를 추가해볼 건데요
라이브러리를 추가하는 방법이 보통 외부 서버를 통해서 다운로드하는 방법도 있고, 프로젝트에 추가하는 방법도 있는데 외부 서버에서 다운로드하는 방식은 문제가 많이 생긴다고 해서 실제 서비스에서는 잘 사용하지 않습니다. 이점 유의해주시고 저희는 프로젝트에 직접 추가하는 방법으로 진행해보겠습니다.
우선 위의 부트스트랩 링크를 클릭하셔서 4.6 버전을 다운로드해주세요.
현재 최신 버전이 5.0인데 이게 아직 베타 버전이기에 안정적인 4.6으로 다운로드하는 게 좋겠습니다!
bootstrap-4.6.0-dist.zip 압축을 풀게 되면
css 디렉터리와 js 디렉터리가 있는데요
- css의 디렉터리의 bootstrap.min.css 파일을 src/main/resources/static/css/lib로 복사합니다.
- js의 디렉터리의 bootstrap.min.js 파일을 src/main/resources/static/js/lib로 복사합니다.
모두 되셨다면 이번엔 jQuery를 추가해볼 건데요
위의 링크로 이동하셔서 Download the compressed, production jQuery 3.5.1을 다운로드해줍니다.
파일 이름을 jquery-3.5.1.min.js -> jquery.min.js로 이름을 변경해줍니다.
- jquery.min.js 파일을 src/main/resources/static/js/lib로 복사합니다.
<!DOCTYPE HTML>
<html>
<head>
<title>스프링부트 웹서비스</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!--부트스트랩 css 추가-->
<link rel="stylesheet" href="/css/lib/bootstrap.min.css">
</head>
<body>
<h1>SpringBoot로 시작하는 웹 서비스</h1>
<!--부트스트랩 js, jquery 추가-->
<script src="/js/lib/jquery.min.js"></script>
<script src="/js/lib/bootstrap.min.js"></script>
</body>
</html>
위의 모든 파일을 복사하셨다면 main.hbs에 위의 코드와 같이 라이브러리를 추가해줍니다.
<!DOCTYPE HTML>
<html>
<head>
<title>스프링부트 웹서비스</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!--부트스트랩 css 추가-->
<link rel="stylesheet" href="/css/lib/bootstrap.min.css">
</head>
<body>
<h1>SpringBoot로 시작하는 웹 서비스</h1>
<div class="col-md-12">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#savePostsModal">글 등록</button>
</div>
<div class="modal fade" id="savePostsModal" tabindex="-1" role="dialog" aria-labelledby="savePostsLabel"
aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="savePostsLabel">게시글 등록</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="title">제목</label>
<input type="text" class="form-control" id="title" placeholder="제목을 입력하세요">
</div>
<div class="form-group">
<label for="author"> 작성자 </label>
<input type="text" class="form-control" id="author" placeholder="작성자를 입력하세요">
</div>
<div class="form-group">
<label for="content"> 내용 </label>
<textarea class="form-control" id="content" placeholder="내용을 입력하세요"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">취소</button>
<button type="button" class="btn btn-primary" id="btn-save">등록</button>
</div>
</div>
</div>
</div>
<!--부트스트랩 js, jquery 추가-->
<script src="/js/lib/jquery.min.js"></script>
<script src="/js/lib/bootstrap.min.js"></script>
</body>
</html>
이번엔 입력화면을 안들 어보죠!! 똑같이 main.hbs에 추가해주시면 됩니다.
Application을 실제로 실행시켜보고 localhost:8080으로 접속하여 글 등록 버튼을 눌러주면
입력화면의 Model이 등장합니다. 아직은 등록버튼의 기능이 없기에 반응이 없습니다.
var main = {
init : function () {
var _this = this;
$('#btn-save').on('click', function () {
_this.save();
});
},
save : function () {
var data = {
title: $('#title').val(),
author: $('#author').val(),
content: $('#content').val()
};
$.ajax({
type: 'POST',
url: '/posts',
dataType: 'json',
contentType:'application/json; charset=utf-8',
data: JSON.stringify(data)
}).done(function() {
alert('글이 등록되었습니다.');
location.reload();
}).fail(function (error) {
alert(error);
});
}
};
main.init();
src/main/resources/static/js/app 디렉터리를 만들어주고 main.js를 만들어줍니다.
그리고 위의 코드를 작성해주시면 됩니다.
<!--부트스트랩 js, jquery 추가-->
<script src="/js/lib/jquery.min.js"></script>
<script src="/js/lib/bootstrap.min.js"></script>
<!--custom js 추가-->
<script src="/js/app/main.js"></script>
이제 main.hbs에 방금 추가한 main.js를 추가해주시면 됩니다.
Application을 실제로 실행시켜보고 localhost:8080으로 접속하여 작성 후 글 등록 버튼을 눌러주고
실제로 데이터가 들어갔는지 localhost:8080/h2-console에 접속하셔서 보면 짠! 아주 잘되네요 ㅎㅎ
다음 시간에는 방금 등록한 게시글을 바로 view에서 볼 수 있도록
목록 리스트를 만들어보도록 하겠습니다.
'SpringBoot' 카테고리의 다른 글
(3-2) - 스프링부트로 웹 서비스 출시하기 : SpringBoot & Handlebars로 화면 만들기 (0) | 2021.03.07 |
---|---|
(2-3) - 스프링부트로 웹 서비스 출시하기 : SpringBoot & JPA로 간단 API 만들기 (0) | 2021.02.09 |
(2-2) - 스프링부트로 웹 서비스 출시하기 : SpringBoot & JPA로 간단 API 만들기 (0) | 2021.02.09 |
SpringBoot H2 DB 연결 에러 (0) | 2021.02.09 |
(2-1) - 스프링부트로 웹 서비스 출시하기 : SpringBoot & JPA로 간단 API 만들기 (0) | 2021.02.07 |
댓글