์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- spring
- ๋งคํธ๋ฉ
- ๊ทธ๋ฆฌ๋
- ๋จ์ํ ์คํธ
- webcrawling
- ์ด์งํ์
- ์ ๋ ๋์
- ํ๋ก๊ทธ๋๋จธ์ค
- selenium
- ํด์๋ฒ
- ์ผ์ฑ๊ธฐ์ถ
- ์๊ณ ๋ฆฌ์ฆ
- ๋ฐฑ์ค
- ์นด์นด์ค๊ธฐ์ถ
- ์นด์นด์ค
- python
- Java
- ToyProject
- JPA
- ํฌ๋กค๋ง
- BFS
- matlab
- ํ์ด์ฌ
- Crawling
- ์ด์์ฒด์
- OS
- ํด์
- API
- ์์์ฒ๋ฆฌ
- ์นํฌ๋กค๋ง
DevKim
[์คํ๋ง with AWS] mustache๋ก ํ๋ฉด ๊ตฌ์ฑํ๊ธฐ ๋ณธ๋ฌธ
๐CH.04 ๋จธ์คํ ์น๋ก ํ๋ฉด ๊ตฌ์ฑํ๊ธฐ๐
์ด ์ฑ ์์ ๋จธ์คํ ์น๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ๋ค๊ณ ํ๋ค.
1. ๋ฌธ๋ฒ์ด ๋ค๋ฅธ ํ ํ๋ฆฟ ์์ง๋ณด๋ค ๋จ์ํ๋ฉฐ
2. ๋ก์ง ์ฝ๋๋ฅผ ์ฌ์ฉํ ์ ์์ด, View์ ์ญํ ๊ณผ ์๋ฒ์ ์ญํ ์ด ๋ช ํํ๊ฒ ๋ถ๋ฆฌ๋ ์ ์๊ณ
3. .js / .java๋ฅผ 2๊ฐ์ง๊ฐ ๋ค ์๊ธฐ ๋๋ฌธ์ ํ๋์ ๋ฌธ๋ฒ์ผ๋ก ํด๋ผ์ด์ธํธ/์๋ฒ ํ ํ๋ฆฟ์ ๋ชจ๋ ์ฌ์ฉ๊ฐ๋ฅํ๋ค
๋จธ์คํ ์น๋ ํ๋ฌ๊ทธ์ธ์ ์ฌ์ฉํ ์ ์๊ณ , build.gradle์ ์์กด์ฑ์ ์ถ๊ฐํด์ฃผ๋ฉด ๋ฐ๋ก ์ฌ์ฉํ ์ ์๋ค.
๊ฐ๋จํ ๊ธฐ๋ณธ ํ์ด์ง๋ฅผ ๋ง๋ค๊ณ ๋จธ์คํ ์น์ API๊ฐ ์ ์๋์ด ๋๋์ง ํ ์คํธ๋ฅผ ํด๋ณด์.
- index.mustache
<!DOCTYPE HTML>
<html>
<head>
<title>์คํ๋ง ๋ถํธ ์น์๋น์ค</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
</head>
<body>
<h1> ์คํ๋ง ๋ถํธ๋ก ์์ํ๋ ์น ์๋น์ค</h1>
</body>
</html>
-IndexController ํ ์คํธ
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class IndexControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void ๋ฉ์ธํ์ด์ง_๋ก๋ฉ() throws Exception{
//when
String body = this.restTemplate.getForObject("/", String.class);
//then
assertThat(body).contains("์คํ๋ง ๋ถํธ๋ก ์์ํ๋ ์น ์๋น์ค");
}
}
์ค์ ๋ก URL ํธ์ถ ์ ํ์ด์ง์ ๋ด์ฉ์ด ์ ๋๋ก ํธ์ถ๋๋์ง ,์ฆ ํด๋น ๋ฌธ์์ด์ด ํฌํจ๋๋์ง ํ ์ค๋ฅผ ํด๋ณด์๋ค.
๋ถํธ์คํธ๋ฉ,์ ์ด์ฟผ๋ฆฌ ๋ฑ ํ๋ก ํธ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์ธ๋ถ CDN์ ์ฌ์ฉํ๊ณ ,
๋ ์ด์์ ๋ฐฉ์(๊ณตํต ์์ญ์ ๋ณ๋์ ํ์ผ๋ก ๋ถ๋ฆฌํ์ฌ ํ์ํ ๊ณณ์์ ๊ฐ์ ธ๋ค ์ฐ๋ ๋ฐฉ์)์ผ๋ก ์ถ๊ฐํ๋ค.
ํ์ด์ง์ ๋ก๋ฉ ์๋๋ฅผ ๋์ด๊ธฐ ์ํด css๋ header์, js๋ footer์ ๋๋ค.
๐ ๊ฒ์๊ธ ๋ฑ๋ก
[ ๊ธ ๋ฑ๋ก ๋ฒํผ ]
{{>layout/header}}
<h1>์คํ๋ง๋ถํธ๋ก ์์ํ๋ ์น ์๋น์ค Ver.2</h1>
<div class="col-md-12">
<div class="row">
<div class="col-md-6">
<a href="/posts/save" role="button" class="btn btn-primary">๊ธ ๋ฑ๋ก</a>
</div>
</div>
<br>
<!-- ๋ชฉ๋ก ์ถ๋ ฅ ์์ญ -->
<table class="table table-horizontal table-bordered">
<thead class="thead-strong">
<tr>
<th>๊ฒ์๊ธ๋ฒํธ</th>
<th>์ ๋ชฉ</th>
<th>์์ฑ์</th>
<th>์ต์ข
์์ ์ผ</th>
</tr>
</thead>
<tbody id="tbody">
{{#posts}}
<tr>
<td>{{id}}</td>
<td><a href="/posts/update/{{id}}">{{title}}</a></td>
<td>{{author}}</td>
<td>{{modifiedDate}}</td>
</tr>
{{/posts}}
</tbody>
</table>
</div>
{{>layout/footer}}
{{>}}
: ํ์ฌ ๋จธ์คํ ์น ํ์ผ์ ๊ธฐ์ค์ผ๋ก ๋ค๋ฅธ ํ์ผ์ ๊ฐ์ ธ์จ๋ค.
{{#posts}} ~ {{/posts}}
: posts๋ผ๋ List๋ฅผ ์ํํ๋ค.
{{๋ณ์๋ช }}
:List์์ ๋ฝ์๋ธ ๊ฐ์ฒด์ ํ๋
[ ๊ธ ๋ฑ๋กํ๋ /posts/save ํ์ด์ง๋ก ์ด๋ ]
@GetMapping("/posts/save")
public String postsSave()
{
return "posts-save";
}
[ ๊ธ ๋ฑ๋ก ํ์ด์ง ]
{{>layout/header}}
<h1>๊ฒ์๊ธ ๋ฑ๋ก</h1>
<div class="col-md-12">
<div class="col-md-4">
<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>
<a href="/" role="button" class="btn btn-secondary">์ทจ์</a>
<button type="button" class="btn btn-primary" id="btn-save">๋ฑ๋ก</button>
</div>
</div>
{{>layout/footer}}
๐ ๊ฒ์๊ธ ์กฐํ
[ Repository์ Query ์ถ๊ฐ ]
๊ฒ์๊ธ ๋ชฉ๋ก ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌํ์ฌ ์กฐํ๊ธฐ๋ฅ ์ถ๊ฐ
...
@Query("select p from Posts p order by p.id DESC")
List<Posts> findAllDesc();
[ ๋ด์์ ๋ณด๋ผ DTO ์์ฑ ]
@Getter
@NoArgsConstructor
public class postsListResponseDto {
private Long id;
private String title;
private String content;
private String author;
public postsListResponseDto(Posts posts)
{
this.id=posts.getId();
this.title=posts.getTitle();
this.content= posts.getContent();
this.author= posts.getAuthor();
}
}
[ Service์ ์ ์ฒด์กฐํ ์ถ๊ฐ ]
foreach๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋๋ค์์ ์ ์ฉํ๋ค.
public List<postsListResponseDto> findAllDesc()
{
return postsRepository.findAllDesc().stream()
.map(postsListResponseDto::new)
.collect(Collectors.toList());
}
[ Controller ์์ ]
model์ ๋ด์์ List๋ฅผ index.mustache์ ์ ๋ฌํ๋ค.
@GetMapping("/")
public String index(Model model)
{
List<Posts> postsList = postsRepository.findAllDesc();
model.addAttribute("posts",postsList);
return "index";
}
๐ ๊ฒ์๊ธ ์์
[ ์์ ํ๋ฉด๊ณผ ์ฐ๊ฒฐํ Controller ]
์์ ํ๋ฉด์ ์์ ๋ Post๋ฅผ Dto๋ก ๋ณํ -> model์ ๋ด์ ์ ๋ฌ
@GetMapping("posts/update/{id}")
public String postsUpdate(@PathVariable Long id, Model model)
{
Posts posts = postsRepository.findById(id).orElseThrow(
() -> new IllegalArgumentException("ํด๋นํ๋ ์์ด๋๊ฐ ์กด์ฌํ์ง ์์ต๋๋ค.")
);
PostsResponseDto postsResponseDto = new PostsResponseDto(posts);
model.addAttribute("post",postsResponseDto);
return "posts-update";
}
[ js์ update ์ถ๊ฐ ]
update : function () {
var data = {
title: $('#title').val(),
content: $('#content').val()
};
var id = $('#id').val();
$.ajax({
type: 'PUT',
url: '/api/v1/posts/'+id,
dataType: 'json',
contentType:'application/json; charset=utf-8',
data: JSON.stringify(data)
}).done(function() {
alert('๊ธ์ด ์์ ๋์์ต๋๋ค.');
window.location.href = '/';
}).fail(function (error) {
alert(JSON.stringify(error));
});
}
'Spring Boot' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[์คํ๋ง with AWS] EC2 ์ธ์คํด์ค ์์ฑ, putty ๋ก ์๊ฒฉ์ ์ ํ ํ์ ์ค์ ๋ค (0) | 2021.07.12 |
---|---|
[์คํ๋ง with AWS] ๊ตฌ๊ธ,๋ค์ด๋ฒ ๋ก๊ทธ์ธ ์ฐ๋ (0) | 2021.07.12 |
[์คํ๋ง with AWS] CRU ๊ธฐ๋ฅ - RestTemplate์ผ๋ก API ํ ์คํธ (0) | 2021.07.10 |
[์คํ๋ง with AWS] MockMvc๋ฅผ ์ด์ฉํ API ํ ์คํธ ์ฝ๋ (0) | 2021.07.10 |
[02] ์ฃผ๋ฌธ ๋๋ฉ์ธ ๊ฐ๋ฐ (0) | 2021.07.08 |