기록을 불러오고 있습니다.
기록을 불러오고 있습니다.
LAB 03 / Spring Boot · Architecture
DispatcherServlet부터 데이터베이스까지, 요청이 지나가는 각 계층을 살펴봅니다.
Controller에 진입하지 못한 요청과 Service에서 실패한 요청을 같은 문제로 보면 조사 범위가 불필요하게 넓어집니다.
HTTP 요청은 여러 컴포넌트를 거칩니다. 경로 매칭, 인자 바인딩, 업무 규칙, 영속성 접근, JSON 직렬화는 서로 다른 단계에서 일어납니다.
설정을 바꾸면 재생이 초기화됩니다. 자동 재생하거나 한 단계씩 실행해 보세요.
자동 재생, 다음 단계, 또는 위의 컴포넌트를 눌러 요청 흐름을 따라가세요.
동기식 REST 요청의 대표 경로를 단순화했습니다. Servlet Filter·Interceptor·보안 필터·예외 처리·비동기 요청과 ViewResolver는 생략했습니다. Database 이후에는 호출 스택을 거슬러 응답합니다.
각 노드를 누르면 역할과 그 단계의 요청 데이터 또는 Java 코드가 표시됩니다. Database 결과는 Repository → Service → Controller로 돌아오고, 반환값 처리기가 JSON 응답으로 변환합니다.
HTTP 입출력과 상태 코드, 입력 검증을 담당합니다. 업무 로직을 모두 넣으면 HTTP 변경과 도메인 변경이 섞입니다.
Service는 업무 규칙과 트랜잭션 경계, Repository는 영속성 접근을 맡습니다. 계층은 변경 이유를 분리하기 위한 도구입니다.
원리를 설명하는 코드입니다. 실제 프로젝트 원본과 구분하며, 엔티티·도메인 타입·import 일부는 생략했습니다.
@RestController
@RequestMapping("/api/albums")
@RequiredArgsConstructor
public class AlbumController {
private final AlbumService albumService;
@GetMapping("/{id}")
public AlbumResponse find(@PathVariable Long id) {
return albumService.findById(id);
}
}@Service
@RequiredArgsConstructor
public class AlbumService {
private final AlbumRepository albumRepository;
@Transactional(readOnly = true)
public AlbumResponse findById(Long id) {
Album album = albumRepository.findById(id)
.orElseThrow(AlbumNotFoundException::new);
return AlbumResponse.from(album);
}
}public interface AlbumRepository extends JpaRepository<Album, Long> {
// Spring Data JPA가 findById 등 구현체를 제공합니다.
}
public record AlbumResponse(Long id, String title) {
public static AlbumResponse from(Album album) {
return new AlbumResponse(album.getId(), album.getTitle());
}
}
// Album/예외 클래스/import는 생략한 구조 설명용 예제입니다.Filter, Interceptor, Spring Security, 예외 처리, 비동기 요청과 ViewResolver는 이 개념도에서 생략했습니다. 모든 요청이 DB에 도달하지는 않습니다. 엔티티 반환 중 지연 로딩이 일어나지 않도록 DTO와 트랜잭션 경계도 확인하세요.