Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- css
- wil
- 개발자 취업
- 정렬 알고리즘(sort algorithm)
- GIT
- Java
- 면접(java
- 항해99
- github
- CS
- 프로그래머스
- HTML
- Entity
- 이진 탐색(binary search)
- 배열
- 메서드
- 자료구조
- 자바
- Til
- cs 공부)준비
- 회고
- 코딩문제
- 99클럽
- 코딩공부
- Grafana
- aop
- Spring
- ArrayList
- 코딩테스트 준비
- 코딩
Archives
- Today
- Total
hayu's 개발 일지
[TIL]240322 스프링 부트와 AWS로 혼자 구현하는 웹서비스: -4장 머스테치 & CRUD 본문
템플릿 엔진이란?
- 지정된 템플릿 양식과 데이터가 합쳐져 HTML 문서를 출력하는 소프트웨어를 말한다.
(ex. 서버 템플릿 엔진: JSP, Freemarker 클리아언트 템플릿 엔진: 리엑트, 뷰 등)
머스테치란?
- 수많은 언어를 지원하는 가장 심플한 템플릿이다.
- 루비, 자바스크립트, 파이썬, PHP, 자바 등 현존하는 대부분의 언어를 지원한다.
- 자바에서 사용될 때는 서버 템플릿 엔진으로, 자바 스크립트를 사용할 때는 클라이언트 템플릿 엔진으로 모두 사용한다.
머스테치의 장점
- 문법이 다른 템플릿 엔진보다 심플하다.
- 로직 코드를 사용할 수 없어 View 의 역할과 서버의 역할이 명확하게 분리된다.
- 하나의 문법으로 클라이언트/서버 템플릿을 모두 사용 가능하다.
CRUD 코드 리펙토링(lv1 과제 코드)
- Controller 코드
@RestController
@RequestMapping("/api")
public class BoardController {
// JdbcTemplate 사용을 JPA 로 바꿈
// service 생성자 주입(기존 코드에는 없었음)
private final BoardService boardService;
public BoardController(BoardService boardService) {
this.boardService = boardService;
}
// 게시글 작성
@PostMapping("/board")
public ResponseEntity<CreateBoardResponseDto> createBoard(@RequestBody CreateBoardRequestDto boardRequestDto) {
// BoardService boardService = new BoardService(jdbcTemplate); 서비스 생성자를 주입하지 않아서 인스턴스를 만들었음. -> IoD / DI 를 위반.
CreateBoardResponseDto createBoardResponseDto = boardService.createBoard(boardRequestDto);
return ResponseEntity.ok().body(createBoardResponseDto);
}
/*
* ResponseEntity.ok()와 ResponseEntity.ok().body() 차이
* ResponseEntity.ok()
* 단순히 HTTP 상태 코드 200 OK를 갖는 ResponseEntity 객체 생성한다. 별도의 데이터가 포함되지 않는다.
* OK() 안에 값을 넣으면 데이터가 반환된다.
* 보통 추가 헤더나 상태 코드를 지정할 필요가 없는 경우 사용하는 간결하고 간단한 방법
* ResponseEntity.ok().body()
* HTTP 상태 코드 200 OK를 갖는 ResponseEntity 객체 생성하고 응답 본문에 헤당하는 데이터를 지정한다.
* 상태 코드 200과 함께 특정 데이터가 반환된다.
* 추가 헤더나 상태 코드를 설정해야하는 경우에 사용한다. (더 유연함)
* */
// 목록 조회
@GetMapping("/boards")
public ResponseEntity<List<UpdateBoardResponseDto>> getBoardsList() {
List<UpdateBoardResponseDto> boardResponseDto = boardService.getBoardsList();
return ResponseEntity.ok().body(boardResponseDto);
}
// 수정
@PutMapping("/board/{id}")
public ResponseEntity<UpdateBoardResponseDto> updateBoard(@PathVariable Long id, @RequestBody UpdateBoardRequestDto requestDto) {
UpdateBoardResponseDto updateBoardResponseDto = boardService.updateBoard(id, requestDto);
return ResponseEntity.ok().body(updateBoardResponseDto);
}
// 삭제
@DeleteMapping("/board/{id}")
public void deleteBoard(@PathVariable Long id, @RequestParam String password) { // return 값이 있었음. 삭제 기능에서는 필요하지 않음.
// @RequestBody BoardRequestDto requestDto 를 사용. -> @RequestBody 는 POST, PUT 만 사용해야함.
boardService.deleteBoard(id, password);
}
}
- Service 코드
@Service // @Service 추가
public class BoardService {
// BoardRepository 생성자 주입
private final BoardRepository boardRepository;
public BoardService(BoardRepository boardRepository) {
this.boardRepository = boardRepository;
}
// 목록 작성
@Transactional // @Transactional 추가 각각의 기능에 대한 틀내잭션 관리를 뒤해 추가.
public CreateBoardResponseDto createBoard(CreateBoardRequestDto boardRequestDto) {
// DB 저장
// toEntity 를 사용하여 boardRequestDto 를 엔티티로 변환하는 코드 없이 DB에 저장.
Board board = boardRepository.save(boardRequestDto.toEntity());
// Entity -> ResponseDto
return new CreateBoardResponseDto(board);
}
// 목록 조회
@Transactional
public List<UpdateBoardResponseDto> getBoardsList() {
List<Board> boards = boardRepository.findAll();
// 목록을 반환하는 코드
return boards.stream()
.map(UpdateBoardResponseDto::new)
.toList();
}
// 게시글 수정
@Transactional
public UpdateBoardResponseDto updateBoard(Long id, UpdateBoardRequestDto requestDto) {
// 예외 처리 코드 추가
Board board = boardRepository.findById(id)
.orElseThrow(() -> new RuntimeException("찾을 수 없는 게시글입니다."));
// NotFoundException 사용이 안됨. -> 사용하기 위해서는 @ExceptionHandler 를 사용하거나 사용자 정의 예외 클래스를 정의해야 한다.
if (!board.getPassword().equals(requestDto.getPassword())) {
throw new IllegalArgumentException("잘못된 비밀번호 입니다.");
}
board.updateBoard(requestDto.getTitle(), requestDto.getUsername(), requestDto.getPassword(), requestDto.getContents()); // 엔티티에서 매개변수로 자정한 각각의 값을 넣어줌
/*
* 엔티티에 매개 변수로 넣은 값에 따라 코드가 달라진다.
* board.updateBoard(requestDto)
* 장점: 엔티티 내에서 논리를 캡슐화하고 코드 중복을 줄인다. 그리고 단일 매개변수를 허용하여 가독성을 향상시킨다.
* 단점: 유연성이 떨어진다. dto 와 엔티티의 결합은 바람직하지 않다.
* board.updateBoard(requestDto.getTitle(), requestDto.getUsername(), requestDto.getPassword(), requestDto.getContents());
* 장점: 각각 매개변수를 명시적으로 전달하여 어떤 필드인지 알 수 있다. 특정 필드를 선택적으로 업데이트하고 다른 필드는 변경하지 않아서 더 많은 유연성을 허용한다.
* 단점: 엔티티에 새로운 필드가 추가되면 서비스에도 수정이 필요하다.
* */
return new UpdateBoardResponseDto(board);
}
// 게시글 삭제
@Transactional
public void deleteBoard(Long id, String password) { // return 삭제
Board board = boardRepository.findById(id)
.orElseThrow(() -> new RuntimeException("찾을 수 없는 게시글입니다."));
if (!board.getPassword().equals(password)) {
throw new IllegalArgumentException("잘못된 비밀번호 입니다.");
}
boardRepository.delete(board);
}
}
'스터디 > spring' 카테고리의 다른 글
[TIL]240419 Prometheus & Grafana (1) | 2024.04.19 |
---|---|
[TIL]240405 extends, implements 차이 (0) | 2024.04.05 |
[TIL]240329 스프링 부트와 AWS로 혼자 구현하는 웹서비스: -5장 스프링 시큐리티 & 인증, 인가 (3) | 2024.03.29 |
[TIL]240315 스프링 부트와 AWS로 혼자 구현하는 웹서비스: -3장 JPA (0) | 2024.03.15 |
[TIL]240301 스프링 부트와 AWS로 혼자 구현하는 웹서비스: JPA (0) | 2024.03.01 |