어제 댓글때문에 머리가 깨지는 줄 알았어요... 퇴실하고 컴퓨터 끄고 나서도 계속 댓글구현 어떻게 할지만 생각나서 자기전에 급하게 메모까지 했습니다... 고양이랑 자기로 약속한 시간 넘어서까지 하느라 미안해서 간식줬더니 제 마음을 아는지 모르는지 한껏 올라간 꼬리...

하루가 지났으니 댓글 출력 등록하고, 어제 발생했던 exception 정리하겠습니다
2/3 생겼던 문제 정리
1. Entity 에 FK 연결을 어떻게 해줘야할지 모르겠다
Schedule Entity 를 Comment Entity 에 직접 선언하고 @ManyToOne 으로 연결, 수많은.. 오류 발생
-> 이런 연결방식은 양방향이라 아직 안 배웠고 숙련 Spring 단계 때 배우니까 사용하지말고 기다리라고 하심
-> 그냥 ScheduleId 라는 private field 를 만들고 Id를 받아올 때 사용하기
2. Comment list 를 Schedule 단건조회에 추가해주기
이부분이 제일 어려웠던 거 같다
DTO 는 박스같은 느낌이라 보내려고 하는 정보들을 모두 담아서 보내야한다고 생각
-> 단건조회일때는 comment list 를 박스에 넣어줘야하고, 다건조회일때는 comment list 를 보내면 안 됨
DTO 를 단건조회와 다건조회로 분리해줘야하나? 라는 생각
Schedule 에 List<Comment> 를 직접 만들어주기 싫어서 더 헷갈렸던 거 같다
근데 일단 다건조회때는 무조건 Comment 가 들어가있는 List 를 만들어줘야 출력이 될 거 같은데 Comment Entity 를 직접보내는건 또 걱정돼서 DTO 로 보내야하나? 싶기도 하고 ..
일단 (1)Comment 를 직접 보내는 형식으로 다시 구현해보기
새로 만들었던 모든 코드들은 정리...
(1) 단건조회에만 Comment List 를 추가했다
import java.time.LocalDateTime;
import java.util.List;
@Getter
public class GetScheduleResponse {
private final Long id;
private final String name;
private final String contents;
private final String writer;
private final List<Comment> commentList;
private final LocalDateTime createdAt;
private final LocalDateTime modifiedAt;
public GetScheduleResponse(Long id, String name, String contents, String writer,
List<Comment> commentList, LocalDateTime createdAt, LocalDateTime modifiedAt) {
this.id = id;
this.name = name;
this.contents = contents;
this.writer = writer;
this.commentList = commentList; #<<< here!
this.createdAt = createdAt;
this.modifiedAt = modifiedAt;
}
}
이렇게 되면 위 코드에 체크해둔 getScheduleResponse 의 생성자에 List<Comment> commentList 를 전달해줘야하기 때문에 CommentRepository 에 함수를 만들어줬다
처음알았는데 findBy뒤에 기준으로 할 필드를 작성하면 신기하게도 ... 함수를 그냥 사용할 수 있다 JPA 가 만들어줌
public interface CommentRepository extends JpaRepository<Comment, Long> {
List<Comment> findByScheduleId(Long scheduleId);
}
ScheduleService 에서 CommentRepository 에 직접 접근하는건 뭔가 이상해서 CommentService 에 함수내용을 구현했다
(ScheduleService 는 ScheduleRepository 에만 접근하고, CommentService 는 CommentRepository 에만 접근하도록)
public List<Comment> findCommentsByScheduleId(Long scheduleId){
return commentRepository.findByScheduleId(scheduleId);
}

정상적으로 메시지가 출력되는것을 확인할 수 있다.
하지만 ... 큰 문제... pw 가 그대로 출력되고 있다
당연히 Comment 를 직접 넘겨주기때문에 Comment 의 field 전체가 출력되어버리는것이다.
(2) DTO 를 새로 만들어서 pw 를 제외한 값만 넘겨줄 수 있도록 해야하나? 싶어서 새로 만들려고 했는데 생각해보니 DTO 를 원래 Controller - Service 를 연결해줄때 사용했는데 같은 계층 내부에서도 사용해도 되는지 헷갈렸다.....

