Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[8주차]Cow_mvc_practice(0711kc) #6

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
fc45d39
feat : 게시글 등록 기능 추가
invalid-email-address May 14, 2024
e9272f2
feat : 회원 삭제 기능 추가
invalid-email-address May 14, 2024
6bac0b2
refactor : 게시글 생성 URL 형식 수정
invalid-email-address May 15, 2024
033ebb9
refactor : 게시글 생성 URL 형식 수정
invalid-email-address May 15, 2024
74decac
feat : 회원 수정 기능 추가
invalid-email-address May 15, 2024
f5ff27b
refactor : Post 생성 시 작성 일자 임의 부여 제한
invalid-email-address May 17, 2024
c3ace06
refactor : 리다이렉션 삭제, URL 형식 변경
invalid-email-address May 18, 2024
514a6fc
style : 코드 정리 및 사용하지 않는 메서드 삭제
invalid-email-address May 18, 2024
9b6a8b0
feat : EntityNotFoundException의 Handler 추가
invalid-email-address May 18, 2024
6189118
feat : 게시글 삭제 기능 추가
invalid-email-address May 18, 2024
9a01e3b
style : 코드 컨벤션 수정
invalid-email-address May 21, 2024
ec67ae0
style : 코드 컨벤션 수정
invalid-email-address May 21, 2024
5be2e3b
style : 코드 컨벤션 수정
invalid-email-address May 21, 2024
d8ea709
style : 코드 컨벤션 수정
invalid-email-address May 21, 2024
b662d27
feat : 프로필 이미지 s3 적용
invalid-email-address Jun 20, 2024
3682a4d
feat : swagger 문서화 적용
invalid-email-address Jun 21, 2024
2ba09f0
refactor : 응답 DTO ResponseEntity로 변경
invalid-email-address Jun 22, 2024
69c840c
test : 회원 테스트 코드 추가
invalid-email-address Jun 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.cow.cow_mvc_practice.comment.entity;

import com.cow.cow_mvc_practice.member.entity.Member;
import com.cow.cow_mvc_practice.post.entity.Post;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "comment_id")
private Long id;

private String content;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "member_id")
private Member member;

@Builder
private Comment(final Long id, final String content) {
this.id = id;
this.content = content;
}

public static Comment from(String content) {
return Comment.builder()
.content(content)
.build();
}

public static Comment of(Long id, String content) {
return Comment.builder()
.id(id)
.content(content)
.build();
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment를 정적팩토리 메서드로 사용하신 점은 너무 잘하신거 같아요!! 하지만 id를 직접 받아서 Comment의 id에 삽입할 일이 필요한가? 를 고민해보셔야합니다!
만약 저 메서드가 있다면 같이 협업하는 개발자가 있다고 할 때 "어? id를 수정할 수 있고, 해도 괜찮은거구나?"라는 오해를 일으킬 수 있습니다!


}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EOL 참고해주세요!

Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@

import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest;
import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse;
import com.cow.cow_mvc_practice.member.entity.Member;
import com.cow.cow_mvc_practice.member.service.MemberService;

import lombok.RequiredArgsConstructor;

@RestController
@Controller
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controller 어노테이션으로 바꾼 이유가 있으신가요??

