2025.03.19 - [언어, 프레임워크/Spring] - Spring MVC
Spring MVC
Spring MVC 사용 배경Servlet 사용비지니스 로직을 처리하는 코드와 화면을 그리는 View 코드가 함께 존재하는 문제JSP 사용View 에 해당하는 코드를 분리하였지만, 여전히 비지니스 로직을 JSP에 포함하
go-getter1kim.tistory.com
이전에 발행한 글에 정리해놨듯이,
M(Model) 레이어는 데이터와 비즈니스 로직을 수행하는 부분,
V(View)는 사용자에게 보여지는 프론트엔드 역할을 하는 부분,
C(Controller)는 Model과 View를 연결해주는 역할을 하는 부분이다.
그런데 단순한 MVC은 Model 부분에 너무 많은 역할을 할당하기 때문에 Model이 다시 Service와 Repository로 세분화된다.
여기서 등장하는 개념이 바로 Layered Architecture이다.
Service는 비즈니스 로직을 처리하고 Repository는 DB에 접근하여 데이터 관련 작업을 수행한다.
프로젝트를 진행하기 전에 아키텍처를 머리로만 이해했을 때는 간단하게 특정 역할을 하는 코드를 각각 해당하는 레이어에 두고, 혹시라도 엔티티 외부에서 데이터를 변경하면 안되니까 레이어를 이동할 때 DTO에 엔티티를 담아서 전달하자! 정도의 지식이었다.
이번 RESTful API 개발 프로젝트를 진행하면서 Spring에 대해서는 아주 얕게 배웠지만 아키텍처 구조에 대해서는 이해도가 많이 올라간 것 같다.
package com.example.todoproject.entity;
import java.sql.Timestamp;
public class Todo {
private long todoId;
private long userId;
private String contents;
private Timestamp createdDate;
private Timestamp updatedDate;
}
package com.example.todoproject.entity;
public class User {
private long userId;
private String userName;
private int password;
}
강의를 듣고 실습을 할 때 자연스럽게 Entity 패키지를 생성하고, 패키지에 필요한 객체 클래스를 만들었다.
그냥 자바에서 클래스를 생성하듯 스프링 프레임워크에서도 그렇게 했던 것 같다.
하지만 DB에서 데이터를 가져와서 특정 엔티티에 저장해야하는 문제에 부딪혔을 때, Entity의 역할을 이해한 것 같다.
나는 ERD로 테이블을 먼저 설계하고 설계된 테이블을 그대로 엔티티에 적용했는데, 막상 테이블을 조인해서 데이터를 반환하는 과정에서 이 데이터를 저장할 적절한 엔티티가 없었던 것이다. (엔티티에는 없는 컬럼도 반환 데이터에 포함되어 있기 때문이다.)
그래서 엔티티에 해당 컬럼을 추가할까? 하고 고민하며 튜터님께 조언을 구했다.
이전에 트러블 슈팅에 작성했던 글처럼, 엔티티는 그저 객체가 아니라 데이터베이스 테이블을 자바 세상에 가져다 놓은 틀의 역할을 하고 있는 거였다.
그렇기 때문에 데이터베이스 테이블의 구조와 달라지면 엔티티가 본연의 역할을 하지 못하게 된다.
이 개념을 배우면서 엔티티 뿐만 아니라 DTO의 개념도 다시 공부할 수 있었던 것 같다.
DTO는 단순히 캡슐화하여 외부에서 데이터를 변경하는 걸 막기 위한 역할도 있지만, 엔티티에 담지 못하는 데이터 묶음을 온전히 담아낼 수 있다.
또한 내가 프로젝트를 진행하면서 수시로 DB가 바뀌듯이 실무에서는 더더욱 많은 테이블이 바뀔 가능성이 농후한데, DTO를 사용하면 각 API, 각 레이어마다 반환타입이나 파라미터를 변경해주지 않아도 된다.
레이어를 거칠 때마다 DTO에 담아서 전달하기 때문에 DTO의 내부 구조만 변경해주면 되는 것이다.

이미지처럼 프로젝트를 진행하는 동안 데이터 타입을 자주 바꾸었는데, updatedDate를 전달하는 API마다 타입을 변경하지 않고 DTO에서만 변경하면 됐다.
아직 간단한 프로젝트라서 Controller와 Service를 여러 개로 분리해서 사용해보진 못했지만, Repository에서는 두 개의 DB 테이블을 접근해야하는 덕분에 이를 적용해볼 수 있었다.

처음에는 하나의 TodoRepository 테이블에 모든 데이터 접근 코드를 때려넣었다면,
User, Todo 각각의 레포지토리 클래스를 생성하고 분리했다.
이를 통해 조금 가독성있는 코드를 만들면서도 각 클래스의 역할이 분명하기 때문에, 추후 규모가 큰 프로젝트를 진행한다면 잘 활용할 수 있을 것 같다.
깃허브에 따로 수정하거나 고민했던 부분은 안남아있지만, 프로젝트를 진행하면서 + 튜터님들이 진행하시는 세션을 들으면서 상태 코드를 반환하는 것에 대한 의미도 조금 더 이해할 수 있었다.
강의를 들을 때는 ResponseEntity로 DTO를 감싸고, 상태코드를 함께 날려보내는 것은 의무적으로, 형식적으로 한다고 생각했다.
사실 아직 프론트엔드와 협업을 해보진 않았기에 역할을 완벽히 경험한 것은 아니지만, 포스트맨으로 데이터를 요청했을 때 500 Internal Server Error만 반환하는 탓에 서버 콘솔을 찾아보고, log를 찍어보며 에러를 파악하려 애썼다.
만약 내가 프론트엔드 개발자라면 더욱 알 수 없기에 이 상태코드와 예외처리가 협업에 있어서는 중요한 역할을 하는구나 깨달았다.
이렇게 프로젝트를 진행하면서 기억에 남는 부분을 적어보았다.
사실 이번 프로젝트는 Spring을 처음으로 써보는 거라 아직 많이 미숙하기도 하고 오로지 Spring의 이해도를 조금 높여주는 역할일 뿐이지만, Layered Architecture와 MVC 패턴, 그리고 협업에서의 백엔드 개발자의 역할 등을 조금은 배울 수 있어서 좋은 경험이었다.
다음에 기회가 있다면 Controller, Service를 분리해서 적용해보는 경험도 할 수 있길 바라고, 만약 없다면 주말을 이용해 개인적으로 실습해보자.
'프로젝트 > 개인 프로젝트' 카테고리의 다른 글
[Java/Spring] HttpServletResponse의 역할 (0) | 2025.04.04 |
---|---|
[Java] 계산기 과제 중 발생한 의문점 정리 (0) | 2025.03.06 |