검색해보니 특정 계층 내부에서도 필요한 데이터 구성을 위해 사용한다고 한다.
(2) DTO 를 새로 만들어서 값 넘겨주기
# GetScheduleResponse class
private final List<GetCommentResponse> commentList;
위와 동일하지만 commentList 의 자료형을 GetCommentResponse 로 바꿔줬다. 아래와 같이 pw 가 제외된 Comment 요소들을 반환하는 DTO 도 만들어줬다
import lombok.Getter;
@Getter
public class GetCommentResponse {
private final Long id;
private final Long scheduleId;
private final String contents;
private final String writer;
public GetCommentResponse(Long id, Long scheduleId, String contents, String writer) {
this.id = id;
this.scheduleId = scheduleId;
this.contents = contents;
this.writer = writer;
}
}
CommentService 에서는새로운 Dto List 를 만들기 위해 반복문을 통해 확인했다. 기본적인 다건조회 형식과 동일하다
함수는 findCommentsByScheduleId 이고, commentRepository 의 findByScheduleId 와 헷갈리지 않도록 주의해야한다...
| 함수명 | 위치 | 역할 |
| findByScheduleId | commentRepository | 특정 ScheduleId 를 매개변수로 하여 List<Comment> 를 반환한다. |
| findCommentsByScheduleId | commentService | findByScheduleId 를 호출하고, 반복문을 돌며 필요한 요소만 필터링 하여 List<GetCommentResponse> 를 반환한다. |
public List<GetCommentResponse> findCommentsByScheduleId(Long scheduleId){
List<Comment> commentList = commentRepository.findByScheduleId(scheduleId);
List<GetCommentResponse> dtos = new ArrayList<>();
for (Comment comment : commentList) {
GetCommentResponse dto = new GetCommentResponse(
comment.getId(),
comment.getScheduleId(),
comment.getContents(),
comment.getWriter()
);
dtos.add(dto);
}
return dtos;
}

이제 PW 가 제외된 제대로 된 commentList 값이 출력된다.
사실 과제에서는 댓글 생성만 하면 되는거였지만... 댓글을 삭제하고싶어질수도 있으니까 이왕 pw 까지 만들어둔거 pw를 받아 삭제까지만 만들어두었다
예외처리
예외처리를 추가로 만들어주었다/ 원래는 IllegalStateException 이었음

추가로 어제 발생한 Exception들을 정리하면
| BeanCreationException | Spring 이 Bean 을 생성하는 과정에서 의존성, 설정, 어노테이션 오류가 있을 때 발생 JPA 매핑 오류, 순환 참조, 생성자 주입 실패 어제 Schedule Entity 를 Comment Entity 에 직접 선언하면서 오류가 터진듯하다. @OneToMany(mappedBy = "scheduleId") 에서 Schedule entity 의 필드명이 그냥 id 였고, Fk 를 관리하는 주체가 Comment 였는데 반대로 주체로 생각했다 |
| createPluginException | 빌드 도구가 플러그인을 생성하거나 로드하는 과정에서 발생 의존성 오류때문에 발생 |
| StringIndexOutOfBoundsException | 어제 Comment list 를 만들고 출력하면서 index 를 잘못 설정해준듯하다 |
이부분은 숙련주차에서 배운다고 하니 exception들은 간단히 보고 넘어갔다
컬럼 출력 정렬
데이터베이스의 특정 컬럼을 기준으로 오름차순, 내림차순으로 가져오는 방법으로 Repository 에서 OrderBy 를 사용한다고 작성되어있다.
https://sshinmj.tistory.com/17
[JPA] OrderBy, DateIs - 오름차순/내림차순, 특정 날짜 기준으로 데이터 나누기
데이터 베이스의 특정 컬럼를 기준으로 오름차순/내림차순으로 가져오기 Repository에서 ‘OrderBy' 사용! - 사용 예시 List findByUserOrderByCreatedDateDesc(User user); >> 위 코드는 Orders 테이블의 ‘CreatedDate’
sshinmj.tistory.com
public interface ScheduleRepository extends JpaRepository<Schedule, Long> {
List<Schedule> findAllOrderByModifiedAtDesc();
}
나도 수정일 기준 내림차순 정렬 함수로 작성하고 Service 에서 호출해주었다

...
정리해보면
Bean 을 생성하는 과정 중 쿼리 생성에서 문제가 발생했다.
중요한 부분은
QueryCreationException, PropertyReferenceException 이었고, 메서드 네이밍 규칙을 따르지 않아서 스프링이 쿼리로 변환하지 못했다고 작성되어있다. Schedule Repository 의 findAllOrderByModifiedAtDesc() 의 명이 틀렸다고 해서 다시보니까 형식이 findAllByOrderByModifiedAtDesc() 요거였다 .... 수정!
실행이 되어서 확인을 해봤다
POST 입력 -> GET -> id 2 스케줄 수정 -> GET
처음엔 생성일 기준 내림차순이었을테니까, 수정이후 2번이 가장 위에 있으면 된다

modifiedAt 이 최신인것 기준으로 정렬되어 출력된다. 생성시 modifiedAt 은 createAt 과 동일하므로 순서가 맞다

2번을 업데이트 해주고 modifiedAt 이 정상적으로 업데이트된것을 확인할 수 있다
231 기준으로 출력된 모습도 확인 완료

'SPARTA 과제 > SPRING' 카테고리의 다른 글
| 숙련) 일정관리앱 트러블슈팅 (1) (0) | 2026.02.11 |
|---|---|
| 숙련) 일정관리앱 업그레이드 초기설정 (1) | 2026.02.10 |
| Schedule README (0) | 2026.02.05 |
| 유저 입력 검증 (0) | 2026.02.04 |
| 기본 DTO 작성 (0) | 2026.02.03 |