✅ 들어가며
Spring Boot로 백엔드 개발을 시작하면 흔히 보게 되는 구조가 있다.
바로 Controller - Service - Repository로 나뉘는 MVC 패턴 기반의 구조다.
처음엔 ‘왜 이렇게 나눠야 하지?’라는 생각이 들 수도 있다. 코드가 더 복잡해 보이고, 한 파일에 다 때려 넣는 게 편할 것 같은데…
하지만 이 구조에는 분명한 이유와 장점이 있다.
이 글에서는 MVC 패턴의 기본 개념부터, Spring Boot에서 구조를 나누는 이유, 각 계층의 역할, 그리고 실무에서 어떤 식으로 적용되는지까지 설명해보려 한다.
🔧 MVC 패턴이란?
MVC는 Model - View - Controller의 약자다.
- Model: 데이터와 비즈니스 로직을 담당
- View: 사용자에게 보여지는 화면
- Controller: 사용자 입력을 받아 처리하고, Model과 View를 연결
Spring Boot에서는 웹 화면보다는 API를 제공하는 백엔드 용도로 많이 사용되기에, View는 거의 사용되지 않거나 JSON 응답으로 대체된다. 그래서 실제 개발에서는 다음과 같은 계층 구조로 발전한다:
[Client] → Controller → Service → Repository → DB
🧱 각 계층의 역할은?
1. Controller (입구)
사용자의 요청을 가장 먼저 받는 계층.
역할은 요청을 받아서 적절한 Service로 전달하고, 응답을 반환하는 것.
- API 주소에 맞는 요청을 받고 (@GetMapping, @PostMapping 등)
- 파라미터를 검증하고
- 결과를 사용자에게 전달함 (예: ResponseEntity, JSON)
⚠ Controller는 로직을 작성하는 곳이 아니다!
복잡한 처리를 하면 유지보수가 어려워진다.
2. Service (비즈니스 로직의 중심)
비즈니스 로직이 구현되는 핵심 계층.
- 회원 가입, 주문 생성, 결제 처리 등 ‘업무 로직’이 들어감
- 여러 Repository를 조합하거나 외부 API 호출 등을 처리함
- 트랜잭션 관리도 여기서 이루어짐 (@Transactional)
💡 Service는 말 그대로 ‘서비스’를 설계하는 곳.
로직이 복잡해질수록 이 계층의 역할이 중요해진다.
3. Repository (데이터 입출력)
실제 DB에 접근하는 계층.
Spring Data JPA 등을 사용해 구현한다.
- 데이터를 조회하고 저장하는 역할
- SQL 대신 메서드 이름만으로 쿼리를 작성 가능 (findByUsername() 등)
📦 Repository는 Model에 맞는 CRUD 처리를 담당하고, 비즈니스 로직은 Service로 넘겨야 한다.
🤔 왜 이렇게 나눠야 할까?
1. 관심사의 분리 (Separation of Concerns)
- 각 계층이 하나의 역할만 하도록 분리하면, 유지보수가 쉬워짐
- 예: DB 구조가 바뀌어도 Repository만 수정하면 됨
2. 재사용성과 테스트 용이성
- Service 단위로 테스트 작성 가능 (단위 테스트)
- 다른 Controller에서도 같은 Service를 재사용 가능
3. 협업의 효율
- 백엔드 개발자끼리도 역할을 나눠서 개발 가능
- 예: 한 명은 Controller 담당, 한 명은 Service 로직 개발
4. 유지보수/확장성
- 기능이 커져도 구조는 그대로 유지 가능
- 신규 기능도 기존 계층 체계에 맞게 추가 가능
📝 마무리
Spring Boot의 구조는 단순히 "나눠야 하니까 나누는 것"이 아니다.
각 계층이 제 역할을 잘 수행할 수 있도록 구조화되어 있으며, 이로 인해 더 유지보수하기 좋은 코드를 만들 수 있다.
Controller는 입구, Service는 뇌, Repository는 손발이라고 생각하면 이해가 쉬울 것이다.
이 구조를 잘 활용하면 팀 프로젝트든 실무든 한결 효율적인 개발이 가능하다.