Troubleshooting: 무엇이 문제였는가?/본캠프 3주 차: 일정 관리 앱 만들기 12

3단계: "406 Not Acceptable"

[문제]이러다가 정말 400번 대 오류를 전부 한 번 이상 만나겠다 싶었다. 데이터베이스(database) 구성이 완전히 바뀌고, 자료구조 대신 JdbcTemplate를 사용하면서 한 문제를 해결하면 다른 문제가 생겼다. [원인]package com.spring.weekthree.dto.member.response;import com.spring.weekthree.entity.Member;import lombok.Getter;// response DTO 클래스(class) @Getter // @Getter가 없으면 JSON 변환이 안 된다.public class MemberResponseDto { //(1) 속성 private long memberId; private String name..

3단계: "순환 참조 오류라니, 돌아가는 각도가 예술이군요."

[문제]열심히 코드를 고치고 나서 실행했더니만, 축하한다는 메시지인 양 APPLICATION FAILED TO START 오류 메시지가 떴다. 일명 순환 참조 오류였다. 화살표가 정말 한 치 오차도 없이 완벽한 각도로 꺾였다. [원인]// [1/1] Data Access Layer(Repository Layer)@Repositorypublic class JdbcTemplatePlanRepository implements PlanRepository { private final JdbcTemplate jdbcTemplate; private final PlanService planService; /* [오답] private final PlanService planService; [정..

3단계: "사용자 Id를 입력했는데 왜 자꾸 0이 나오니?"

[문제]몇몇 사용자가 이미 가입한 상황이라고 가정하고, 즉 데이터베이스에 몇몇 사용자 정보를 저장한 다음 3단계 도전 과제를 했다. 문제는 일정을 생성하는 데에는 성공했는데, memberId를 입력해도 계속 0이 나왔다. 아무래도 무언가를 빠뜨린 듯싶었다.  [원인]package com.spring.weekthree.dto.responsedto;import com.spring.weekthree.entity.Plan;import lombok.AllArgsConstructor;import lombok.Getter;import java.time.LocalDate;import java.time.LocalDateTime;// 클라이언트(client)에 응답하는 response DTO 클래스(class) @AllA..

2단계: "PATCH를 두 번 눌러야 수정이 돼요. 왜 이럴까요?"

[문제]Postman으로 일정을 부분 수정하는 PATCH를 실행하면 Send 버튼을 두 번 눌러야 수정되었다. 500번 대 오류 메시지가 뜨지는 않았으나, 이는 분명 무언가에 문제가 있다는 뜻이었다. 이 문제를 확실히 해결하고자 아침 9시에 팀에서 데일리 스크럼(Daily Scrum)을 마치는 대로 튜터님을 찾아갔다. [원인]이번에 발생한 문제는 PATCH 기능이 두 번 이루어진 게 아니라, 수정된 일정을 제대로 반환하지 않아서 생긴 문제였다. 스프링(Spring) 내에서 쓰는 객체와 데이터베이스는 별개인데, Send 버튼을 눌렀을 때 데이터베이스에서만 일정을 수정한 탓에 API 응답에서는 수정 전 일정이 출력된 것이었다. [해결](1) 데이터베이스와 한 번 더 소통하기ⓐ 해결 방법더보기package c..

1단계: "넌 띄어쓰기를 소중히 하지 않았어"

[문제]SQL 쿼리(query)문을 작성하고 실행하니 바로 500 Internal Server Error 메시지가 떴다. 이 정도면 저 오류 메시지를 보려고 리팩토링(refactoring)하는 게 아닌가 싶었다. [원인]package com.spring.weekthree.repository;import com.spring.weekthree.dto.responsedto.PlanResponseDto;import com.spring.weekthree.entity.Plan;import org.springframework.http.HttpStatus;import org.springframework.jdbc.core.*;import org.springframework.jdbc.core.namedparam.MapSq..

1단계: "아무래도 이름(name)이란 체에 구멍이 뻥 뚫렸나 보다."

[문제]분명히 Key 값으로 name을 넣었는데도 결과는 일정 목록을 조회할 때와 별반 다르지 않았다. 차라리 400이나 500번 대 오류 메시지가 떴다면 원인이 뭔지 금방 찾을 수 있으나, 200 OK 메시지가 뜨면 코드를 다시 읽어야 했다. 우선 수정한 부분을 다시 읽었다. [원인]package com.spring.weekthree.repository;import com.spring.weekthree.dto.PlanResponseDto;import com.spring.weekthree.entity.Plan;import org.springframework.http.HttpStatus;import org.springframework.jdbc.core.JdbcTemplate;import org.spring..

2단계: "왜 수정 날짜를 수정하려고 하니!"

[문제]벌써 500 Internal Server Error 메시지를 두 번이나 봤다. 이쯤 되니까 놀랍지도 않았다. 이번엔 또 뭘 잘못 했을까, 차분한 마음으로 설명을 읽었다. [원인]package com.spring.weekthree.repository;import com.spring.weekthree.dto.PlanResponseDto;import com.spring.weekthree.entity.Plan;import java.time.LocalDate;import java.util.List;import java.util.Optional;// [1/2] 인터페이스public interface PlanRepository { PlanResponseDto save(Plan plan); List ..

1단계: "@NoArgsConstructor가 굴린 대형 눈덩이"

[문제]처음에는 전부 다 빨간 줄이 쳐져서 얼마나 심장이 벌렁벌렁 뛰었는지 모른다. 분명 강의를 들으며 코드를 따라 쳤는데, 왜 내가 쓴 코드에만 문제가 생기는지 영 감을 못 잡았다. 챗GPT에도 물었으나, 분명한 답을 얻지는 못했다. [원인]package com.spring.weekthree.entity;import lombok.AllArgsConstructor;import lombok.Getter;import java.time.LocalDate;import java.time.LocalDateTime;/*entity에 해당하는 Plan 클래스[오답] NoArgsConstructor[정답] AllArgsConstructor*/@NoArgsConstructor@Getterpublic class Plan {..

2단계: "500 Internal Server Error라니! 일단 침착해!"

[문제]어쩐지 데이터베이스(database) 연동이 너무 순조롭다 싶었다. 두근거리는 마음으로 실행 버튼을 누르기 무섭게 무려 500 Internal Server Error 메시지가 떴다. 400번이 아니었기 때문에 코드 작성에 문제가 있다는 뜻이었다. 당황하긴 했지만, 보통 이럴 때는 꼭 문제가 무엇인지 설명도 같이 나오니까 읽어보기로 했다. [원인]spring.application.name=weekthreespring.datasource.url=jdbc:mysql://localhost:3306/memospring.datasource.username=사용자명spring.datasource.password=비밀번호spring.datasource.driver-class-name=com.mysql.cj.jd..

1단계: "Condition '(name != null) && (updatedDate != null)' is always 'false'"

[문제]package com.spring.weekthree.repository;import com.spring.weekthree.dto.PlanResponseDto;import com.spring.weekthree.entity.Plan;import org.springframework.stereotype.Repository;import java.time.LocalDate;import java.util.*;// Data Access Layer(Repository Layer)@Repositorypublic class PlanRepositoryImpl implements PlanRepository { // 속성 private final Map planList = new HashMap(); // ..