๐ก PURPOSE
๊ฐ์ธ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ ค๊ณ ํ์ผ๋ ์ค์ค๋ก ์๊ฐํ๊ธฐ์ ์์ง api ์์ฑ์ ๋ํด ๋ง์ด ๋ถ์กฑํ ๊ฒ ๊ฐ์ ์ด๋์๋ถํฐ ์์ํด์ผํ ์ง ๋ชจ๋ฅด๊ฒ ์ด์ ์ผ๋จ jpa์ ๋ํ ๊ธฐ์ด์ ์ธ ์ง์์ ์๊ธฐ ์ํด ๊ณต๋ถํ ๊ฒ์ ๋ณต์ตํ ๊ฒธ ํฌ์คํ ํด๋ณด๊ฒ ๋ค.
๐ก STUDY LIST
# Subject 1 : ์ปจํธ๋กค๋ฌ๋ฅผ ํตํ ๊ฒ์ํ ๊ธฐ๋ฅ ๊ตฌํํ๊ธฐ
1. ์ฃผ์์์ฒญ์ ๋ํ ์ดํด
2. ๊ฒ์ํ ๊ธฐ๋ณธ ๋ชฉ๋ก (6~10)
3. ๊ฒ์๊ธ ์์ฑ (11~15)
4.๊ฒ์๊ธ ์์ (16~20)
5.๊ฒ์๊ธ ์ญ์ (21~25)
6.๊ฒ์ํ ์ถ๊ฐ๊ธฐ๋ฅ (26~30)
๐ก CONTENTS
(6) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก์ ๋ํ ์์ฒญ ์ฒ๋ฆฌ API
- ํ์ : REST API
- HTTP METHOD : GET
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ๋ฌธ์์ด "๊ณต์ง์ฌํญ์ ๋๋ค."
/*
controller/NoticeController.java ์์ฑ
*/
@RestController
public class NoticeController {
@GetMapping("/api/notice")
public String noticeString() {
return "๊ณต์ง์ฌํญ์
๋๋ค.";
}
}
(7) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก์ ๋ํ ์์ฒญ ์ฒ๋ฆฌ API
- ํ์ : REST API
- HTTP METHOD : GET
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ด์ฉ์ ์ถ์ํํ ๋ชจ๋ธ (๊ฒ์๊ธID, ์ ๋ชฉ, ๋ด์ฉ, ๋ฑ๋ก์ผ)
- ๊ฒ์๊ธID = 1, ์ ๋ชฉ = ๊ณต์ง์ฌํญ์ ๋๋ค., ๋ด์ฉ = ๊ณต์ง์ฌํญ ๋ด์ฉ์ ๋๋ค., ๋ฑ๋ก์ผ = 2021-2-8
/*
dto/NoticeDto.java ์์ฑ
*/
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class NoticeDto {
//๊ฒ์๊ธID, ์ ๋ชฉ, ๋ด์ฉ, ๋ฑ๋ก์ผ
private long id;
private String title;
private String contents;
private LocalDateTime regDate;
}
@RestController
public class NoticeController {
@GetMapping("/api/notice")
public NoticeDto notice() {
NoticeDto noticeDto = new NoticeDto();
noticeDto.setId(1);
noticeDto.setTitle("๊ณต์ง์ฌํญ์
๋๋ค.");
noticeDto.setContents("๊ณต์ง์ฌํญ๋ด์ฉ์
๋๋ค.");
noticeDto.setRegDate(LocalDateTime.of(2021,2,8,0,0));
return noticeDto;
}
}
(8) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก์ ๋ํ ์์ฒญ ์ฒ๋ฆฌ API
- ํ์ : REST API
- HTTP METHOD : GET
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ด์ฉ์ ์ถ์ํํ ๋ชจ๋ธ (๊ฒ์๊ธID, ์ ๋ชฉ, ๋ด์ฉ, ๋ฑ๋ก์ผ)์ด๋ฉฐ ๋ณต์ํํ์ ๋ฐ์ดํฐ
- ๊ฒ์๊ธID = 1, ์ ๋ชฉ = ๊ณต์ง์ฌํญ์ ๋๋ค., ๋ด์ฉ = ๊ณต์ง์ฌํญ ๋ด์ฉ์ ๋๋ค., ๋ฑ๋ก์ผ = 2021-1-30
- ๊ฒ์๊ธID = 2, ์ ๋ชฉ = ๋๋ฒ์งธ ๊ณต์ง์ฌํญ์ ๋๋ค., ๋ด์ฉ = ๋๋ฒ์งธ ๊ณต์ง์ฌํญ ๋ด์ฉ์ ๋๋ค., ๋ฑ๋ก์ผ = 2021-1-31
@RestController
public class NoticeController {
@GetMapping("/api/notice")
public List<NoticeDto> notice() {
List<NoticeDto> noticeDtoList = new ArrayList<>();
NoticeDto noticeDto1 = new NoticeDto();
noticeDto1.setId(1);
noticeDto1.setTitle("๊ณต์ง์ฌํญ์
๋๋ค.");
noticeDto1.setContents("๊ณต์ง์ฌํญ๋ด์ฉ์
๋๋ค.");
noticeDto1.setRegDate(LocalDateTime.of(2021,1,30,0,0));
noticeDtoList.add(noticeDto1);
NoticeDto noticeDto2 = new NoticeDto();
noticeDto2.setId(2);
noticeDto2.setTitle("๋๋ฒ์งธ ๊ณต์ง์ฌํญ์
๋๋ค.");
noticeDto2.setContents("๋๋ฒ์งธ ๊ณต์ง์ฌํญ๋ด์ฉ์
๋๋ค.");
noticeDto2.setRegDate(LocalDateTime.of(2021,1,31,0,0));
noticeDtoList.add(noticeDto2);
return noticeDtoList;
}
}
(9) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก์ ๋ํ ์์ฒญ ์ฒ๋ฆฌ API
- ํ์ : REST API
- HTTP METHOD : GET
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ด์ฉ์ ์ถ์ํํ ๋ชจ๋ธ (๊ฒ์๊ธID, ์ ๋ชฉ, ๋ด์ฉ, ๋ฑ๋ก์ผ)์ด๋ฉฐ ๋ณต์ํํ์ ๋ฐ์ดํฐ
- ์์ฒญํ ๋ด์ฉ์ด ์๋ ๋น ๋ชฉ๋ก์ ๋ฆฌํด
@RestController
public class NoticeController {
@GetMapping("/api/notice")
public List<NoticeDto> notice() {
List<NoticeDto> noticeDtoList = new ArrayList<>();
return noticeDtoList;
}
}
(10) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก ์ค ์ ์ฒด ๊ฐ์ ์ ๋ณด์ ๋ํ ์์ฒญ์ ์ฒ๋ฆฌํ๋ API
- ํ์ : REST API
- HTTP METHOD : GET
- ์์ฒญ ์ฃผ์ : "/api/notice/count"
- return : ๊ฒ์ํ์ ๊ฒ์๊ธ ๊ฐ์(์ ์)๋ฅผ ๋ฆฌํด
- ์ปจํธ๋กค๋ฌ์์ ์ ์ํ์ ๋ฆฌํดํ์๋๋ผ๋ ํด๋ผ์ด์ธํธ ์ชฝ์ ๋ด๋ ค๊ฐ๋ ๋ถ๋ถ์ ๋ฌธ์์ด์
@RestController
public class NoticeController {
@GetMapping("/api/notice/count")
public int noticeCount() {
return 10;
}
}
(11) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก ์ค ์ ์ฒด ๊ฐ์ ์ ๋ณด์ ๋ํ ์์ฒญ์ ์ฒ๋ฆฌํ๋ API
- ํ์ : REST API
- HTTP METHOD : POST
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ์ ๋ฌ๋๋ ํ๋ผ๋ฏธํฐ๋ x-www-form-urlencoded ํ์์ ์ ๋ชฉ, ๋ด์ฉ์ ์
๋ ฅ ๋ฐ์
- ํ๋ผ๋ฏธํฐ๋ ์ถ์ํํ์ง ์๊ณ ๊ธฐ๋ณธ๋ฐ์ดํฐ ํ์ ํํ๋ก ์ ๋ฌ๋ฐ์
- ๋ฆฌํด๊ฐ์ ์ ๋ ฅ๋ ํํ์ ๊ฒ์๊ธID(1)์ ์ถ๊ฐํ์ฌ ๋ชจ๋ธ ํํ๋ก ๋ฆฌํด
@RestController
public class NoticeController {
@PostMapping("/api/notice")
public NoticeDto addNotice(String title, String contents) {
NoticeDto noticeDto = NoticeDto.builder()
.id(1)
.title(title)
.contents(contents)
.regDate(LocalDateTime.now())
.build();
return noticeDto;
}
}
(12) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก ์ค ์ ์ฒด ๊ฐ์ ์ ๋ณด์ ๋ํ ์์ฒญ์ ์ฒ๋ฆฌํ๋ API
- ํ์ : REST API
- HTTP METHOD : POST
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ์ ๋ฌ๋๋ ํ๋ผ๋ฏธํฐ๋ x-www-form-urlencoded ํ์์ ์ ๋ชฉ, ๋ด์ฉ์ ์
๋ ฅ ๋ฐ์
- ํ๋ผ๋ฏธํฐ๋ ๊ณต์ง์ฌํญ ๋ชจ๋ธ๋ก ์ถ์ํํ์ฌ ์ ๋ฌ๋ฐ์
- ๋ฆฌํด๊ฐ์ ์ ๋ ฅ๋ ํํ์ ๊ฒ์๊ธID(2) ๊ณผ ๋ฑ๋ก์ผ์(ํ์ฌ์๊ฐ) ์ถ๊ฐํ์ฌ ๋ชจ๋ธ ํํ๋ก ๋ฆฌํด
@RestController
public class NoticeController {
@PostMapping("/api/notice")
public NoticeDto addNotice(NoticeDto noticeDto) {
noticeDto.setId(2);
noticeDto.setRegDate(LocalDateTime.now());
return noticeDto;
}
}
(13) ๊ณต์ง์ฌํญ ๊ฒ์ํ์ ๋ชฉ๋ก ์ค ์ ์ฒด ๊ฐ์ ์ ๋ณด์ ๋ํ ์์ฒญ์ ์ฒ๋ฆฌํ๋ API
- ํ์ : REST API
- HTTP METHOD : POST
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ์ ๋ฌ๋๋ ํ๋ผ๋ฏธํฐ๋ json ํ์์ ์ ๋ชฉ, ๋ด์ฉ์ ์
๋ ฅ ๋ฐ์
- ํ๋ผ๋ฏธํฐ๋ ๊ณต์ง์ฌํญ ๋ชจ๋ธ๋ก ์ถ์ํํ์ฌ ์ ๋ฌ๋ฐ์
- ๋ฆฌํด๊ฐ์ ์ ๋ ฅ๋ ํํ์ ๊ฒ์๊ธID(3) ๊ณผ ๋ฑ๋ก์ผ์(ํ์ฌ์๊ฐ) ์ถ๊ฐํ์ฌ ๋ชจ๋ธ ํํ๋ก ๋ฆฌํด
@RestController
public class NoticeController {
@PostMapping("/api/notice")
public NoticeDto addNotice(@RequestBody NoticeDto noticeDto) {
noticeDto.setId(3);
noticeDto.setRegDate(LocalDateTime.now());
return noticeDto;
}
}
(14) ๊ณต์ง์ฌํญ์ ๊ธ์ ๋ฑ๋กํ๊ธฐ ์ํ ๊ธ์์ฑ์ ๋ํ API
- ํ์ : REST API
- HTTP METHOD : POST
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ์ ๋ฌ๋๋ ํ๋ผ๋ฏธํฐ๋ json ํ์์ ์ ๋ชฉ, ๋ด์ฉ์ ์
๋ ฅ ๋ฐ์
- ์ ๋ฌ๋ ๊ฐ์ ์ ์ฅํ๊ธฐ ์ํ JPA Repository์ Entity๋ฅผ ํตํด์ Database์ ์ ์ฅ
- ๋ฆฌํด๊ฐ์ ์ ์ฅ๋ id๊ฐ์ด ํฌํจ๋ Entity ๋ฆฌํด
/*
entity/Notice.java ์์ฑ
*/
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
public class Notice {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column
private String title;
@Column
private String contents;
@Column
private LocalDateTime regDate;
}
/*
repository/NoticeRepository.java ์์ฑ
*/
@Repository
public interface NoticeRepository extends JpaRepository<Notice, Long> {
}
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@PostMapping("/api/notice")
public Notice addNotice(@RequestBody NoticeDto noticeDto) {
Notice notice = Notice.builder()
.title(noticeDto.getTitle())
.contents(noticeDto.getContents())
.regDate(LocalDateTime.now())
.build();
noticeRepository.save(notice);
return notice;
}
}
(15) ๊ณต์ง์ฌํญ์ ๊ธ์ ๋ฑ๋กํ๊ธฐ ์ํ ๊ธ์์ฑ์ ๋ํ API
- ํ์ : REST API
- HTTP METHOD : POST
- ์์ฒญ ์ฃผ์ : "/api/notice"
- return : ์ ๋ฌ๋๋ ํ๋ผ๋ฏธํฐ๋ json ํ์์ ์ ๋ชฉ, ๋ด์ฉ์ ์
๋ ฅ ๋ฐ์
- +) ๊ณต์ง์ฌํญ ์กฐํ์์ ์กฐํ์๋ ์ด๊ธฐ๊ฐ์ 0์ผ๋ก ์ค์
- ์ ๋ฌ๋ ๊ฐ์ ์ ์ฅํ๊ธฐ ์ํ JPA Repository์ Entity๋ฅผ ํตํด์ Database์ ์ ์ฅ
- ๋ฆฌํด๊ฐ์ ์ ์ฅ๋ id๊ฐ์ด ํฌํจ๋ Entity ๋ฆฌํด
/*
entity/Notice.java ์ ์นผ๋ผ ์ถ๊ฐ
*/
@Column
private int hits;
@Column
private int likes;
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@PostMapping("/api/notice")
public Notice addNotice(@RequestBody NoticeDto noticeDto) {
Notice notice = Notice.builder()
.title(noticeDto.getTitle())
.contents(noticeDto.getContents())
.regDate(LocalDateTime.now())
.hits(0)
.likes(0)
.build();
Notice resultNotice = noticeRepository.save(notice);
return resultNotice;
}
}
(16) ๊ณต์ง์ฌํญ์ ๊ธ์ ์์ ํ๊ธฐ ์ํ ์์ธ์ ๋ณด ์์ฒญ์ ๋ํ API
- ํ์ : REST API
- HTTP METHOD : GET
- ์์ฒญ ์ฃผ์ : "/api/notice/1" ("1"์ ๊ณต์ง์ฌํญ์ ๊ธID๋ก ๋์ ์ผ๋ก ๋ณํจ)
- DB์๋ ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ์์
- return : ์กฐํ๋ ๊ฒฐ๊ณผ๊ฐ ์๋ ๊ฒฝ์ฐ Entity ๋ฆฌํด, ์๋ ๊ฒฝ์ฐ null return
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@GetMapping("/api/notice/{id}")
public Notice notice(@PathVariable Long id) {
Optional<Notice> notice = noticeRepository.findById(id);
if(notice.isPresent()) {
return notice.get();
}
return null;
}
}
(17) ๊ณต์ง์ฌํญ์ ๊ธ์ ์์ ํ๊ธฐ ์ํ ๊ธ์์ ์ ๋ํ API
- ํ์ : REST API
- HTTP METHOD : PUT
- ์์ฒญ ์ฃผ์ : "/api/notice/1" ("1"์ ๊ณต์ง์ฌํญ์ ๊ธID๋ก ๋์ ์ผ๋ก ๋ณํจ)
- ํ๋ผ๋ฏธํฐ : json ํ์์ ๊ณต์ง์ฌํญ ๊ธID, ์ ๋ชฉ, ๋ด์ฉ์ ์ ๋ ฅ ๋ฐ์
- ๊ณต์ง์ฌํญ ์์ ์ผ์ ํ์ฌ์๊ฐ์ ์ ์ฅ, ๊ณต์ง์ฌํญ ์กฐํ์์ ์ข์์ ์๋ ๋ณ๊ฒฝํ์ง ์์
- ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ๋ Data๋งคํ์ ๋ํ Entity๋ก ํ์์๋ ํญ๋ชฉ๊น์ง ๋ฐ์ง ๋ง๊ณ ํ์ํ ๋ฐ์ดํฐ๋ง ์ ๋ ฅ๋ฐ๊ฒ ์์ฑ
- DB์๋ ๋ฐ์ดํฐ๊ฐ ์ด๋ฏธ ์์
- ์ ๋ฌ๋ ๊ฐ์ ์์ ํ๊ธฐ ์ํ JPA Repository์ Entity๋ฅผ ํตํด์ Database์ ์์
/*
entity/Notice.java ์ ์นผ๋ผ ์ถ๊ฐ
*/
@Column
private LocalDateTime updateDate;
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@PutMapping ("/api/notice/{id}")
public void updateNotice(@PathVariable Long id, @RequestBody NoticeDto noticeDto) {
Optional<Notice> notice = noticeRepository.findById(id);
if(notice.isPresent()) {
notice.get().setTitle(noticeDto.getTitle());
notice.get().setContents(noticeDto.getContents());
notice.get().setUpdateDate(LocalDateTime.now());
noticeRepository.save(notice.get());
}
}
}
(18,19) ๊ณต์ง์ฌํญ์ ๊ธ์ ์์ ํ๊ธฐ ์ํ ๊ธ์์ ์ ๋ํ API
- ํ์ : REST API
- HTTP METHOD : PUT
- ์์ฒญ ์ฃผ์ : "/api/notice/1" ("1"์ ๊ณต์ง์ฌํญ์ ๊ธID๋ก ๋์ ์ผ๋ก ๋ณํจ)
- ํ๋ผ๋ฏธํฐ : json ํ์์ ๊ณต์ง์ฌํญ ๊ธID, ์ ๋ชฉ, ๋ด์ฉ์ ์ ๋ ฅ ๋ฐ์
- ๊ณต์ง์ฌํญ ์์ ์ผ์ ํ์ฌ์๊ฐ์ ์ ์ฅ, ๊ณต์ง์ฌํญ ์กฐํ์์ ์ข์์ ์๋ ๋ณ๊ฒฝํ์ง ์์
- ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๊ฒฝ์ฐ๋ Data๋งคํ์ ๋ํ Entity๋ก ํ์์๋ ํญ๋ชฉ๊น์ง ๋ฐ์ง ๋ง๊ณ ํ์ํ ๋ฐ์ดํฐ๋ง ์ ๋ ฅ๋ฐ๊ฒ ์์ฑ
- ๊ณต์ง์ฌํญ์ ๊ธ์ด ์กด์ฌํ์ง ์์ ๊ฒฝ์ฐ ์์ธ์ฌํญ์ ๋ฐ์
- ์์ธ์ฒ๋ฆฌ๋ ExceptionHandler๋ฅผ ํตํด์ ๊ตฌํํ๊ณ , ๋ฐ์ํ๋ ์์ธ์ ๋ํด์๋ 400, ์์ธ ๋ฉ์ธ์ง๋ฅผ ๋ฆฌํด
/*
exception/NoticeNotFoundException.java ์์ฑ
*/
public class NoticeNotFoundException extends RuntimeException{
public NoticeNotFoundException(String message) {
super(message);
}
}
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@ExceptionHandler(NoticeNotFoundException.class)
public ResponseEntity<String> handlerNoticeNotFoundException(NoticeNotFoundException exception) {
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
@PutMapping ("/api/notice/{id}")
public void updateNotice(@PathVariable Long id, @RequestBody NoticeDto noticeDto) {
/*
Optional<Notice> notice = noticeRepository.findById(id);
if(!notice.isPresent()) {
//์์ธ ๋ฐ์
throw new NoticeNotFoundException("๊ณต์ง์ฌํญ์ ๊ธ์ด ์กด์ฌํ์ง ์์ต๋๋ค.");
}
*/
Notice notice = noticeRepository.findById(id)
.orElseThrow(() -> new NoticeNotFoundException("๊ณต์ง์ฌํญ์ ๊ธ์ด ์กด์ฌํ์ง ์์ต๋๋ค."));
//๊ณต์ง์ฌํญ ๊ธ์ด ์์ ๋
notice.setTitle(noticeDto.getTitle());
notice.setContents(noticeDto.getContents());
notice.setUpdateDate(LocalDateTime.now());
noticeRepository.save(notice);
}
}
(20) ๊ณต์ง์ฌํญ์ ๊ธ์ ์กฐํ์๋ฅผ ์ฆ๊ฐ์ํค๋ API
- ํ์ : REST API
- HTTP METHOD : PATCH
- ์์ฒญ ์ฃผ์ : "/api/notice/1/hits" ("1"์ ๊ณต์ง์ฌํญ์ ๊ธID๋ก ๋์ ์ผ๋ก ๋ณํจ)
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@ExceptionHandler(NoticeNotFoundException.class)
public ResponseEntity<String> handlerNoticeNotFoundException(NoticeNotFoundException exception) {
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
@PatchMapping("/api/notice/{id}/hits")
public void noticeHits(@PathVariable Long id) {
Notice notice = noticeRepository.findById(id)
.orElseThrow(() -> new NoticeNotFoundException("๊ณต์ง์ฌํญ์ ๊ธ์ด ์กด์ฌํ์ง ์์ต๋๋ค."));
notice.setHits(notice.getHits() + 1);
noticeRepository.save(notice);
}
(21,22) ๊ณต์ง์ฌํญ์ ๊ธ์ ์ญ์ ํ๊ธฐ ์ํ API
- ํ์ : REST API
- HTTP METHOD : DELETE
- ์์ฒญ ์ฃผ์ : "/api/notice/1" ("1"์ ๊ณต์ง์ฌํญ์ ๊ธID๋ก ๋์ ์ผ๋ก ๋ณํจ)
- ์ ๋ฌ๋ฐ์ ๊ณต์ง์ฌํญ์ ๋ด์ฉ์ด ์กฐํ๊ฐ ๋์ง ์๋ ๊ฒฝ์ฐ NotFoundException ๋ฐ์
- ์ด์ ๋ํ ๊ฒฐ๊ณผ๋ 400์๋ฌ์ "๋ด์ฉ์ด ์กด์ฌํ์ง ์์ต๋๋ค." ๋ผ๋ ๋ฉ์์ง ๋ฆฌํด
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@ExceptionHandler(NoticeNotFoundException.class)
public ResponseEntity<String> handlerNoticeNotFoundException(NoticeNotFoundException exception) {
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
@DeleteMapping("/api/notice/{id}")
public void deleteNotice(@PathVariable Long id) {
Notice notice = noticeRepository.findById(id)
.orElseThrow(() -> new NoticeNotFoundException("๊ณต์ง์ฌํญ์ ๊ธ์ด ์กด์ฌํ์ง ์์ต๋๋ค."));
noticeRepository.delete(notice);
}
(23) ๊ณต์ง์ฌํญ์ ๊ธ์ ์ญ์ ํ๊ธฐ ์ํ API
- ํ์ : REST API
- HTTP METHOD : DELETE
- ์์ฒญ ์ฃผ์ : "/api/notice/1" ("1"์ ๊ณต์ง์ฌํญ์ ๊ธID๋ก ๋์ ์ผ๋ก ๋ณํจ)
- ๊ฒ์ํ์ ๊ธ์ ๋ฌผ๋ฆฌ์ ์ผ๋ก ์ญ์ ํ์ง ์๊ณ ์ญ์ ํ๋๊ทธ๊ฐ์ ์ด์ฉํ์ฌ ์ญ์ ์งํ
- ์ญ์ ์ผ์๋ ํ์ฌ ์๊ฐ์ผ๋ก ์ค์
- ๊ณต์ง์ฌํญ์ ๊ธ์ด ์ด๋ฏธ ์ญ์ ๋ ๊ฒฝ์ฐ๋ 200์ฝ๋์ "์ด๋ฏธ ์ญ์ ๋ ๊ธ์ ๋๋ค."๋ผ๋ ๋ฉ์์ง ๋ฆฌํด
/*
entity/Notice.java ์ ์นผ๋ผ ์ถ๊ฐ
*/
@Column
private boolean deleted; //๋ฐ์ดํฐ ๊ธฐ๋ณธ๊ฐ 0์ผ๋ก ๋ณ๊ฒฝ
@Column
private LocalDateTime deletedDate;
/*
exception/AlreadyDeletedException.java ์์ฑ
*/
public class AlreadyDeletedException extends RuntimeException{
public AlreadyDeletedException(String message) {
super(message);
}
}
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@ExceptionHandler(AlreadyDeletedException.class)
public ResponseEntity<String> handlerAlreadyDeletedException(AlreadyDeletedException exception) {
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(NoticeNotFoundException.class)
public ResponseEntity<String> handlerNoticeNotFoundException(NoticeNotFoundException exception) {
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
@DeleteMapping("/api/notice/{id}")
public void deleteNotice(@PathVariable Long id) {
Notice notice = noticeRepository.findById(id)
.orElseThrow(() -> new NoticeNotFoundException("๊ณต์ง์ฌํญ์ ๊ธ์ด ์กด์ฌํ์ง ์์ต๋๋ค."));
if (notice.isDeleted()) {
throw new AlreadyDeletedException("์ด๋ฏธ ์ญ์ ๋ ๊ธ์
๋๋ค.");
}
notice.setDeleted(true);
notice.setDeletedDate(LocalDateTime.now());
noticeRepository.save(notice);
}
}
(24) ๊ณต์ง์ฌํญ์ ๊ธ์ ์ญ์ ํ๊ธฐ ์ํ API
- ํ์ : REST API
- HTTP METHOD : DELETE
- ์์ฒญ ์ฃผ์ : "/api/notice
- ์ฌ๋ฌ ๊ฐ์ ๊ธ์ ๋์์ ์ญ์ ํ๊ธฐ ์ํด์ noticeId ๋ชฉ๋ก์ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์์ ํด๋น ๊ณต์ง์ฌํญ์ ๊ธ์ ์ญ์
/*
Dto/NoticeDeleteDto.java ์์ฑ
*/
@Data
public class NoticeDeleteDto {
private List<Long> idList;
}
/*
repository/NoticeRepository.java ๋ณ๊ฒฝ
*/
@Repository
public interface NoticeRepository extends JpaRepository<Notice, Long> {
Optional<List<Notice>> findByIdIn(List<Long> idList);
}
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@ExceptionHandler(NoticeNotFoundException.class)
public ResponseEntity<String> handlerNoticeNotFoundException(NoticeNotFoundException exception) {
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
@DeleteMapping("/api/notice")
public void deleteNoticeList(@RequestBody NoticeDeleteDto noticeDeleteDto) {
List<Notice> noticeList = noticeRepository.findByIdIn(noticeDeleteDto.getIdList())
.orElseThrow(() -> new NoticeNotFoundException("๊ณต์ง์ฌํญ์ ๊ธ์ด ์กด์ฌํ์ง ์์ต๋๋ค."));
noticeList.forEach(e -> {
e.setDeleted(true);
e.setDeletedDate(LocalDateTime.now());
});
noticeRepository.saveAll(noticeList);
}
(25) ๊ณต์ง์ฌํญ์ ๊ธ์ ์ญ์ ํ๊ธฐ ์ํ API
- ํ์ : REST API
- HTTP METHOD : DELETE
- ์์ฒญ ์ฃผ์ : "/api/notice/all"
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@DeleteMapping("/api/notice/all")
public void deleteAll( ) {
noticeRepository.deleteAll();
}
(26) ๊ธ์ ์์ฑํ ๋ ์ ๋ชฉ๊ณผ ๋ด์ฉ์ ๋ฐ์์ ์ ์ฅํ๋ API
- ํ์ : REST API
- HTTP METHOD : POST
- DTO๋ฅผ ํตํ ํ๋ผ๋ฏธํฐ๋ฅผ ํํ๋ก ๋ฐ์
- ๋ฑ๋ก์ผ์ ํ์ฌ์ผ์, ์กฐํ์/์ข์์๋ 0์ผ๋ก ์ค์
- ์ ๋ฌ๋ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ํตํด์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํจ
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@PostMapping("/api/notice")
public Notice addNotice(@RequestBody NoticeDto noticeDto) {
Notice notice = Notice.builder()
.title(noticeDto.getTitle())
.contents(noticeDto.getContents())
.regDate(LocalDateTime.now())
.hits(0)
.likes(0)
.build();
Notice resultNotice = noticeRepository.save(notice);
return resultNotice;
}
}
(27) ๊ธ์ ์์ฑํ ๋ ์ ๋ชฉ๊ณผ ๋ด์ฉ์ ๋ฐ์์ ์ ์ฅํ๋ API
- ํ์ : REST API
- HTTP METHOD : POST
- ์ ๋ ฅ๊ฐ์ ์ ๋ ฅDTO๋ฅผ ํตํด์ ์ ๋ ฅ๋ฐ์
- ์ ๋ชฉ๊ณผ ๋ด์ฉ์ ํ์ ์ ๋ ฅ ์กฐ๊ฑด(์ ๋ ฅ๋์ง ์์ ๊ฒฝ์ฐ 400๋ฆฌํด
- ์์ธ๋ฐ์์ ๊ฐ๊ฐ์ ์๋ฌ๋ฅผ ์ทจํฉํ์ฌ ์ฝ๋ ์ ํํ๋ก ๋ฆฌํด
/*
build.gradle์ ์ถ๊ฐ
*/
implementation("org.springframework.boot:spring-boot-starter-validation")
/*
dto/NoticeDto.java ์์
*/
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class NoticeDto {
//๊ฒ์๊ธID, ์ ๋ชฉ, ๋ด์ฉ, ๋ฑ๋ก์ผ
private long id;
@NotBlank(message = "์ ๋ชฉ์ ํ์ ํญ๋ชฉ์
๋๋ค.")
private String title;
@NotBlank(message = "๋ด์ฉ์ ํ์ ํญ๋ชฉ์
๋๋ค.")
private String contents;
private LocalDateTime regDate;
}
/*
config/ResponseError.java ์์ฑ
*/
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class ResponseError {
private String field;
private String message;
public static ResponseError of(ObjectError e) {
return ResponseError.builder()
.field(((FieldError) e).getField())
.message(e.getDefaultMessage())
.build();
}
}
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@PostMapping("/api/notice")
public ResponseEntity<?> addNotice(@RequestBody @Valid NoticeDto noticeDto, Errors errors) {
if (errors.hasErrors()) {
List<ResponseError> responseErrors = new ArrayList<>();
errors.getAllErrors().forEach(e -> {
// ์ด๋ ๊ฒ๋ ๊ฐ๋ฅ
// ResponseError responseError = new ResponseError();
// responseError.setField(((FieldError) e).getField());
// responseError.setMessage(e.getDefaultMessage());
// responseErrors.add(responseError);
responseErrors.add(ResponseError.of((FieldError)e));
});
return new ResponseEntity<>(responseErrors, HttpStatus.BAD_REQUEST);
}
//์ ์์ ์ธ ์ ์ฅ
Notice notice = Notice.builder()
.title(noticeDto.getTitle())
.contents(noticeDto.getContents())
.likes(0)
.hits(0)
.regDate(LocalDateTime.now())
.build();
noticeRepository.save(notice);
return ResponseEntity.ok().build();
}
}
(28) ๊ธ์ ์์ฑํ ๋ ์ ๋ชฉ๊ณผ ๋ด์ฉ์ ๋ฐ์์ ์ ์ฅํ๋ API
- ํ์ : REST API
- HTTP METHOD : POST
- ์ ๋ ฅ๊ฐ์ ์ ๋ ฅDTO๋ฅผ ํตํด์ ์ ๋ ฅ๋ฐ์
- ์ ๋ชฉ๊ณผ ๋ด์ฉ์ ํ์ ์ ๋ ฅ ์กฐ๊ฑด(์ ๋ ฅ๋์ง ์์ ๊ฒฝ์ฐ 400๋ฆฌํด)
- +) ์ ๋ชฉ์ ๊ฒฝ์ฐ 10์ ์ด์ 100์ ์ดํ๋ก ์ ๋ ฅ
- +) ๋ด์ฉ์ ๊ฒฝ์ฐ 50์ ์ด์ 1000์ ์ดํ๋ก ์ ๋ ฅ
- ์์ธ๋ฐ์์ ๊ฐ๊ฐ์ ์๋ฌ๋ฅผ ์ทจํฉํ์ฌ ์ฝ๋ ์ ํํ๋ก ๋ฆฌํด
/*
dto/NoticeDto.java ์์
*/
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class NoticeDto {
//๊ฒ์๊ธID, ์ ๋ชฉ, ๋ด์ฉ, ๋ฑ๋ก์ผ
private long id;
@NotBlank(message = "์ ๋ชฉ์ ํ์ ํญ๋ชฉ์
๋๋ค.")
@Size(min = 10, max = 100, message = "์ ๋ชฉ์ 10-100์ ์ฌ์ด์ ๊ฐ์
๋๋ค.")
private String title;
@NotBlank(message = "๋ด์ฉ์ ํ์ ํญ๋ชฉ์
๋๋ค.")
@Size(min = 50, max = 1000, message = "๋ด์ฉ์ 10-100์ ์ฌ์ด์ ๊ฐ์
๋๋ค.")
private String contents;
private LocalDateTime regDate;
}
(29) ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ณต์ง์ฌํญ ๋ชฉ๋ก ์ค์์ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌ๋ ๊ฐ์๋งํผ ์ต๊ทผ ๊ณต์ง์ฌํญ์ ๋ฆฌํดํ๋ API
- ex) ์ต๊ทผ 2๊ฐ
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@GetMapping("/api/notice/latest/{size}")
public Page<Notice> noticeLatest(@PathVariable int size) {
Page<Notice> noticePage = noticeRepository.findAll(PageRequest.of(0, size, Sort.Direction.DESC, "regDate"));
return noticePage;
}
}
(30) ๊ณต์ง์ฌํญ์ ๋ด์ฉ์ ๋ฑ๋กํ ์ดํ์ ๋ฐ๋ก ๋์ผํ ์ ๋ชฉ๊ณผ ๋ด์ฉ์ ๊ณต์ง์ฌํญ์ ๋ฑ๋กํ๋ ๊ฒฝ์ฐ ๋ฑ๋ก์ ๋ง๋ API
- ์ค๋ณต ๊ฒฝ์ฐ (์กฐ๊ฑด : ๋์ผ์ ๋ชฉ, ๋์ผ๋ด์ฉ๊ณผ ๋ฑ๋ก์ผ์ด ํ์ฌ์๊ฐ ๊ธฐ์ค 1๋ถ ์ด๋ด์ ๊ฒฝ์ฐ๋ ์ค๋ณต์ผ๋ก ํ๋จํจ)
- ์์ธ๋ฐ์ (DuplicateNoticeException)
/*
repository/NoticeRepository.java ๋ณ๊ฒฝ
*/
@Repository
public interface NoticeRepository extends JpaRepository<Notice, Long> {
//๊ฒฝ์ฐ 1
Optional<List<Notice>> findByTitleAndContentsAndRegDateIsGreaterThanEqual(String title, String contents, LocalDateTime regDate);
//๊ฒฝ์ฐ 2
int countByTitleAndContentsAndRegDateIsGreaterThanEqual(String title, String contents, LocalDateTime regDate);
}
/*
exception/DuplicateNoticeException.java ์์ฑ
*/
public class DuplicateNoticeException extends RuntimeException{
public DuplicateNoticeException(String message) {
super(message);
}
}
@RequiredArgsConstructor
@RestController
public class NoticeController {
private final NoticeRepository noticeRepository;
@ExceptionHandler(DuplicateNoticeException.class)
public ResponseEntity<String> handlerDuplicateNoticeException(DuplicateNoticeException exception) {
return new ResponseEntity<>(exception.getMessage(), HttpStatus.BAD_REQUEST);
}
@PostMapping("/api/notice")
public void addNotice(@RequestBody NoticeDto noticeDto) {
//์ค๋ณต์ฒดํฌ
LocalDateTime checkDate = LocalDateTime.now().minusMinutes(1);
// ๊ฒฝ์ฐ1
// Optional<List<Notice>> noticeList = noticeRepository.findByTitleAndContentsAndRegDateIsGreaterThanEqual(
// noticeDto.getTitle(),
// noticeDto.getContents(),
// checkDate);
// if (noticeList.isPresent()) {
// if (noticeList.get().size() > 0) {
// throw new DuplicateNoticeException("1๋ถ์ด๋ด์ ๋ฑ๋ก๋ ๋์ผํ ๊ณต์ง์ฌํญ์ด ์กด์ฌํฉ๋๋ค.");
// }
//๊ฒฝ์ฐ 2
int noticeCount = noticeRepository.countByTitleAndContentsAndRegDateIsGreaterThanEqual(
noticeDto.getTitle(),
noticeDto.getContents(),
checkDate);
if (noticeCount > 0) {
throw new DuplicateNoticeException("1๋ถ์ด๋ด์ ๋ฑ๋ก๋ ๋์ผํ ๊ณต์ง์ฌํญ์ด ์กด์ฌํฉ๋๋ค.");
}
Notice notice = Notice.builder()
.title(noticeDto.getTitle())
.contents(noticeDto.getContents())
.likes(0)
.hits(0)
.regDate(LocalDateTime.now())
.build();
noticeRepository.save(notice);
}
}
๋๊ธ