[문제]
Postman으로 API가 잘 작동하는지 확인했는데, 막상 GET 메서드(method)를 실행하니 아무것도 나오지 않았다. 처음에는 오류인 줄 알고 심정이 철렁했는데, '200 OK'라는 Http 상태 메시지를 보니 원인이 어느 쪽인지 짐작할 수 있었다. 이번에 발생한 문제는 리턴(return), 즉 반환하는 부분을 제대로 작성하지 않아서 생긴 듯했다. 여기까지 추측한 다음에는 DTO(Data Transfer Object)나 엔티티(Entity)는 건너뛰고 각 레이어(layer)를 다시 찬찬히 읽었다.
[원인]
package com.spring.weekthree.controller;
import com.spring.weekthree.dto.PlanRequestDto;
import com.spring.weekthree.dto.PlanResponseDto;
import com.spring.weekthree.service.PlanService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
// [1/3] Presentation Layer - controller
@RestController
@RequestMapping("/plans")
public class PlanController {
// (1) 속성
private final PlanService planService;
// (2) 생성자
public PlanController(PlanService planService) {
this.planService = planService;
}
// (3) 기능
@PostMapping
public ResponseEntity<PlanResponseDto> createPlan(@RequestBody PlanRequestDto requestDto) {
PlanResponseDto responseDto = planService.processSaveInService(requestDto);
return new ResponseEntity<>(responseDto, HttpStatus.CREATED);
}
@GetMapping
public ResponseEntity<List<PlanResponseDto>> readAllPlans() {
List<PlanResponseDto> allPlans = planService.processViewService();
return new ResponseEntity<>(allPlans, HttpStatus.OK);
}
}
package com.spring.weekthree.service;
import com.spring.weekthree.dto.PlanRequestDto;
import com.spring.weekthree.dto.PlanResponseDto;
import com.spring.weekthree.entity.Plan;
import com.spring.weekthree.repository.PlanRepository;
import org.springframework.stereotype.Service;
import java.util.List;
// [2/3] Business Layer(Service Layer) - service
@Service
public class PlanServiceImpl implements PlanService {
// (1) 속성
private final PlanRepository planRepository;
// (2) 생성자
public PlanServiceImpl(PlanRepository planRepository) {
this.planRepository = planRepository;
}
// (3) 기능
@Override
public PlanResponseDto processSaveInService(PlanRequestDto requestDto) {
Plan plan = new Plan(
requestDto.getName(),
requestDto.getPassword(),
requestDto.getPlannedDate(),
requestDto.getTitle(),
requestDto.getTask()
);
Plan savedPlan = planRepository.saveEachPlan(plan);
return new PlanResponseDto(savedPlan);
}
@Override
public List<PlanResponseDto> processViewService() {
return planRepository.pullAllPlans();
}
}
package com.spring.weekthree.repository;
import com.spring.weekthree.dto.PlanResponseDto;
import com.spring.weekthree.entity.Plan;
import org.springframework.stereotype.Repository;
import java.util.*;
// [3/3] Data Access Layer(Repository Layer) - repository
@Repository
public class PlanRepositoryImpl implements PlanRepository {
// (1) 속성
private final Map<Long, Plan> planList = new HashMap<>();
// (2) 생성자
// (3) 기능
@Override
public Plan saveEachPlan(Plan plan) {
Long planId = planList.isEmpty() ? 1 : Collections.max(planList.keySet()) + 1;
plan.setId(planId);
planList.put(planId, plan);
return plan;
}
@Override
public List<PlanResponseDto> pullAllPlans() {
List<PlanResponseDto> allPlans = new ArrayList<>();
for (Plan plan : planList.values()) {
PlanResponseDto responseDto = new PlanResponseDto(plan);
allPlans.add(responseDto);
}
return List.of();
// [오답] List.of();
// [정답] allPlans;
}
}
역시 짐작대로 원인은 인터페이스(interface) PlanRepository를 오버라이딩(overriding) 해온 PlanRepositoryImpl 클래스(class)에 있었다. add() 메서드까지 잘 사용해 놓고 allPlans가 아니라 List.of()를 반환했으니, 컴퓨터는 명령대로 잘 움직였을 뿐이었다.
[해결]
package com.spring.weekthree.repository;
import com.spring.weekthree.dto.PlanResponseDto;
import com.spring.weekthree.entity.Plan;
import org.springframework.stereotype.Repository;
import java.util.*;
@Repository
public class PlanRepositoryImpl implements PlanRepository {
// (1) 속성
private final Map<Long, Plan> planList = new HashMap<>();
// (2) 생성자
// (3) 기능
@Override
public Plan saveEachPlan(Plan plan) {
Long planId = planList.isEmpty() ? 1 : Collections.max(planList.keySet()) + 1;
plan.setId(planId);
planList.put(planId, plan);
return plan;
}
@Override
public List<PlanResponseDto> pullAllPlans() {
List<PlanResponseDto> allPlans = new ArrayList<>();
for (Plan plan : planList.values()) {
PlanResponseDto responseDto = new PlanResponseDto(plan);
allPlans.add(responseDto);
}
return allPlans;
/*
[수정 전] return List.of();
[수정 후] return allPlans;
*/
}
}
문제는 금방 해결했다. 정말 사소한 부분이지만, 오답 노트로 정리해 두면 같은 실수를 반복해도 최소한 '저번에도 이러지 않았나?' 기억을 더듬으며 오답 노트에서 찾을 수 있는 만큼, 기록으로 남겨두었다. '이런 실수를 했다고?' 느낀 동시에 팀 프로젝트를 하기 전에 저질러서 다행이라는 마음 또한 들었다.
'Troubleshooting: 무엇이 문제였는가? > 본캠프 3주 차: 일정 관리 앱 만들기' 카테고리의 다른 글
2단계: "왜 수정 날짜를 수정하려고 하니!" (0) | 2024.12.08 |
---|---|
1단계: "@NoArgsConstructor가 굴린 대형 눈덩이" (0) | 2024.12.08 |
2단계: "500 Internal Server Error라니! 일단 침착해!" (0) | 2024.12.07 |
1단계: "Condition '(name != null) && (updatedDate != null)' is always 'false'" (0) | 2024.12.07 |
2단계: "꿈쩍 안 하는 수정일과 얼음땡!" (0) | 2024.12.06 |