From 2f3c0263a39d1f524fdab49a4e688355ea1feebe Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Tue, 28 May 2024 14:30:53 +0900 Subject: [PATCH 01/10] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20Create?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/blog/domain/user/domain/User.java | 9 ++++++- .../blog/domain/user/service/UserService.java | 25 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/example/blog/domain/user/service/UserService.java diff --git a/src/main/java/com/example/blog/domain/user/domain/User.java b/src/main/java/com/example/blog/domain/user/domain/User.java index d086e59..a231473 100644 --- a/src/main/java/com/example/blog/domain/user/domain/User.java +++ b/src/main/java/com/example/blog/domain/user/domain/User.java @@ -15,10 +15,16 @@ @Getter public class User{ @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) // 기본키 생성 private Long id; + + @Column(nullable = true) private String username; + + @Column(nullable = true) private String email; + + @Column(nullable = true) private String password; @OneToMany(mappedBy = "user", cascade = CascadeType.ALL) @@ -32,6 +38,7 @@ public User(String username, String email, String password) { this.password = password; } + //편의 메서드 public void update(String username, String password) { this.username = username; diff --git a/src/main/java/com/example/blog/domain/user/service/UserService.java b/src/main/java/com/example/blog/domain/user/service/UserService.java new file mode 100644 index 0000000..29fc506 --- /dev/null +++ b/src/main/java/com/example/blog/domain/user/service/UserService.java @@ -0,0 +1,25 @@ +package com.example.blog.domain.user.service; + +import com.example.blog.domain.user.domain.User; +import com.example.blog.domain.user.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.GetMapping; + +@Service +@RequiredArgsConstructor +public class UserService { + private final UserRepository userRepository; + + // Create + public User createUser(String username, String email, String password){ + User user = User.builder() + .username(username) + .email(email) + .password(password) + .build(); + return userRepository.save(user); + } + + +} From 0d85a2ced1060d38ab5caa391db92011062a3190 Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Tue, 28 May 2024 14:52:46 +0900 Subject: [PATCH 02/10] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20CRUD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/Controller/UserController.java | 54 +++++++++++++++++++ .../example/blog/domain/user/dto/UserReq.java | 17 ++++++ .../example/blog/domain/user/dto/UserRes.java | 18 +++++++ .../user/repository/UserRepository.java | 2 +- .../blog/domain/user/service/UserService.java | 44 +++++++++++---- 5 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 src/main/java/com/example/blog/domain/user/Controller/UserController.java create mode 100644 src/main/java/com/example/blog/domain/user/dto/UserReq.java create mode 100644 src/main/java/com/example/blog/domain/user/dto/UserRes.java diff --git a/src/main/java/com/example/blog/domain/user/Controller/UserController.java b/src/main/java/com/example/blog/domain/user/Controller/UserController.java new file mode 100644 index 0000000..6a008ce --- /dev/null +++ b/src/main/java/com/example/blog/domain/user/Controller/UserController.java @@ -0,0 +1,54 @@ +package com.example.blog.domain.user.Controller; + +import com.example.blog.domain.user.domain.User; +import com.example.blog.domain.user.dto.UserReq; +import com.example.blog.domain.user.dto.UserRes; +import com.example.blog.domain.user.service.UserService; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@Slf4j +@AllArgsConstructor +@RequestMapping("/users") +public class UserController { + private final UserService userService; + + @GetMapping("") + public ResponseEntity getAllUsers() { + List users = userService.getAllUsers(); + return ResponseEntity.ok(users); + } + + @GetMapping("/{id}") + public ResponseEntity getUser(@PathVariable Long userId){ + User user = userService.getUser(userId); + UserRes userRes = UserRes.fromEntity(user); + return ResponseEntity.ok(user); + } + + @PostMapping("") + public ResponseEntity createUser(@RequestBody UserReq userReq){ + User user = userService.createUser(userReq); + UserRes userRes = UserRes.fromEntity(user); + return ResponseEntity.ok(userRes); + } + + @PutMapping("/{id}") + public ResponseEntity updateUser(@PathVariable Long userId, @RequestBody UserReq userReq){ + User user = userService.updateUser(userId, userReq); + UserRes userRes = UserRes.fromEntity(user); + return ResponseEntity.ok(userRes); + } + + @DeleteMapping("/{id}") + public ResponseEntity deleteUser(@PathVariable Long userId){ + userService.deleteUser(userId); + return ResponseEntity.ok().build(); + } + +} diff --git a/src/main/java/com/example/blog/domain/user/dto/UserReq.java b/src/main/java/com/example/blog/domain/user/dto/UserReq.java new file mode 100644 index 0000000..59c62af --- /dev/null +++ b/src/main/java/com/example/blog/domain/user/dto/UserReq.java @@ -0,0 +1,17 @@ +package com.example.blog.domain.user.dto; + +import com.example.blog.domain.user.domain.User; + +public record UserReq( + String username, + String email, + String password +) { + public User toEntity() { + return User.builder() + .username(username) + .email(email) + .password(password) + .build(); + } +} diff --git a/src/main/java/com/example/blog/domain/user/dto/UserRes.java b/src/main/java/com/example/blog/domain/user/dto/UserRes.java new file mode 100644 index 0000000..bc5a58e --- /dev/null +++ b/src/main/java/com/example/blog/domain/user/dto/UserRes.java @@ -0,0 +1,18 @@ +package com.example.blog.domain.user.dto; + +import com.example.blog.domain.user.domain.User; + +public record UserRes( + Long id, + String username, + String email +) { + // 간단하게 파라미터가 여러개면? -> of, 단일 파라미터(주로 인스턴스)가 들어온다? -> from + public static UserRes of(Long id, String username, String email) { + return new UserRes(id, username, email); + } + + public static UserRes fromEntity(User user) { + return new UserRes(user.getId(), user.getUsername(), user.getEmail()); + } +} diff --git a/src/main/java/com/example/blog/domain/user/repository/UserRepository.java b/src/main/java/com/example/blog/domain/user/repository/UserRepository.java index 08ec5b7..e1e0354 100644 --- a/src/main/java/com/example/blog/domain/user/repository/UserRepository.java +++ b/src/main/java/com/example/blog/domain/user/repository/UserRepository.java @@ -6,4 +6,4 @@ @Repository public interface UserRepository extends JpaRepository { -} +} \ No newline at end of file diff --git a/src/main/java/com/example/blog/domain/user/service/UserService.java b/src/main/java/com/example/blog/domain/user/service/UserService.java index 29fc506..56b7252 100644 --- a/src/main/java/com/example/blog/domain/user/service/UserService.java +++ b/src/main/java/com/example/blog/domain/user/service/UserService.java @@ -1,25 +1,49 @@ package com.example.blog.domain.user.service; +import com.example.blog.domain.user.dto.UserReq; +import com.example.blog.domain.user.dto.UserRes; import com.example.blog.domain.user.domain.User; import com.example.blog.domain.user.repository.UserRepository; -import lombok.RequiredArgsConstructor; +import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; -import org.springframework.web.bind.annotation.GetMapping; + +import java.util.List; +import java.util.stream.Collectors; @Service -@RequiredArgsConstructor +@AllArgsConstructor public class UserService { private final UserRepository userRepository; - // Create - public User createUser(String username, String email, String password){ - User user = User.builder() - .username(username) - .email(email) - .password(password) - .build(); + public List getAllUsers() { + List users = userRepository.findAll(); + return users.stream() + .map(UserRes::fromEntity) + .collect(Collectors.toList()); + } + + public User getUser(Long userId) { + return userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("해당 유저 없음")); + } + + public User createUser(UserReq request) { + User user = request.toEntity(); + return userRepository.save(user); } + public User updateUser(Long userId, UserReq request) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("해당 유저 없음")); + + // 여기는 save 안해주나요?? + user.update(request.username(), request.password()); + return user; + } + + public void deleteUser(Long userId) { + userRepository.deleteById(userId); + } } From 1f98dd9a160fe3ea2274f20d8c3db619a700b8aa Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Tue, 28 May 2024 16:06:47 +0900 Subject: [PATCH 03/10] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20CRUD,=20Pos?= =?UTF-8?q?tman-save=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/blog/domain/user/Controller/UserController.java | 6 +++--- .../com/example/blog/domain/user/service/UserService.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/blog/domain/user/Controller/UserController.java b/src/main/java/com/example/blog/domain/user/Controller/UserController.java index 6a008ce..5671615 100644 --- a/src/main/java/com/example/blog/domain/user/Controller/UserController.java +++ b/src/main/java/com/example/blog/domain/user/Controller/UserController.java @@ -24,7 +24,7 @@ public ResponseEntity getAllUsers() { return ResponseEntity.ok(users); } - @GetMapping("/{id}") + @GetMapping("/{userId}") // id -> userId로 변경 public ResponseEntity getUser(@PathVariable Long userId){ User user = userService.getUser(userId); UserRes userRes = UserRes.fromEntity(user); @@ -38,14 +38,14 @@ public ResponseEntity createUser(@RequestBody UserReq userReq){ return ResponseEntity.ok(userRes); } - @PutMapping("/{id}") + @PutMapping("/{userId}") public ResponseEntity updateUser(@PathVariable Long userId, @RequestBody UserReq userReq){ User user = userService.updateUser(userId, userReq); UserRes userRes = UserRes.fromEntity(user); return ResponseEntity.ok(userRes); } - @DeleteMapping("/{id}") + @DeleteMapping("/{userId}") public ResponseEntity deleteUser(@PathVariable Long userId){ userService.deleteUser(userId); return ResponseEntity.ok().build(); diff --git a/src/main/java/com/example/blog/domain/user/service/UserService.java b/src/main/java/com/example/blog/domain/user/service/UserService.java index 56b7252..3f889eb 100644 --- a/src/main/java/com/example/blog/domain/user/service/UserService.java +++ b/src/main/java/com/example/blog/domain/user/service/UserService.java @@ -40,7 +40,7 @@ public User updateUser(Long userId, UserReq request) { // 여기는 save 안해주나요?? user.update(request.username(), request.password()); - return user; + return userRepository.save(user); // save 추가 } public void deleteUser(Long userId) { From d15e0addc6645cca493d380332cb00b27d221c68 Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Tue, 28 May 2024 16:38:19 +0900 Subject: [PATCH 04/10] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20CRUD,=20sav?= =?UTF-8?q?e=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/blog/domain/post/domain/Post.java | 2 +- .../java/com/example/blog/domain/user/service/UserService.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/blog/domain/post/domain/Post.java b/src/main/java/com/example/blog/domain/post/domain/Post.java index f1e4bab..9d11e59 100644 --- a/src/main/java/com/example/blog/domain/post/domain/Post.java +++ b/src/main/java/com/example/blog/domain/post/domain/Post.java @@ -17,7 +17,7 @@ public class Post { @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @JoinColumn(name = "user_id") - User user; + User user; // 작성자 필드 private String title; private String content; diff --git a/src/main/java/com/example/blog/domain/user/service/UserService.java b/src/main/java/com/example/blog/domain/user/service/UserService.java index 3f889eb..90cc2d5 100644 --- a/src/main/java/com/example/blog/domain/user/service/UserService.java +++ b/src/main/java/com/example/blog/domain/user/service/UserService.java @@ -46,4 +46,7 @@ public User updateUser(Long userId, UserReq request) { public void deleteUser(Long userId) { userRepository.deleteById(userId); } + + + } From 3dd5c5eaac93308e2a91db63883926294ca727cb Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Tue, 28 May 2024 23:00:00 +0900 Subject: [PATCH 05/10] =?UTF-8?q?=EC=82=AC=EC=9A=A9=EC=9E=90=20CRUD,=20?= =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=EC=9E=AC=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20API=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blog/domain/user/Controller/UserController.java | 9 +++++++++ .../com/example/blog/domain/user/dto/PwdDto.java | 6 ++++++ .../blog/domain/user/service/UserService.java | 13 ++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/example/blog/domain/user/dto/PwdDto.java diff --git a/src/main/java/com/example/blog/domain/user/Controller/UserController.java b/src/main/java/com/example/blog/domain/user/Controller/UserController.java index 5671615..1be8044 100644 --- a/src/main/java/com/example/blog/domain/user/Controller/UserController.java +++ b/src/main/java/com/example/blog/domain/user/Controller/UserController.java @@ -1,6 +1,7 @@ package com.example.blog.domain.user.Controller; import com.example.blog.domain.user.domain.User; +import com.example.blog.domain.user.dto.PwdDto; import com.example.blog.domain.user.dto.UserReq; import com.example.blog.domain.user.dto.UserRes; import com.example.blog.domain.user.service.UserService; @@ -51,4 +52,12 @@ public ResponseEntity deleteUser(@PathVariable Long userId){ return ResponseEntity.ok().build(); } + // 비밀번호 재생성 API 생성 + @PutMapping("/{userId}/reset-password") + public ResponseEntity resetPassword(@PathVariable Long userId, @RequestBody PwdDto pwdDto) { + User user = userService.resetPassword(userId, pwdDto); + UserRes userRes = UserRes.fromEntity(user); + return ResponseEntity.ok(userRes); + } + } diff --git a/src/main/java/com/example/blog/domain/user/dto/PwdDto.java b/src/main/java/com/example/blog/domain/user/dto/PwdDto.java new file mode 100644 index 0000000..2b447dd --- /dev/null +++ b/src/main/java/com/example/blog/domain/user/dto/PwdDto.java @@ -0,0 +1,6 @@ +package com.example.blog.domain.user.dto; + +public record PwdDto ( + String newPassword +) {} + diff --git a/src/main/java/com/example/blog/domain/user/service/UserService.java b/src/main/java/com/example/blog/domain/user/service/UserService.java index 90cc2d5..e441666 100644 --- a/src/main/java/com/example/blog/domain/user/service/UserService.java +++ b/src/main/java/com/example/blog/domain/user/service/UserService.java @@ -1,5 +1,6 @@ package com.example.blog.domain.user.service; +import com.example.blog.domain.user.dto.PwdDto; import com.example.blog.domain.user.dto.UserReq; import com.example.blog.domain.user.dto.UserRes; import com.example.blog.domain.user.domain.User; @@ -7,6 +8,7 @@ import lombok.AllArgsConstructor; import org.springframework.stereotype.Service; + import java.util.List; import java.util.stream.Collectors; @@ -37,7 +39,6 @@ public User updateUser(Long userId, UserReq request) { User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("해당 유저 없음")); - // 여기는 save 안해주나요?? user.update(request.username(), request.password()); return userRepository.save(user); // save 추가 @@ -47,6 +48,12 @@ public void deleteUser(Long userId) { userRepository.deleteById(userId); } + // 기능 추가 : 비밀번호 재설정 + public User resetPassword(Long userId, PwdDto pwdDto) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("해당 유저 없음")); - -} + user.update(user.getUsername(), pwdDto.newPassword()); + return userRepository.save(user); + } +} \ No newline at end of file From 3dbbb40eb1f303e09888a183d57d67912b39e6f0 Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Wed, 29 May 2024 12:20:17 +0900 Subject: [PATCH 06/10] Post CRUD --- .../post/Controller/PostController.java | 65 +++++++++++++++++++ .../example/blog/domain/post/domain/Post.java | 8 ++- .../example/blog/domain/post/dto/PostReq.java | 17 +++++ .../example/blog/domain/post/dto/PostRes.java | 16 +++++ .../post/repository/PostRepository.java | 6 +- .../blog/domain/post/service/PostService.java | 10 ++- 6 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 src/main/java/com/example/blog/domain/post/Controller/PostController.java create mode 100644 src/main/java/com/example/blog/domain/post/dto/PostReq.java create mode 100644 src/main/java/com/example/blog/domain/post/dto/PostRes.java diff --git a/src/main/java/com/example/blog/domain/post/Controller/PostController.java b/src/main/java/com/example/blog/domain/post/Controller/PostController.java new file mode 100644 index 0000000..6c4debc --- /dev/null +++ b/src/main/java/com/example/blog/domain/post/Controller/PostController.java @@ -0,0 +1,65 @@ +package com.example.blog.domain.post.Controller; + +import com.example.blog.domain.post.domain.Post; +import com.example.blog.domain.post.service.PostService; +import com.example.blog.domain.post.dto.PostReq; +import com.example.blog.domain.post.dto.PostRes; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.stream.Collectors; + +@RestController +@Slf4j +@RequiredArgsConstructor +@RequestMapping("/posts") +public class PostController { + private final PostService postService; + + @GetMapping("") + public ResponseEntity> getAllPosts() { + List posts = postService.getAllPosts(); + List postResponses = posts.stream() + .map(PostRes::fromEntity) + .collect(Collectors.toList()); + return ResponseEntity.ok(postResponses); + } + + @GetMapping("/{postId}") + public ResponseEntity getPost(@PathVariable Long postId) { + Post post = postService.getPost(postId); + PostRes postRes = PostRes.fromEntity(post); + return ResponseEntity.ok(postRes); + } + + @PostMapping("") + public ResponseEntity createPost(@RequestBody PostReq postReq) { + Post post = Post.builder() + .title(postReq.title()) + .content(postReq.content()) + .build(); + Post createdPost = postService.createPost(postReq.userId(), post); + PostRes postRes = PostRes.fromEntity(createdPost); + return ResponseEntity.ok(postRes); + } + + @PutMapping("/{postId}") + public ResponseEntity updatePost(@PathVariable Long postId, @RequestBody PostReq postReq) { + Post post = Post.builder() + .title(postReq.title()) + .content(postReq.content()) + .build(); + Post updatedPost = postService.updatePost(postId, post); + PostRes postRes = PostRes.fromEntity(updatedPost); + return ResponseEntity.ok(postRes); + } + + @DeleteMapping("/{postId}") + public ResponseEntity deletePost(@PathVariable Long postId) { + postService.deletePost(postId); + return ResponseEntity.ok().build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/blog/domain/post/domain/Post.java b/src/main/java/com/example/blog/domain/post/domain/Post.java index 9d11e59..f8de11a 100644 --- a/src/main/java/com/example/blog/domain/post/domain/Post.java +++ b/src/main/java/com/example/blog/domain/post/domain/Post.java @@ -1,12 +1,17 @@ package com.example.blog.domain.post.domain; +import com.example.blog.domain.post.dto.PostRes; import com.example.blog.domain.user.domain.User; +import com.example.blog.domain.user.dto.UserRes; import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.List; +import java.util.stream.Collectors; + @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @@ -17,7 +22,7 @@ public class Post { @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @JoinColumn(name = "user_id") - User user; // 작성자 필드 + private User user; // 작성자 필드 private String title; private String content; @@ -28,6 +33,7 @@ public Post(String title, String content) { this.content = content; } + // 편의 메서드 public void update(String title, String content) { this.title = title; diff --git a/src/main/java/com/example/blog/domain/post/dto/PostReq.java b/src/main/java/com/example/blog/domain/post/dto/PostReq.java new file mode 100644 index 0000000..6accd17 --- /dev/null +++ b/src/main/java/com/example/blog/domain/post/dto/PostReq.java @@ -0,0 +1,17 @@ +package com.example.blog.domain.post.dto; + +import com.example.blog.domain.post.domain.Post; +import com.example.blog.domain.user.domain.User; + +public record PostReq( + Long userId, + String title, + String content +) { + public Post toEntity() { + return Post.builder() + .title(title) + .content(content) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/blog/domain/post/dto/PostRes.java b/src/main/java/com/example/blog/domain/post/dto/PostRes.java new file mode 100644 index 0000000..e400d4a --- /dev/null +++ b/src/main/java/com/example/blog/domain/post/dto/PostRes.java @@ -0,0 +1,16 @@ +package com.example.blog.domain.post.dto; + +import com.example.blog.domain.post.domain.Post; + +public record PostRes( + Long id, + String title, + String content, + Long userId +) { + + public static PostRes fromEntity(Post post) { + return new PostRes(post.getId(), post.getTitle(), post.getContent(), post.getUser().getId()); + } +} + diff --git a/src/main/java/com/example/blog/domain/post/repository/PostRepository.java b/src/main/java/com/example/blog/domain/post/repository/PostRepository.java index e3065f4..f6cc8af 100644 --- a/src/main/java/com/example/blog/domain/post/repository/PostRepository.java +++ b/src/main/java/com/example/blog/domain/post/repository/PostRepository.java @@ -1,6 +1,7 @@ package com.example.blog.domain.post.repository; import com.example.blog.domain.post.domain.Post; +import com.example.blog.domain.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @@ -8,8 +9,5 @@ @Repository public interface PostRepository extends JpaRepository { - - Optional findByTitle(String title); - - Optional findByTitleOrContent(String title, String content); } + diff --git a/src/main/java/com/example/blog/domain/post/service/PostService.java b/src/main/java/com/example/blog/domain/post/service/PostService.java index bbb71de..89fdbe6 100644 --- a/src/main/java/com/example/blog/domain/post/service/PostService.java +++ b/src/main/java/com/example/blog/domain/post/service/PostService.java @@ -7,6 +7,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; + @Service @RequiredArgsConstructor public class PostService { @@ -36,7 +38,13 @@ public Post updatePost(Long postId, Post post) { .orElseThrow(() -> new IllegalArgumentException("해당 게시글 없음!")); foundPost.update(post.getTitle(), post.getContent()); - return foundPost; + return postRepository.save(foundPost); + } + + + // getAllPosts + public List getAllPosts() { + return postRepository.findAll(); } } From eecf2a31d30f5cb8b7e1ead002df5c15e866f60e Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Wed, 29 May 2024 13:41:38 +0900 Subject: [PATCH 07/10] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blog/domain/post/Controller/PostController.java | 3 +++ .../java/com/example/blog/domain/post/domain/Post.java | 7 ++++++- .../java/com/example/blog/domain/post/dto/PostRes.java | 5 +++-- .../blog/domain/post/repository/PostRepository.java | 6 ++++++ .../com/example/blog/domain/post/service/PostService.java | 7 +++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/blog/domain/post/Controller/PostController.java b/src/main/java/com/example/blog/domain/post/Controller/PostController.java index 6c4debc..d2b9823 100644 --- a/src/main/java/com/example/blog/domain/post/Controller/PostController.java +++ b/src/main/java/com/example/blog/domain/post/Controller/PostController.java @@ -7,6 +7,7 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -30,6 +31,7 @@ public ResponseEntity> getAllPosts() { @GetMapping("/{postId}") public ResponseEntity getPost(@PathVariable Long postId) { + postService.updateView(postId); // 조회수 증가 Post post = postService.getPost(postId); PostRes postRes = PostRes.fromEntity(post); return ResponseEntity.ok(postRes); @@ -62,4 +64,5 @@ public ResponseEntity deletePost(@PathVariable Long postId) { postService.deletePost(postId); return ResponseEntity.ok().build(); } + } \ No newline at end of file diff --git a/src/main/java/com/example/blog/domain/post/domain/Post.java b/src/main/java/com/example/blog/domain/post/domain/Post.java index f8de11a..9b72e3f 100644 --- a/src/main/java/com/example/blog/domain/post/domain/Post.java +++ b/src/main/java/com/example/blog/domain/post/domain/Post.java @@ -23,10 +23,15 @@ public class Post { @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) @JoinColumn(name = "user_id") private User user; // 작성자 필드 - + @Column(nullable = false) private String title; + @Column(nullable = false) private String content; + // 조회수 기능 추가 + @Column(columnDefinition = "integer default 0", nullable = false) + private int view; + @Builder public Post(String title, String content) { this.title = title; diff --git a/src/main/java/com/example/blog/domain/post/dto/PostRes.java b/src/main/java/com/example/blog/domain/post/dto/PostRes.java index e400d4a..e423807 100644 --- a/src/main/java/com/example/blog/domain/post/dto/PostRes.java +++ b/src/main/java/com/example/blog/domain/post/dto/PostRes.java @@ -6,11 +6,12 @@ public record PostRes( Long id, String title, String content, - Long userId + Long userId, + int view // 조회수 추가 ) { public static PostRes fromEntity(Post post) { - return new PostRes(post.getId(), post.getTitle(), post.getContent(), post.getUser().getId()); + return new PostRes(post.getId(), post.getTitle(), post.getContent(), post.getUser().getId(), post.getView()); // 게시글 조회 빌더 추가 } } diff --git a/src/main/java/com/example/blog/domain/post/repository/PostRepository.java b/src/main/java/com/example/blog/domain/post/repository/PostRepository.java index f6cc8af..56ee598 100644 --- a/src/main/java/com/example/blog/domain/post/repository/PostRepository.java +++ b/src/main/java/com/example/blog/domain/post/repository/PostRepository.java @@ -3,11 +3,17 @@ import com.example.blog.domain.post.domain.Post; import com.example.blog.domain.user.domain.User; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; import java.util.Optional; @Repository public interface PostRepository extends JpaRepository { + + @Modifying + @Query("update Post p set p.view = p.view + 1 where p.id = :id") + int updateView(Long id); } diff --git a/src/main/java/com/example/blog/domain/post/service/PostService.java b/src/main/java/com/example/blog/domain/post/service/PostService.java index 89fdbe6..af53ba0 100644 --- a/src/main/java/com/example/blog/domain/post/service/PostService.java +++ b/src/main/java/com/example/blog/domain/post/service/PostService.java @@ -4,6 +4,7 @@ import com.example.blog.domain.post.repository.PostRepository; import com.example.blog.domain.user.domain.User; import com.example.blog.domain.user.repository.UserRepository; +import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -47,4 +48,10 @@ public List getAllPosts() { return postRepository.findAll(); } + + @Transactional + // 기능 추가 : 조회수 증가 + public void updateView(Long id){ + postRepository.updateView(id); + } } From b027229732f902b02097a89f4462f49199f18449 Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Wed, 29 May 2024 21:55:50 +0900 Subject: [PATCH 08/10] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EA=B2=80?= =?UTF-8?q?=EC=83=89=20=EA=B8=B0=EB=8A=A5(=EC=A0=9C=EB=AA=A9,=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9,=20=EC=9E=91=EC=84=B1=EC=9E=90)=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/Controller/PostController.java | 42 +++++++++++++++++++ .../post/repository/PostRepository.java | 11 +++++ .../blog/domain/post/service/PostService.java | 24 ++++++++++- 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/blog/domain/post/Controller/PostController.java b/src/main/java/com/example/blog/domain/post/Controller/PostController.java index d2b9823..360c336 100644 --- a/src/main/java/com/example/blog/domain/post/Controller/PostController.java +++ b/src/main/java/com/example/blog/domain/post/Controller/PostController.java @@ -64,5 +64,47 @@ public ResponseEntity deletePost(@PathVariable Long postId) { postService.deletePost(postId); return ResponseEntity.ok().build(); } + @RestController + public class SearchController { + + // 검색 기능 : 제목 + @GetMapping("/search/title") + public ResponseEntity searchByTitle(@RequestParam String titleKeyword) { + List searchList = postService.searchByTitle(titleKeyword); + if (searchList.isEmpty()) { + return ResponseEntity.status(404).body("해당 게시물 없음!"); + } + List postResponses = searchList.stream() + .map(PostRes::fromEntity) + .collect(Collectors.toList()); + return ResponseEntity.ok(postResponses); + } + + // 검색 기능 : 내용 + @GetMapping("/search/content") + public ResponseEntity searchByContent(@RequestParam String contentKeyword) { + List searchList = postService.searchByContent(contentKeyword); + if (searchList.isEmpty()) { + return ResponseEntity.status(404).body("해당 내용 없음!"); + } + List postResponses = searchList.stream() + .map(PostRes::fromEntity) + .collect(Collectors.toList()); + return ResponseEntity.ok(postResponses); + } + + // 검색 기능 : 작성자 + @GetMapping("/search/username") + public ResponseEntity searchByUsername(@RequestParam String usernameKeyword) { + List searchList = postService.searchByUsername(usernameKeyword); + if (searchList.isEmpty()) { + return ResponseEntity.status(404).body("해당 작성자 없음!"); + } + List postResponses = searchList.stream() + .map(PostRes::fromEntity) + .collect(Collectors.toList()); + return ResponseEntity.ok(postResponses); + } + } } \ No newline at end of file diff --git a/src/main/java/com/example/blog/domain/post/repository/PostRepository.java b/src/main/java/com/example/blog/domain/post/repository/PostRepository.java index 56ee598..cd491cf 100644 --- a/src/main/java/com/example/blog/domain/post/repository/PostRepository.java +++ b/src/main/java/com/example/blog/domain/post/repository/PostRepository.java @@ -7,6 +7,7 @@ import org.springframework.data.jpa.repository.Query; import org.springframework.stereotype.Repository; +import java.util.List; import java.util.Optional; @Repository @@ -15,5 +16,15 @@ public interface PostRepository extends JpaRepository { @Modifying @Query("update Post p set p.view = p.view + 1 where p.id = :id") int updateView(Long id); + + // 게시판 검색 기능 추가 + + List findByTitle(String titleKeyword); + + List findByContent(String contentKeyword); + + List findByUserUsername(String usernameKeyword); + + } diff --git a/src/main/java/com/example/blog/domain/post/service/PostService.java b/src/main/java/com/example/blog/domain/post/service/PostService.java index af53ba0..6504337 100644 --- a/src/main/java/com/example/blog/domain/post/service/PostService.java +++ b/src/main/java/com/example/blog/domain/post/service/PostService.java @@ -48,10 +48,30 @@ public List getAllPosts() { return postRepository.findAll(); } - - @Transactional // 기능 추가 : 조회수 증가 + @Transactional public void updateView(Long id){ postRepository.updateView(id); } + + // 기능 추가 : 게시판 검색 + + @Transactional + public List searchByTitle(String titleKeyword) { + return postRepository.findByTitle(titleKeyword); + } + + @Transactional + public List searchByContent(String contentKeyword) { + return postRepository.findByContent(contentKeyword); + } + + @Transactional + public List searchByUsername(String usernameKeyword) { + return postRepository.findByUserUsername(usernameKeyword); + } + + + + } From ea79d196e592825a91d4de3f6bf2a559fd4997ca Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Wed, 29 May 2024 22:23:48 +0900 Subject: [PATCH 09/10] =?UTF-8?q?=EB=8C=93=EA=B8=80=20CRUD=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/Controller/CommentController.java | 51 +++++++++++++++ .../blog/domain/comment/domain/Comment.java | 41 ++++++++++++ .../blog/domain/comment/dto/CommentReq.java | 12 ++++ .../blog/domain/comment/dto/CommentRes.java | 23 +++++++ .../comment/repository/CommentRepository.java | 11 ++++ .../comment/service/CommentService.java | 62 +++++++++++++++++++ 6 files changed, 200 insertions(+) create mode 100644 src/main/java/com/example/blog/domain/comment/Controller/CommentController.java create mode 100644 src/main/java/com/example/blog/domain/comment/domain/Comment.java create mode 100644 src/main/java/com/example/blog/domain/comment/dto/CommentReq.java create mode 100644 src/main/java/com/example/blog/domain/comment/dto/CommentRes.java create mode 100644 src/main/java/com/example/blog/domain/comment/repository/CommentRepository.java create mode 100644 src/main/java/com/example/blog/domain/comment/service/CommentService.java diff --git a/src/main/java/com/example/blog/domain/comment/Controller/CommentController.java b/src/main/java/com/example/blog/domain/comment/Controller/CommentController.java new file mode 100644 index 0000000..a33d838 --- /dev/null +++ b/src/main/java/com/example/blog/domain/comment/Controller/CommentController.java @@ -0,0 +1,51 @@ +package com.example.blog.domain.comment.Controller; + + +import com.example.blog.domain.comment.dto.CommentReq; +import com.example.blog.domain.comment.dto.CommentRes; +import com.example.blog.domain.comment.service.CommentService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/comments") +public class CommentController { + + private final CommentService commentService; + + public CommentController(CommentService commentService) { + this.commentService = commentService; + } + + @PostMapping + public ResponseEntity createComment(@RequestBody CommentReq commentReq) { + CommentRes comment = commentService.createComment(commentReq); + return ResponseEntity.ok(comment); + } + + @GetMapping("/post/{postId}") + public ResponseEntity> getCommentsByPostId(@PathVariable Long postId) { + List comments = commentService.getCommentsByPostId(postId); + return ResponseEntity.ok(comments); + } + + @GetMapping("/user/{userId}") + public ResponseEntity> getCommentsByUserId(@PathVariable Long userId) { + List comments = commentService.getCommentsByUserId(userId); + return ResponseEntity.ok(comments); + } + + @PutMapping("/{commentId}") + public ResponseEntity updateComment(@PathVariable Long commentId, @RequestBody CommentReq commentReq) { + CommentRes updatedComment = commentService.updateComment(commentId, commentReq.getContent()); + return ResponseEntity.ok(updatedComment); + } + + @DeleteMapping("/{commentId}") + public ResponseEntity deleteComment(@PathVariable Long commentId) { + commentService.deleteComment(commentId); + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/com/example/blog/domain/comment/domain/Comment.java b/src/main/java/com/example/blog/domain/comment/domain/Comment.java new file mode 100644 index 0000000..7a4375d --- /dev/null +++ b/src/main/java/com/example/blog/domain/comment/domain/Comment.java @@ -0,0 +1,41 @@ +package com.example.blog.domain.comment.domain; + +import com.example.blog.domain.post.domain.Post; +import com.example.blog.domain.user.domain.User; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +public class Comment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "post_id") + private Post post; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id") + private User user; + + @Column(nullable = false) + private String content; + + @Builder + public Comment(Post post, User user, String content) { + this.post = post; + this.user = user; + this.content = content; + } + + public void update(String content) { + this.content = content; + } +} diff --git a/src/main/java/com/example/blog/domain/comment/dto/CommentReq.java b/src/main/java/com/example/blog/domain/comment/dto/CommentReq.java new file mode 100644 index 0000000..c8efbb8 --- /dev/null +++ b/src/main/java/com/example/blog/domain/comment/dto/CommentReq.java @@ -0,0 +1,12 @@ +package com.example.blog.domain.comment.dto; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +public class CommentReq { + private Long postId; + private Long userId; + private String content; +} diff --git a/src/main/java/com/example/blog/domain/comment/dto/CommentRes.java b/src/main/java/com/example/blog/domain/comment/dto/CommentRes.java new file mode 100644 index 0000000..afcdaea --- /dev/null +++ b/src/main/java/com/example/blog/domain/comment/dto/CommentRes.java @@ -0,0 +1,23 @@ +package com.example.blog.domain.comment.dto; + +import com.example.blog.domain.comment.domain.Comment; +import lombok.Getter; + +@Getter +public class CommentRes { + private Long id; + private String content; + private String username; + private Long postId; + + public CommentRes(Comment comment) { + this.id = comment.getId(); + this.content = comment.getContent(); + this.username = comment.getUser().getUsername(); + this.postId = comment.getPost().getId(); + } + + public static CommentRes fromEntity(Comment comment) { + return new CommentRes(comment); + } +} diff --git a/src/main/java/com/example/blog/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/blog/domain/comment/repository/CommentRepository.java new file mode 100644 index 0000000..7342cb9 --- /dev/null +++ b/src/main/java/com/example/blog/domain/comment/repository/CommentRepository.java @@ -0,0 +1,11 @@ +package com.example.blog.domain.comment.repository; + +import com.example.blog.domain.comment.domain.Comment; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface CommentRepository extends JpaRepository { + List findByPostId(Long postId); + List findByUserId(Long userId); +} diff --git a/src/main/java/com/example/blog/domain/comment/service/CommentService.java b/src/main/java/com/example/blog/domain/comment/service/CommentService.java new file mode 100644 index 0000000..1dac7c9 --- /dev/null +++ b/src/main/java/com/example/blog/domain/comment/service/CommentService.java @@ -0,0 +1,62 @@ +package com.example.blog.domain.comment.service; + +import com.example.blog.domain.comment.domain.Comment; +import com.example.blog.domain.comment.dto.CommentReq; +import com.example.blog.domain.comment.dto.CommentRes; +import com.example.blog.domain.comment.repository.CommentRepository; +import com.example.blog.domain.post.domain.Post; +import com.example.blog.domain.post.repository.PostRepository; +import com.example.blog.domain.user.domain.User; +import com.example.blog.domain.user.repository.UserRepository; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class CommentService { + + private final CommentRepository commentRepository; + private final PostRepository postRepository; + private final UserRepository userRepository; + + public CommentService(CommentRepository commentRepository, PostRepository postRepository, UserRepository userRepository) { + this.commentRepository = commentRepository; + this.postRepository = postRepository; + this.userRepository = userRepository; + } + + @Transactional + public CommentRes createComment(CommentReq commentReq) { + Post post = postRepository.findById(commentReq.getPostId()).orElseThrow(() -> new IllegalArgumentException("Invalid post ID")); + User user = userRepository.findById(commentReq.getUserId()).orElseThrow(() -> new IllegalArgumentException("Invalid user ID")); + Comment comment = Comment.builder().post(post).user(user).content(commentReq.getContent()).build(); + return CommentRes.fromEntity(commentRepository.save(comment)); + } + + @Transactional(readOnly = true) + public List getCommentsByPostId(Long postId) { + List comments = commentRepository.findByPostId(postId); + return comments.stream().map(CommentRes::fromEntity).collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public List getCommentsByUserId(Long userId) { + List comments = commentRepository.findByUserId(userId); + return comments.stream().map(CommentRes::fromEntity).collect(Collectors.toList()); + } + + @Transactional + public CommentRes updateComment(Long commentId, String content) { + Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new IllegalArgumentException("Invalid comment ID")); + comment.update(content); + return CommentRes.fromEntity(commentRepository.save(comment)); + } + + @Transactional + public void deleteComment(Long commentId) { + Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new IllegalArgumentException("Invalid comment ID")); + commentRepository.delete(comment); + } +} From e895e0bfa5625f6afde13a3f6f9e91e1e7190f5b Mon Sep 17 00:00:00 2001 From: icegosimperson Date: Wed, 29 May 2024 23:36:33 +0900 Subject: [PATCH 10/10] =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=A2=8B=EC=95=84?= =?UTF-8?q?=EC=9A=94,=20=EC=B7=A8=EC=86=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/Controller/CommentController.java | 15 +++++++++ .../blog/domain/comment/domain/Comment.java | 33 +++++++++++++++++++ .../comment/service/CommentService.java | 24 ++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/src/main/java/com/example/blog/domain/comment/Controller/CommentController.java b/src/main/java/com/example/blog/domain/comment/Controller/CommentController.java index a33d838..0d1ec80 100644 --- a/src/main/java/com/example/blog/domain/comment/Controller/CommentController.java +++ b/src/main/java/com/example/blog/domain/comment/Controller/CommentController.java @@ -48,4 +48,19 @@ public ResponseEntity deleteComment(@PathVariable Long commentId) { commentService.deleteComment(commentId); return ResponseEntity.noContent().build(); } + + // 댓글 좋아요 + @PostMapping("/{commentId}/like") + public ResponseEntity likeComment(@PathVariable Long commentId, @RequestParam Long userId) { + commentService.likeComment(commentId, userId); + return ResponseEntity.ok().build(); + } + + // 댓글 좋아요 취소 + @PostMapping("/{commentId}/unlike") + public ResponseEntity unlikeComment(@PathVariable Long commentId, @RequestParam Long userId) { + commentService.unlikeComment(commentId, userId); + return ResponseEntity.ok().build(); + } + } diff --git a/src/main/java/com/example/blog/domain/comment/domain/Comment.java b/src/main/java/com/example/blog/domain/comment/domain/Comment.java index 7a4375d..046d814 100644 --- a/src/main/java/com/example/blog/domain/comment/domain/Comment.java +++ b/src/main/java/com/example/blog/domain/comment/domain/Comment.java @@ -8,6 +8,9 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.util.HashSet; +import java.util.Set; + @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @Getter @@ -28,6 +31,18 @@ public class Comment { @Column(nullable = false) private String content; + // 댓글 좋아요 기능 추가 + @Column(columnDefinition = "integer default 0", nullable = false) + private int likes; + + @ManyToMany + @JoinTable( + name = "comment_likes", + joinColumns = @JoinColumn(name = "comment_id"), + inverseJoinColumns = @JoinColumn(name = "user_id") + ) + private Set likedUsers = new HashSet<>(); + @Builder public Comment(Post post, User user, String content) { this.post = post; @@ -38,4 +53,22 @@ public Comment(Post post, User user, String content) { public void update(String content) { this.content = content; } + + + // 댓글 좋아요 + public void like(User user) { + if (likedUsers.add(user)) { + this.likes++; + } + } + + // 댓글 좋아요 취소 + public void unlike(User user) { + if (likedUsers.remove(user)) { + this.likes--; + } + } + + + } diff --git a/src/main/java/com/example/blog/domain/comment/service/CommentService.java b/src/main/java/com/example/blog/domain/comment/service/CommentService.java index 1dac7c9..413d4ed 100644 --- a/src/main/java/com/example/blog/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/blog/domain/comment/service/CommentService.java @@ -59,4 +59,28 @@ public void deleteComment(Long commentId) { Comment comment = commentRepository.findById(commentId).orElseThrow(() -> new IllegalArgumentException("Invalid comment ID")); commentRepository.delete(comment); } + + // 댓글 좋아요 + @Transactional + public void likeComment(Long commentId, Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("해당 유저 없음")); + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() -> new IllegalArgumentException("해당 댓글 없음")); + + comment.like(user); + commentRepository.save(comment); + } + + // 댓글 좋아요 취소 + @Transactional + public void unlikeComment(Long commentId, Long userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("해당 유저 없음")); + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() -> new IllegalArgumentException("해당 댓글 없음")); + + comment.unlike(user); + commentRepository.save(comment); + } }