[스파르타코딩클럽] 웹개발의 봄, Spring 3주차
웹개발의 봄, Spring 3주차
💡기대하는 것
웹개발의 봄, Spring 강의를 통해 웹의 기본 구조를 배우고 간단한 서비스를 구현
개발부터 배포까지 과정을 경험해보면서 웹서비스의 전체적인 틀을 잡고 싶다.
📝배운것
- End to End 로 타임라인 서비스 프로젝트 완성
http://spring.spartacodingclub.kr/timeline
- API를 먼저 설계 후 그에 따라 코드를 작성하자
전체 흐름 다시 잡기
- Controller - Service - Repository 3계층
안에서 바깥으로, 즉 Repository 쪽부터 Service, Controller 방향으로 만들어나가자
✏️API 설계하기
CRUD 설계
기능 | METHOD | URL | RETURN |
---|---|---|---|
메모 생성하기 | POST | /api/memos | Memo |
메모 조회하기 | GET | /api/memos | List<Memo> |
메모 변경하기 | PUT | /api/memos/{id} | Long |
메모 삭제하기 | DELETE | /api/memos/{id} | Long |
✏️Repository 만들기
- Memo 클래스(엔터티) 생성
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Memo extends Timestamped{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String username;
@Column(nullable = false)
private String contents;
public void update(MemoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.contents = requestDto.getContents();
}
public Memo(MemoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.contents = requestDto.getContents();
}
}
- Timestapmed 추상클래스 생성 (공통 컬럼)
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Timestamped {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime modifiedAt;
}
- MemoRepository 생성
public interface MemoRepository extends JpaRepository<Memo, Long> {
List<Memo> findAllByOrderByModifiedAtDesc();
}
List<Memo> findAllByOrderByModifiedAtDesc()
: ModifiedAt컬럼을 기준으로 정렬
쿼리 메소드
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
- MemoRequestDto 생성
@Getter
public class MemoRequestDto {
private String username;
private String contents;
}
✏️Service 만들기
- MemoService 생성
@RequiredArgsConstructor
@Service
public class MemoService {
private final MemoRepository memoRepository;
@Transactional
public Long update(Long id, MemoRequestDto requestDto) {
Memo memo = memoRepository.findById(id).orElseThrow(
() -> new NullPointerException("해당 아이디가 존재하지 않습니다.")
);
memo.update(requestDto);
return id;
}
}
✏️Controller 만들기
설계한 API 대로 Controller를 만들어준다.
- MemoController 생성
@RequiredArgsConstructor
@RestController
public class MemoController {
private final MemoRepository memoRepository;
private final MemoService memoService;
@GetMapping("/api/memos")
public List<Memo> getMemos() {
return memoRepository.findAllByOrderByModifiedAtDesc();
}
@PostMapping("/api/memos")
public Memo createMemo(@RequestBody MemoRequestDto requestDto) {
Memo memo = new Memo(requestDto);
return memoRepository.save(memo);
}
@PutMapping("/api/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
return memoService.update(id, requestDto);
}
@DeleteMapping("/api/memos/{id}")
public Long deleteMemo(@PathVariable Long id){
memoRepository.deleteById(id);
return id;
}
}
ARC를 통해서 API 잘 동작하는지 확인
✏️HTML, CSS, JS 만들기
자바스크립트 백틱 연습
let name = '내 이름';
let text = `${name}님의 스프링 5주 완주를 축하합니다!`;
console.log(text);
jQuery 연습
# 인풋값 가져오기
$('#post-url').val();
# 인풋에 값 넣어주기
$('#post-url').val('new text');
# HTML 없애기
$('#cards-box').empty();
# HTML 추가하기
$('#cards-box').append(`<div class="card">
<img class="card-img-top"
src="https://www.eurail.com/content/dam/images/eurail/Italy%20OCP%20Promo%20Block.adaptive.767.1535627244182.jpg"
alt="Card image cap">
<div class="card-body">
<a href="#" class="card-title">여기 기사 제목이 들어가죠</a>
<p class="card-text">기사의 요약 내용이 들어갑니다. 동해물과 백두산이 마르고 닳도록 하느님이 보우하사 우리나라만세 무궁화 삼천리 화려강산...</p>
<p class="card-text comment">여기에 코멘트가 들어갑니다.</p>
</div>
</div>`);
✏️클라이언트 설계하기
필요한 기능 살펴보기
- 접속하자마자 메모 전체 목록 조회하기
- GET API 사용해서 메모 목록 불러오기
- 메모 마다 HTML 만들고 붙이기
- 메모 생성하기
- 사용자가 입력한 메모 내용 확인하기
- POST API 사용해서 메모 신규 생성하기
- 화면 새로고침하여 업데이트 된 메모 목록 확인하기
- 메모 변경하기
- 사용자가 클릭한 메모가 어떤 것인지 확인
- 변경한 메모 내용 확인
- PUT API 사용해서 메모 내용 변경하기
- 화면 새로고침하여 업데이트 된 메모 목록 확인하기
- 메모 삭제하기
- 사용자가 클릭한 메모가 어떤 것인지 확인
- DELETE API 사용해서 메모 삭제하기
- 화면 새로고침하여 업데이트 된 메모 목록 확인하기
✏️메모 생성하기
// 메모를 생성합니다.
function writePost() {
// 1. 작성한 메모를 불러옵니다.
let contents = $('#contents').val();
// 2. 작성한 메모가 올바른지 isValidContents 함수를 통해 확인합니다.
if (isValidContents(contents) == false) {
return;
}
// 3. genRandomName 함수를 통해 익명의 username을 만듭니다.
let username = genRandomName(10);
// 4. 전달할 data JSON으로 만듭니다.
let data = {'username': username, 'contents': contents};
// 5. POST /api/memos 에 data를 전달합니다.
$.ajax({
type: "POST",
url: "/api/memos",
contentType: "application/json",
data: JSON.stringify(data),
success: function (response) {
alert('메시지가 성공적으로 작성되었습니다.');
window.location.reload();
}
});
}
✏️메모 조회하기
// 메모를 불러와서 보여줍니다.
function getMessages() {
// 1. 기존 메모 내용을 지웁니다.
$('#cards-box').empty();
// 2. 메모 목록을 불러와서 HTML로 붙입니다.
$.ajax({
type: 'GET',
url: '/api/memos',
success: function (response) {
for (let i = 0; i < response.length; i++) {
let message = response[i];
let id = message['id'];
let username = message['username'];
let contents = message['contents'];
let modifiedAt = message['modifiedAt'];
addHTML(id, username, contents, modifiedAt);
}
}
})
}
// 메모 하나를 HTML로 만들어서 body 태그 내 원하는 곳에 붙입니다.
function addHTML(id, username, contents, modifiedAt) {
// 1. HTML 태그를 만듭니다.
let tempHtml = `<div class="card">
<!-- date/username 영역 -->
<div class="metadata">
<div class="date">
${modifiedAt}
</div>
<div id="${id}-username" class="username">
${username}
</div>
</div>
<!-- contents 조회/수정 영역-->
<div class="contents">
<div id="${id}-contents" class="text">
${contents}
</div>
<div id="${id}-editarea" class="edit">
<textarea id="${id}-textarea" class="te-edit" name="" id="" cols="30" rows="5"></textarea>
</div>
</div>
<!-- 버튼 영역-->
<div class="footer">
<img id="${id}-edit" class="icon-start-edit" src="images/edit.png" alt="" onclick="editPost('${id}')">
<img id="${id}-delete" class="icon-delete" src="images/delete.png" alt="" onclick="deleteOne('${id}')">
<img id="${id}-submit" class="icon-end-edit" src="images/done.png" alt="" onclick="submitEdit('${id}')">
</div>
</div>`;
// 2. #cards-box 에 HTML을 붙인다.
$('#cards-box').append(tempHtml);
}
✏️메모 변경하기
// 메모를 수정합니다.
function submitEdit(id) {
// 1. 작성 대상 메모의 username과 contents 를 확인합니다.
let username = $(`#${id}-username`).text().trim();
let contents = $(`#${id}-textarea`).val().trim();
// 2. 작성한 메모가 올바른지 isValidContents 함수를 통해 확인합니다.
if (isValidContents(contents) == false) {
return;
}
// 3. 전달할 data JSON으로 만듭니다.
let data = {'username': username, 'contents': contents};
// 4. PUT /api/memos/{id} 에 data를 전달합니다.
$.ajax({
type: "PUT",
url: `/api/memos/${id}`,
contentType: "application/json",
data: JSON.stringify(data),
success: function (response) {
alert('메시지 변경에 성공하였습니다.');
window.location.reload();
}
});
}
✏️메모 삭제하기
function deleteOne(id) {
$.ajax({
type: "DELETE",
url: `/api/memos/${id}`,
success: function (response) {
alert('메시지 삭제에 성공하였습니다.');
window.location.reload();
}
})
}
Author And Source
이 문제에 관하여([스파르타코딩클럽] 웹개발의 봄, Spring 3주차), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@qudalsrnt3x/Spring-스파르타-코딩-클럽-3주차저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)