-
Notifications
You must be signed in to change notification settings - Fork 12
Feat/week 3 #27
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
Open
junyi04
wants to merge
24
commits into
ApptiveDev:강준이
Choose a base branch
from
junyi04:feat/week-3
base: 강준이
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Feat/week 3 #27
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
098a8c2
Update README.md
junyi04 5200ce0
Merge branch 'ApptiveDev:main' into main
junyi04 3d54a1f
chore: add JPA and Lombok dependencies
junyi04 2ded9e9
feat(docs): add PostEntity and explanation
junyi04 2592017
feat(docs): add PostRepository and explanation
junyi04 a869462
feat(docs): add PostService and explanation
junyi04 9346fa9
feat(docs): add PostController and explanation
junyi04 e227126
feat: create templates/list.html (/posts/new)
junyi04 96b956f
feat: create templates/form.html (/posts)
junyi04 845bb2d
feat: create templates/detail.html (/posts/{id}/delete)
junyi04 eb68811
chore: update H2 database and JPA configuration
junyi04 8000aaf
fix: correct typo in list.html&detail.html th name
junyi04 7437ff5
feat: add createdAt, updatedAt fields and connect CRUD
junyi04 bbc2f3d
feat: implement edit feature with update API and edit.html
junyi04 cc40f17
feat: 댓글 기능 로직 구현 완료
junyi04 f955163
feat: detail 화면에 댓글 기능 추가
junyi04 a06835e
refactor: Entity를 DTO 쓰는 방향으로 수정
junyi04 f090e61
feat: week-2 브랜치
junyi04 6bb0f9d
feat: MemberEntity 생성 및 연관관계 추가
junyi04 7fff80a
feat: MemberService 비지니스 로직 추가
junyi04 c2cd66e
feat: 좋아요 기능 생성 및 연결
junyi04 5bef8a8
feat: member 전체 조회 기능 추가
junyi04 fed4d15
feat: 멤버 목록 및 게시글 목록 연결 완료
junyi04 eeaf7d7
feat: week3 과제
junyi04 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,3 @@ | ||
| # backend-study-sns | ||
|
|
||
| 강준이 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,4 +10,4 @@ public static void main(String[] args) { | |
| SpringApplication.run(DevSnsApplication.class, args); | ||
| } | ||
|
|
||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package com.example.devSns.config; | ||
|
|
||
| import com.example.devSns.entity.MemberEntity; | ||
| import com.example.devSns.repository.MemberRepository; | ||
| import jakarta.annotation.PostConstruct; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| @Component | ||
| public class DataInit { | ||
|
|
||
| private final MemberRepository memberRepository; | ||
|
|
||
| public DataInit(MemberRepository memberRepository) { | ||
| this.memberRepository = memberRepository; | ||
| } | ||
|
|
||
| @PostConstruct | ||
| public void init() { | ||
| // Member가 없으면 테스트용 계정 자동 생성 | ||
| if (memberRepository.count() == 0) { | ||
| memberRepository.save(MemberEntity.create("tester", "tester@example.com")); | ||
| } | ||
| } | ||
| } |
31 changes: 31 additions & 0 deletions
31
src/main/java/com/example/devSns/controller/CommentController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package com.example.devSns.controller; | ||
|
|
||
| import com.example.devSns.dto.CommentRequest; | ||
| import com.example.devSns.entity.CommentEntity; | ||
| import com.example.devSns.service.CommentService; | ||
| import org.springframework.stereotype.Controller; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| @Controller | ||
| @RequestMapping("/comments") | ||
| public class CommentController { | ||
| private final CommentService commentService; | ||
|
|
||
| public CommentController(CommentService commentService) { | ||
| this.commentService = commentService; | ||
| } | ||
|
|
||
| // 댓글 생성 | ||
| @PostMapping("/{postId}") | ||
| public String createComment(@PathVariable Long postId, @ModelAttribute CommentRequest request) { | ||
| commentService.createComment(postId, request); | ||
| return "redirect:/posts/" + postId; | ||
| } | ||
|
|
||
| // 댓글 삭제 | ||
| @PostMapping("/{commentId}/delete") | ||
| public String deleteComment(@PathVariable Long commentId, @RequestParam Long postId) { | ||
| commentService.deleteComment(commentId); | ||
| return "redirect:/posts/" + postId; | ||
| } | ||
| } | ||
61 changes: 61 additions & 0 deletions
61
src/main/java/com/example/devSns/controller/MemberController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| package com.example.devSns.controller; | ||
|
|
||
| import com.example.devSns.entity.MemberEntity; | ||
| import com.example.devSns.service.MemberService; | ||
| import org.springframework.stereotype.Controller; | ||
| import org.springframework.ui.Model; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| @Controller | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @RestController와 @controller의 차이는 무엇일까요? |
||
| @RequestMapping("/members") | ||
| public class MemberController { | ||
|
|
||
| private final MemberService memberService; | ||
|
|
||
| public MemberController(MemberService memberService) { | ||
| this.memberService = memberService; | ||
| } | ||
|
|
||
| // 전체 멤버 목록 | ||
| @GetMapping | ||
| public String list(Model model) { | ||
| model.addAttribute("members", memberService.getAllMembers()); | ||
| return "member-list"; | ||
| } | ||
|
Comment on lines
+21
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 메소드에서 model은 어떤 역할을 할까요? |
||
|
|
||
| // 멤버 상세 페이지 | ||
| @GetMapping("/{id}") | ||
| public String detail(@PathVariable Long id, Model model) { | ||
| MemberEntity member = memberService.getMember(id); | ||
|
|
||
| model.addAttribute("member", member); | ||
| model.addAttribute("posts", member.getPosts()); | ||
| model.addAttribute("comments", member.getComments()); | ||
|
|
||
| return "member-detail"; | ||
| } | ||
|
|
||
| // 멤버 생성 | ||
| @GetMapping("/new") | ||
| public String newForm() { | ||
| return "member-form"; | ||
| } | ||
|
|
||
| // 멤버 생성 처리 | ||
| @PostMapping | ||
| public String create(@RequestParam String username, | ||
| @RequestParam String email) { | ||
|
|
||
| memberService.createMember(username, email); | ||
| return "redirect:/members"; | ||
| } | ||
|
|
||
| // 멤버 검색 | ||
| // /members/search?keyword=abc | ||
| @GetMapping("/search") | ||
| public String search(@RequestParam String keyword, Model model) { | ||
| model.addAttribute("members", memberService.search(keyword)); | ||
| model.addAttribute("keyword", keyword); | ||
| return "member-search"; | ||
| } | ||
| } | ||
95 changes: 95 additions & 0 deletions
95
src/main/java/com/example/devSns/controller/PostController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,95 @@ | ||
| package com.example.devSns.controller; | ||
|
|
||
| import com.example.devSns.entity.MemberEntity; | ||
| import com.example.devSns.entity.PostEntity; | ||
| import com.example.devSns.repository.LikeRepository; | ||
| import com.example.devSns.repository.MemberRepository; | ||
| import com.example.devSns.service.PostService; | ||
| import org.springframework.stereotype.Controller; | ||
| import org.springframework.ui.Model; | ||
| import org.springframework.web.bind.annotation.*; | ||
|
|
||
| @Controller | ||
| @RequestMapping("/posts") | ||
| public class PostController { | ||
|
|
||
| private final PostService postService; | ||
| private final LikeRepository likeRepository; | ||
| private final MemberRepository memberRepository; | ||
|
|
||
| // 생성자 | ||
| public PostController(PostService postService, | ||
| LikeRepository likeRepository, | ||
| MemberRepository memberRepository) { | ||
| this.postService = postService; | ||
| this.likeRepository = likeRepository; | ||
| this.memberRepository = memberRepository; | ||
| } | ||
|
|
||
| // HTTP GET /posts | ||
| @GetMapping | ||
| public String list(Model model) { | ||
| model.addAttribute("posts", postService.getAllPosts()); | ||
| return "list"; | ||
| } | ||
|
|
||
| // HTTP GET /posts/new | ||
| @GetMapping("/new") | ||
| public String form(Model model) { | ||
| model.addAttribute("post", new PostEntity()); | ||
| return "form"; | ||
| } | ||
|
|
||
| // HTTP POST /posts | ||
| @PostMapping | ||
| public String create(@ModelAttribute PostEntity postEntity) { | ||
| postService.createPost(postEntity); | ||
| return "redirect:/posts"; // 글 생성 후 돌아올 주소 | ||
| } | ||
|
|
||
| // HTTP GET /posts/{id} | ||
| @GetMapping("/{id}") | ||
| public String detail(@PathVariable Long id, Model model) { | ||
| PostEntity postEntity = postService.getPost(id); | ||
|
|
||
| // 임시 멤버 아이디 | ||
| Long memberId = 1L; | ||
| MemberEntity member = memberRepository.findById(memberId).orElseThrow(); | ||
|
|
||
| // 좋아요 수 | ||
| int likeCount = likeRepository.countByPostId(id); | ||
|
|
||
| // 좋아요 여부 | ||
| boolean liked = likeRepository | ||
| .findByMemberAndPost(member, postEntity) | ||
| .isPresent(); | ||
|
|
||
| model.addAttribute("post", postEntity); | ||
| model.addAttribute("likeCount", likeCount); | ||
| model.addAttribute("liked", liked); | ||
| model.addAttribute("memberId", memberId); | ||
| return "detail"; | ||
| } | ||
|
|
||
| // HTTP GET /posts/{id}/edit | ||
| @GetMapping("/{id}/edit") | ||
| public String editForm(@PathVariable Long id, Model model) { | ||
| PostEntity postEntity = postService.getPost(id); | ||
| model.addAttribute("post", postEntity); | ||
| return "edit"; | ||
| } | ||
|
|
||
| // HTTP POST /posts/{id}/update | ||
| @PostMapping("/{id}/update") | ||
| public String update(@PathVariable Long id, @ModelAttribute PostEntity updatedPost) { | ||
| postService.updatePost(id, updatedPost); | ||
| return "redirect:/posts/" + id; // 수정 후 돌아올 주소 | ||
| } | ||
|
|
||
| // HTTP POST /posts/{id}/delete | ||
| @PostMapping("/{id}/delete") | ||
| public String delete(@PathVariable Long id) { | ||
| postService.deletePost(id); | ||
| return "redirect:/posts"; // 삭제 후 돌아올 주소 | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| 요청을 받는 곳 | ||
|
|
||
| PostController | ||
| Spring MVC 패턴에서 Controller 계층 역할 | ||
| - 사용자의 요청을 받고 Service 계층을 호출해서 처리한 후, 결과를 View에 전달 | ||
|
|
||
| @Controller | ||
| 이 클래스는 웹 요청을 처리하는 컨트롤러임을 알려줌 | ||
| - Model에 데이터를 담아 템플릿에 전달 (templates/list.html) | ||
|
|
||
| @RequestMapping | ||
| 클래스 전체의 기본 URL 경로를 지정 | ||
| - 이 컨트롤러 안의 모든 요청은 /posts로 시작 | ||
| - /posts (게시글 목록), /posts/new (새 글 작성 폼) | ||
|
|
||
| @GetMapping, @PostMapping | ||
| HTTP 메서드 별 라우팅 | ||
|
|
||
| @PathVariable, @ModelAttribute | ||
| URL 경로 변수 바인딩 / 폼 데이터를 객체에 바인딩 | ||
|
|
||
| @RestController | ||
| 문자열 반환이 뷰 이름이 아닌 JSON | ||
| - REST API 만들 때 사용 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| import lombok.Getter; | ||
| import lombok.Setter; | ||
|
|
||
| @Getter | ||
| @Setter | ||
| public class CommentRequest { | ||
| private String username; | ||
| private String content; | ||
| } | ||
|
|
||
| // Controller는 CommentEntity를 직접 받지 않고 CommentRequest만 받게 됨 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.example.devSns.dto; | ||
|
|
||
| import lombok.Getter; | ||
|
|
||
| @Getter | ||
| public class CommentResponse { | ||
| private final Long id; | ||
| private final String username; | ||
| private final String content; | ||
| private final String createdAt; | ||
|
|
||
| public CommentResponse(Long id, String username, String content, String createdAt) { | ||
| this.id = id; | ||
| this.username = username; | ||
| this.content = content; | ||
| this.createdAt = createdAt; | ||
| } | ||
| } | ||
|
|
||
| // Entity를 외부로 그대로 내보내지 않고 DTO로 가공해서 반환 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| 계층간 데이터 교환에 사용 | ||
| - Entity 클래스를 보호 | ||
| - 필요한 데이터만 선택적으로 담을 수 있음 | ||
|
|
||
| 분리해서 사용하는 이유 | ||
| - Entity 객체의 변경을 피하기 위함 | ||
| - 클라이언트와 통신하는 ResponseDTO나 RequestDTO는 요구사항에 따라 자주 변경 | ||
| - 어떤 요청에서는 특정 값이 추가되거나 없을 수 있어서 분리해서 관리 |
57 changes: 57 additions & 0 deletions
57
src/main/java/com/example/devSns/entity/CommentEntity.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| package com.example.devSns.entity; | ||
|
|
||
| import jakarta.persistence.*; | ||
| import lombok.Getter; | ||
|
|
||
| import java.time.LocalDateTime; | ||
|
|
||
| // DTO를 사용하고 Setter를 삭제 (안전) | ||
| @Entity | ||
| @Getter | ||
| public class CommentEntity { | ||
| @Id | ||
| @GeneratedValue(strategy = GenerationType.IDENTITY) | ||
| private Long id; | ||
|
|
||
| private String content; | ||
| private String username; | ||
|
|
||
| private LocalDateTime createdAt; | ||
| private LocalDateTime updatedAt; | ||
|
|
||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "member_id") | ||
| private MemberEntity member; | ||
|
|
||
| // Post와 N:1 관계 | ||
| @ManyToOne(fetch = FetchType.LAZY) | ||
| @JoinColumn(name = "post_id") | ||
| private PostEntity postEntity; | ||
|
|
||
| // JPA 기본 생성자 | ||
| protected CommentEntity() {} | ||
|
|
||
| // 정적 생성 메서드 > 엔터티 변경은 오직 메서드로 | ||
| public static CommentEntity create(PostEntity postEntity, String username, String content) { | ||
| CommentEntity comment = new CommentEntity(); | ||
| comment.postEntity = postEntity; | ||
| comment.username = username; | ||
| comment.content = content; | ||
| return comment; | ||
| } | ||
|
|
||
| public void updateContent(String content) { | ||
| this.content = content; | ||
| } | ||
|
|
||
| @PrePersist | ||
| public void onCreate() { | ||
| this.createdAt = LocalDateTime.now(); | ||
| this.updatedAt = LocalDateTime.now(); | ||
| } | ||
|
|
||
| @PreUpdate | ||
| public void onUpdate() { | ||
| this.updatedAt = LocalDateTime.now(); | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"redirect:/posts/" 와 같은 문자열들은 상수로 만들어 사용하시면, 추후에 링크가 변경되더라도 더 효율적으로 코드를 수정할 수 있을거 같아요