Spring MVC는 웹 애플리케이션에서 클라이언트의 요청(Request)을 받아 처리하고,
그 결과를 응답(Response)으로 반환하는 구조이다.
MVC는 다음 3가지 역할로 나뉜다.
Model: 데이터 (DTO, Entity)
View: 사용자에게 보여지는 결과 (JSON, HTML) 요새는 프론트엔드쪽 프레임워크에 좋아진부분이 많아서 X
Controller: 요청을 받아 처리 흐름을 제어
Spring에서는 View 대신 JSON을 반환하는 경우가 많기 때문에
Controller + Service + Repository 구조로 이해하는 것이 더 실용적이다.
Spring MVC의 실제 흐름은 다음과 같다.
[클라이언트]
↓ HTTP 요청 (JSON)
[Controller]
↓ Request DTO
[Service]
↓ Entity 생성/조회/수정
[Repository]
↓ DB 접근
[DB]
(응답 흐름)
[DB]
↑ Entity
[Service]
↑ Response DTO 변환
[Controller]
↑ JSON 응답
[클라이언트]
핵심
요청은 DTO → Entity로 변환되고
응답은 Entity → DTO로 변환된다
Controller는 클라이언트 요청을 처음 받는 계층이다.
@RestController
@RequestMapping("/members")
public class MemberController {
@PostMapping
public MemberResponse create(@RequestBody MemberCreateRequest request) {
return memberService.create(request);
}
}
@RestController
-> 반환값을 JSON으로 변환
@RequestBody
-> JSON → Java 객체로 자동 변환
URL과 메서드를 연결 (@PostMapping)
Controller는 비즈니스 로직을 처리하지 않고, 요청을 Service로 전달하는 역할만 한다
Controller -> Service -> Repository
Service는 실제 비즈니스 로직이 수행되는 계층이다.
@Transactional
public MemberResponse create(MemberCreateRequest request) {
// 1. DTO → Entity 변환
Member member = new Member(
request.getName(),
request.getEmail(),
request.getPassword()
);
// 2. 저장
Member savedMember = memberRepository.save(member);
// 3. Entity → DTO 변환
return MemberResponse.from(savedMember);
}
DTO -> Entity 변환
비즈니스 로직 수행
DB 저장/조회
Entity -> DTO 변환
@Transactional로 데이터 일관성 유지
Service가 가장 중요한 계층이다
public interface MemberRepository extends JpaRepository<Member, Long> {
}
DB와 직접 통신
CRUD 제공 (save, findById, delete 등)
Service는 Repository를 통해서만 DB에 접근한다
Spring MVC에서는 Entity 대신 DTO를 사용하는 것이 일반적이다.
1) 보안 문제 방지
Entity에는 민감한 정보가 포함될 수 있다.
private String password;
Entity를 그대로 응답하면 비밀번호가 노출될 위험 있음
2) 역할 분리
Entity -> DB 저장용 객체
DTO -> 요청/응답용 객체
책임을 분리해서 코드 구조를 명확하게 만든다
3) API 유연성 확보
예를 들어 회원가입 요청:
{
"name": "영범",
"email": "test@test.com",
"password": "1234",
"passwordConfirm": "1234"
}
-> passwordConfirm은 DB에 필요 없음 → DTO에서만 처리
4) 유지보수 용이성
DB 구조가 변경되어도
DTO만 잘 설계하면 API 응답은 유지 가능
@RequestBody MemberCreateRequest request
-> 내부적으로 JSON을 객체로 변환
2) 응답: DTO → JSON
return MemberResponse.from(member);
-> 객체를 JSON으로 자동 변환해서 응답
@PostMapping
public Member create(@RequestBody Member member) {
return memberRepository.save(member);
}
클라이언트가 id 조작 가능
password 노출 위험
API 구조가 DB 구조에 종속됨
검증 로직 추가하기 어려움
그래서 DTO를 반드시 사용하는 것이 좋다
10.느낀 점
처음에는 Entity와 DTO를 왜 나누는지 이해가 안되고 귀찮은작업이라생각했지만
실제로 보안, 유지보수, 역할 분리 측면에서 꼭 필요하다는 것을 이해했다
Controller는 단순히 연결 역할이고
Service가 핵심이라는 점이 중요하다
DTO 변환 과정이 번거롭지만
구조를 안정적으로 만들기 위한 과정이라는 것을 알게 되었다