@RequestMapping("/member")
@RequiredArgsConstructor
public class MemberController {
Expand All @@ -40,23 +41,32 @@ public class MemberController {

/* MemberResponse dto 적용 */
@PostMapping("/new")
public MemberResponse create(@RequestBody final MemberRequest memberRequest) {
public @ResponseBody MemberResponse create(@RequestBody final MemberRequest memberRequest) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RestController을 사용하게되면 ResponseBody를 포함하고 있어 각 메소드마다 안 붙혀도 적용됩니다!

return memberService.join(memberRequest);
}

@GetMapping("/{memberId}")
public MemberResponse findMember(@PathVariable final Long memberId) {
public @ResponseBody MemberResponse findMember(@PathVariable final Long memberId) {
return memberService.findOne(memberId);
}

@DeleteMapping("/{memberId}/delete")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleteMaping을 통해 http 메소드 중 delete를 사용 중입니다. url에 한번 더 delete를 언급하는 것은 rest 스럽지 못 한 거 같습니다!

https://velog.io/@yewo2nn16/Spring-%EC%98%88%EC%A0%9C%EC%99%80-%ED%95%A8%EA%BB%98-REST-API-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90

public String delete(@PathVariable final Long memberId) {
return memberService.delete(memberId);
}

@GetMapping()
public MemberResponse findMemberQuery(@RequestParam final Long memberId) {
public @ResponseBody MemberResponse findMemberQuery(@RequestParam("id") final Long memberId) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

같은 행위를 하는 두 개의 메소드가 보이는데 따로 이유가 있으신가요? 또 메소드 명이 의미하는 바가 무엇인가요?

return memberService.findOne(memberId);
}

@GetMapping("all")
public List<MemberResponse> findMembers() {
@GetMapping("/all")
public @ResponseBody List<MemberResponse> findMembers() {
return memberService.findAll();
}
}

@RequestMapping("/{memberId}/post/{path}")
public String redirectToPost(@PathVariable final Long memberId, @PathVariable final String path) {
return "forward:/post/"+memberId+"/"+path;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@AllArgsConstructor
Expand All @@ -19,6 +18,6 @@ private MemberRequest(final String name) {
}

public static Member toEntity(String name) {
return Member.of(name);
return Member.from(name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

builder를 이용해서 객체를 해당 클래스에서 리턴해주는 것이 의미있어 보입니다

}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.cow.cow_mvc_practice.member.controller.dto.request;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

생상자 생성 이유가 있으신가요?

public class UpdateMemberRequest {

private String name;
final String name;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,31 @@

import com.cow.cow_mvc_practice.member.entity.Member;

import java.util.ArrayList;
import java.util.List;
import lombok.Builder;
import lombok.Getter;

@Getter
public class MemberResponse {
private final Long id;
private final String name;
private final List<String> posts;

@Builder
private MemberResponse(final Long id, final String name) {
private MemberResponse(final Long id, final String name, final List<String> posts) {
this.id = id;
this.name = name;
this.posts = posts;
}

public static MemberResponse of(final Member member) {
public static MemberResponse from(final Member member) {
List<String> posts = new ArrayList<>();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

새로 list를 생성하면 null이 아닌가요?

member.getPosts().forEach((p) -> posts.add(p.getTitle()));
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Post를 title만 받아서 MemberResponse의 필드값으로 가지고 싶으셨던거 같아요!
그럼 필드값을 PostResponse와 같은 dto로 가지도록 변경해보시는걸 추천드립니다.

return MemberResponse.builder()
.id(member.getId())
.name(member.getName())
.posts(posts)
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.cow.cow_mvc_practice.member.entity;

import com.cow.cow_mvc_practice.comment.entity.Comment;
import java.util.ArrayList;
import java.util.List;

Expand All @@ -8,7 +9,6 @@
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand All @@ -33,19 +33,22 @@ public class Member {
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private final List<Post> posts = new ArrayList<>();

@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private final List<Comment> comments = new ArrayList<>();

@Builder
private Member(final Long id, final String name) {
this.id = id;
this.name = name;
}

public static Member of(String name) {
public static Member from(String name) {
return Member.builder()
.name(name)
.build();
}

public static Member from(Long id, String name) {
public static Member of(Long id, String name) {
return Member.builder()
.id(id)
.name(name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ public interface MemberRepository {
Optional<Member> findById(Long memberId);

Optional<List<Member>> findAll();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class MemberRepositoryImpl implements MemberRepository {
/**
* 원래라면 HashMap이 아닌, concurrentHashMap이 적합함. HashMap은 멀티 쓰레드 환경에서 사용할 수 없기 때문.(동시성 이슈)
*/
private static Map<Long, Member> store = new HashMap<>();
private static final Map<Long, Member> store = new HashMap<>();


@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
package com.cow.cow_mvc_practice.member.service;

import java.util.ArrayList;
import java.util.List;

import com.cow.cow_mvc_practice.member.controller.dto.request.MemberRequest;
import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse;
import com.cow.cow_mvc_practice.member.entity.Member;

public interface MemberService {

/* 기본 */
// void join(MemberRequest memberRequest);
// Member findOne(Long memberId);


/* MemberResponse dto 적용 */
MemberResponse findOne(Long memberId);
MemberResponse join(MemberRequest memberRequest);
List<MemberResponse> findAll();
String delete(Long memberId);
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.cow.cow_mvc_practice.member.service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

Expand All @@ -11,7 +10,6 @@
import com.cow.cow_mvc_practice.member.controller.dto.response.MemberResponse;
import com.cow.cow_mvc_practice.member.entity.Member;
import com.cow.cow_mvc_practice.member.repository.MemberJPARepository;
import com.cow.cow_mvc_practice.member.repository.MemberRepository;

import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -41,24 +39,30 @@ public class MemberServiceImpl implements MemberService {
/* MemberResponse dto 적용 */
@Override
public MemberResponse join(MemberRequest memberRequest) {
Member member = Member.of(memberRequest.getName());
Member member = Member.from(memberRequest.getName());
memberRepository.save(member);
return MemberResponse.of(member);
return MemberResponse.from(member);
}

@Transactional(readOnly = true)
@Override
public MemberResponse findOne(Long memberId) {
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new EntityNotFoundException("[Error] 사용자를 찾을 수 없습니다."));
return MemberResponse.of(member);
return MemberResponse.from(member);
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@transactional(readOnly = true)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 어떤 피드백인가요??

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 까먹었는데 왜 저렇게 썼을까요,,,호호

@Override
public List<MemberResponse> findAll() {
List<Member> members = memberRepository.findAll();
return members.stream()
.map(MemberResponse::of)
.map(MemberResponse::from)
.collect(Collectors.toList());
}

@Override
public String delete(Long memberId) {
memberRepository.deleteById(memberId);
return "삭제에 성공하였습니다.";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ResponseEntity 키워드에 대해 알아보시고, 해당 상태 코드에 대해 공부하는 것도 좋아보입니다!~

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.cow.cow_mvc_practice.post.controller;

import com.cow.cow_mvc_practice.post.controller.dto.request.PostRequest;
import com.cow.cow_mvc_practice.post.controller.dto.response.PostResponse;
import com.cow.cow_mvc_practice.post.service.PostService;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/post")
@RequiredArgsConstructor
public class PostController {

private final PostService postService;

@PostMapping("/members/{memberId}/new")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restful api url에 대한 고민해보세요!

public PostResponse create(@PathVariable final Long memberId ,@RequestBody final PostRequest postRequest) {
return postService.join(memberId, postRequest);
}

@GetMapping("/{postId}")
public PostResponse findMember(@PathVariable final Long postId) {
0711kc marked this conversation as resolved.
Show resolved Hide resolved
return postService.findOne(postId);
}

@GetMapping()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

url에 대한 고민이 필요합니다

public PostResponse findPostQuery(@RequestParam("id") final Long postId) {
return postService.findOne(postId);
}

@GetMapping("all")
public List<PostResponse> findPosts() {
return postService.findAll();
}

@PostMapping("/{memberId}/new")
public PostResponse create2(@PathVariable final Long memberId, @RequestBody final PostRequest postRequest) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

create2는 어떤 의미인가요??

return postService.join(memberId, postRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.cow.cow_mvc_practice.post.controller.dto.request;

import java.time.LocalDateTime;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import org.springframework.format.annotation.DateTimeFormat;

@Getter
@AllArgsConstructor
public class PostRequest {
Long id;
final String title;
final String content;
@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
final LocalDateTime date;
0711kc marked this conversation as resolved.
Show resolved Hide resolved
0711kc marked this conversation as resolved.
Show resolved Hide resolved

public PostRequest() {
this.title = "";
this.content = "";
this.date = LocalDateTime.now();
}

@Builder
private PostRequest(final String title, final String content, final LocalDateTime date) {
this.title = title;
this.content = content;
this.date = date;
}
}
Loading