
JPA로 개발을 하게된다면 필연적으로 N+1문제를 겪을 수 밖에 없다고 생각합니다. 저같은 경우 게시판 프로젝트를 진행하면서 JPA를 학습하면서 말로만 듣던 N+1문제를 정말 많이 만나게 되었는데 이를 해결하면서 공부한 내용을 바탕으로 N+1 문제상황을 직접 예제코드로 만들어 해결하는 과정을 포스팅해보도록 하겠습니다. N+1문제상황 만들기 이해를 쉽게하기 위하여 게시판 서비스의 게시글 엔티티인 Post와 회원 엔티티인 User를 다음과 같이 간단하게 작성해보겠습니다. - Post package com.hw.study.entity; import java.util.List; import lombok.*; import javax.persistence.*; @Entity @NoArgsConstructor(acc..
![사이드 프로젝트 [국비의 모든것] - 게시글 삭제 구현](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQi2y6%2FbtsjILvTJVY%2F2j081SXcxxtEkpNTOpZwK1%2Fimg.png)
목차요구사항 분석구현테스트 이번에는 비교적 간단한 게시글 삭제 기능을 개발하여보겠습니다. 위의 게시글 상세보기 화면에서, 빨간색 동그라미를 친 삭제하기 버튼을 눌러봅니다. 위와 같은 Confirm 창이 뜨고, 확인을 누른다면 게시글 삭제 기능을 수행합니다.요구사항 분석게시글 상세보기 페이지에서, 현재 로그인된 사용자와 일치하는 사용자가 게시글 삭제를 요청한다면 게시글을 삭제합니다.게시글 삭제가 완료되면, 삭제된 게시글의 카테고리에 해당하는 게시물 목록 페이지로 이동합니다. 구현- BoardController.java@Slf4j@RestController@RequiredArgsConstructor@RequestMapping("/api/v1/boards")public class BoardApiControll..
![사이드 프로젝트 [국비의 모든것] - 게시글 작성 구현](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnwxCl%2FbtsjGnCLhJz%2FHik2zZnE1g0YnwBk8TPhek%2Fimg.png)
목차UI요구사항 분석기능 구현 여느 커뮤니티 사이트에 있는 필수 기능인 게시글 작성 기능을 개발해보도록 하겠습니다.UI - BoardController.java/** 커뮤니티 작성 폼 */@GetMapping("/community/new")public String boardForm(@ModelAttribute CommunityFormDto form) { return "board/community/communityForm.tiles1";}먼저 /boards/community/new 로 Get 요청시, communityForm.jsp 를 서버사이드 렌더링합니다. 렌더링된 화면은 다음과 같습니다. 요구사항 분석위의 UI를 토대로 요구사항을 정의해보겠습니다.글 작성한 뒤, 간단하게 클라이언트에서 유효성 ..
![사이드 프로젝트 [국비의 모든것] - 게시글 추천, 댓글 추천 기능 구현](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbte4a9%2FbtsjH0Nf1h9%2FEL39IkoCs75zgU9mkKnLIK%2Fimg.png)
목차UI/UX요구사항추천서비스 개발결과 쿼리UI/UX 요구사항추천은 게시글 추천, 댓글 추천을 할 수 있습니다.추천을 한 상태에서 한번 더 추천을 누르면(요청을 한다면) 추천을 취소합니다.추천서비스 개발먼저 요청을 처리하는 LikeController를 만들어 다음과 같은 코드를 넣어줍니다. - LikeController.javaprivate final LikeService likeService;/** 게시글에서 추천 클릭시 처리 API */@PostMapping("/board")public BaseResponse boardLike(@RequestParam Long memberId, @RequestParam Long boardId) { String deleteOrInsert = likeService..
목차계층형 댓글 조회계층형 댓글 조회먼저 CommentsRepository에서 findCommentListByBoardId 메소드를 살펴보겠습니다. - CommentsRepository.java@Query("select c from Comments c join fetch c.member left join fetch c.parent where c.board.id = :boardId order by c.parent.id asc nulls first, c.id asc")List findCommentListByBoardId(@Param("boardId") Long boardId);JPQL을 정리해보면,select cfrom Comments cjoin fetch c.memberleft join fetch c.pa..
![사이드 프로젝트 [국비의 모든것] - 페이징 게시글 목록 조회 기능 구현](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlrMI4%2FbtsjbpU7QB2%2F8g9baV8TuhMn7kjwOiMgyK%2Fimg.png)
목차기능 요구사항 분석요구사항 구현 계획계획대로 구현하기기능 요구사항 분석이번에는 게시판 목록 조회 기능을 개발해보겠습니다. 게시판 목록을 조회했을 시 화면을 먼저 살펴보겠습니다.조회하고자 하는 카테고리에 해당하는 게시물 목록을 조회해야 합니다. 이 때 만약 국비학원 카테고리나 교육과정 카테고리일 경우 기본적인 게시물 데이터 + 추가적인 데이터를 조회해야합니다.검색창에 검색어를 입력한다면, 해당 검색어가 포함된 글제목의 글 목록을 보여주어야 합니다.페이징처리가 되어야 합니다.공지사항 카테고리의 필독 공지사항은 모든 게시물 목록 조회 화면에서 조회해야 합니다.최신순, 댓글순, 추천순, 조회순으로 정렬할 수 있어야 합니다.요구사항 구현 계획해당 기능은 게시판 서비스에서 가장 많은 호출이 일어나는 서비스이므로..
목차Member 엔티티 내부에 변경 메소드 만들기FileManager 클래스요청 처리하기 Member 엔티티 내부에 변경 메소드 만들기1편에서 말한 JPA 변경감지를 사용하기 위하여, 엔티티 내부에 변경 메소드를 만들어주도록 하겠습니다.Setter를 통하여 변경감지를 할 수도 있지만, 저는 엔티티에는 Setter를 사용하지 않았습니다. 이유는 엔티티의 필드에 Setter가 있게 된다면 엔티티를 생성하고 저장하기 위하여 값을 주입하는 것인지, 변경감지를 위하여 Setter를 사용하는 것인지 의도를 파악하기 힘들고 어느 부분에서 엔티티의 변경이 일어났는지도 파악하기 힘들기 때문입니다. 반대로 change() 같은 엔티티의 내부 메소드를 사용하게 된다면 메소드 이름을 통하여 개발자의 의도도 직관적으로 파악할 ..
![사이드 프로젝트 [국비의 모든것] - 회원정보 수정 기능 구현 (1)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB5wnR%2Fbtsi3qzC7dr%2FthxfI5TpY56S5tuH5ETkC1%2Fimg.png)
목차기능 요구사항변경감지, merge 어떤걸 사용하지?파일 업로드기능 요구사항이번엔 마이페이지에서 회원정보를 수정할수 있도록 하는 기능을 개발해보겠습니다. 1. 회원은 이름, 닉네임, 프로필이미지, 이메일수신동의 여부 상태를 변경할 수 있습니다.2. 기존 이름, 닉네임, 프로필이미지, 이메일수신동의 여부 상태가 변경되어야만 [저장] 버튼을 누를 수 있습니다.3. 프로필이미지를 변경하지 않는다면 이름, 닉네임, 이메일수신동의 여부 상태에 대해서만 변경을 해주어야 합니다.4. 프로필이미지를 변경한다면 서버의 images 폴더에 변경하고자 하는 이미지 파일을 저장해주고 기존 프로필이미지가 기본이미지인 "user.PNG"가 아니라면, 해당 폴더에서 파일을 삭제해줍니다. 변경감지, merge 어떤걸 사용하지?J..
![사이드 프로젝트 [국비의 모든것] - 패키지 구조 설계하기](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpTedi%2FbtsiO6Po5M2%2FGuR40bkhMOTYJwOaT5yGu1%2Fimg.png)
목차기존 프로젝트 패키지 구조개선된 패키지 구조 기존 프로젝트를 진행할 때 가장 의문점이였던 부분중 하나는 패키지 구조가 이게맞나? 라는 부분이었습니다.그도 그럴것이 학원에서 프로젝트를 진행할 때 Github의 충돌을 방지하기 위하여 이름별로 패키지를 나누고 각자 따로 작업을 진행하라고 하였었기 때문이었는데, 아무리 다른 프로젝트의 코드들을 둘러보아도 이름별로 패키지를 나누어 놓은 프로젝트는 찾아볼 수 없었기 때문입니다.먼저, 기존 프로젝트의 패키지 구조는 다음과 같습니다.기존 프로젝트 패키지 구조📦gukmo ┣ 📂board ┃ ┣ 📂aop ┃ ┣ 📂common ┃ ┣ 📂hasol ┃ ┃ ┣ 📂alarm ┃ ┃ ┣ 📂controller ┃ ┃ ┣ 📂repository ┃ ┃ ┗ 📂serv..
![사이드 프로젝트 [국비의 모든것] - 데이터베이스, 엔티티 설계](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIAcPT%2FbtsiuMKGM9H%2FPzuYdl1vSro7RmDgfetqt1%2Fimg.png)
목차ERD 작성엔티티 설계ERD 작성ERD작성 툴을 기존 프로젝트에서는 eXERD 를 사용하였는데 노트북을 바꾸면서 기존에 쓰던 라이센스를 까먹게 되어서 새로운 툴을 사용해야 했습니다.검색 끝에 ERDCloud라는 툴을 알게되었는데, 웹 기반으로 자동으로 저장되고 몇번 사용해보니 쉬워서 해당 툴을 사용하게 되었습니다. 기존 프로젝트의 ERD는 다음과 같습니다.해당 데이터베이스 설계를 제가 대부분 도맡아서 했었는데, 한눈에 보기에도 유의미한 값이 기본키로 설정되어있고, 다른 테이블들과 복잡한 연관관계를 가지고 있기 때문에 값이 변경되거나 데이터를 삭제할 때 제약조건에 걸려 수정할 일이 발생하면 생각지 못한 사이드이펙트가 많이 발생하였습니다. 이점을 고려하여 새롭게 데이터베이스 구조를 갈아엎었습니다. 물론..
![사이드 프로젝트 [국비의 모든것] - 프로젝트 환경설정](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4Yp1p%2FbtsgttT8jlC%2F9LiKnr0GJhepOSh8R60MeK%2Fimg.png)
목차프로젝트 생성Gradle로 변환하기Tiles 설정하기프로젝트 생성먼저 https://start.spring.io/ 에서 마이그레이션 할 프로젝트를 새로 생성한 뒤, 필요한 소스코드 파일들은 기존 프로젝트에서 복붙으로 옮기고자 합니다. 프로젝트에 기본 의존성은 Spring Web, Lombok, Spring Data JPA을 추가해주었고, Generated를 눌러 적당한 위치에 옮겨 압축을 풀었습니다. 저의 경우에 설정은Gradle - Groovy 선택Language - JavaSpring Boot - 2.7.8버전 선택그다음 Project Metadata에 Group, Artifact, Name, Description, Package name을 설정해야 하는데, 솔직히 기존 프로젝트에서 해당 속성을 ..
프로젝트 진행 배경기존 프로젝트를 개발하면서 유지보수성을 전혀 고려하지 않고 개발을 하였었습니다. 패키지 구조도 당시 학원에서 Github 충돌이 나지 않게 팀원 이름별로 나누어 개발을 진행하라고 하였기 때문에, 실무에서도 그렇게 개발하는 줄 알았으나 다르다는 것을 깨달았고 이를 고치고 싶다는 생각을 가지고 있었습니다. 하지만 유지보수성을 전혀 고려하지 않은 프로젝트 였기 때문에, 해당 프로젝트를 수정하기보단 아예 새롭게 개발하는것이 빠르겠다 싶었습니다.기존 프로젝트는 Spring Framework, MyBatis 를 사용하여 개발하였는데, 개인적으로 JPA와 Spring Boot에 대해 학습하면서 JPA와 Spring Boot를 사용하여 어플리케이션을 개발하는 것이 더 효율적이고 빠르게 개발할 수 있다..