| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- math
- vscode
- Eclipse
- CSS
- ArrayList
- Java
- HashMap
- 문자열
- junit
- 정규식
- json
- list
- java테스트
- IntelliJ
- 배열
- javascript
- Visual Studio Code
- 자바
- 인텔리제이
- Array
- input
- js
- 단위테스트
- 테스트자동화
- html
- junit5
- 자바스크립트
- 자바문법
- string
- 이클립스
- Today
- Total
어제 오늘 내일
[Spring Boot 입문 - 6] Controller, Service, Repository: 3계층 구조 완벽 이해하기 본문
[Spring Boot 입문 - 6] Controller, Service, Repository: 3계층 구조 완벽 이해하기
hi.anna 2026. 2. 12. 01:36지난 시간, 우리는 HelloController라는 웨이터 한 명을 고용해서 손님(브라우저)의 인사를 받아주게 했습니다.
그런데 만약 손님이 "로그인 해주세요" 라거나 "내 통장 잔고 조회해 주세요" 같은 복잡한 요청을 하면 어떻게 될까요?
웨이터(Controller) 혼자서 장부 뒤지고, 계산하고, 보안 확인하고... 과로사할지도 모릅니다.
그래서 스프링 부트는 일을 세 명에게 철저하게 나눠줍니다. 이것이 바로 3계층 구조 (Layered Architecture)입니다.
1. 역할 분담: 레스토랑의 3인방
다시 레스토랑 비유를 가져오겠습니다. 각자의 역할은 절대 섞이면 안 됩니다.
① Controller (웨이터)
- 역할: 접수와 서빙.
- 하는 일:
- 손님의 주문(Request)을 받습니다. ("파스타 하나요!")
- 메뉴판에 있는 요리인지 확인합니다. (유효성 검사)
- 주방장(Service)에게 주문을 넣습니다.
- 요리가 나오면 손님에게 가져다줍니다(Response).
- 주의점: 절대로 직접 요리(비즈니스 로직)를 하지 않습니다. 웨이터가 주방에 들어가면 동선이 꼬입니다.
② Service (셰프/주방장)
- 역할: 요리 (비즈니스 로직).
- 하는 일:
- 웨이터가 준 주문서를 보고 요리를 시작합니다.
- 재료가 필요하면 창고지기(Repository)에게 달라고 합니다.
- 재료를 볶고, 끓이고, 간을 맞춥니다. (데이터 가공, 계산, 로직 수행)
- 핵심: 프로그램의 '지능(Brain)'이 모여있는 곳입니다. 가장 코드가 많고 중요합니다.
③ Repository (창고지기)
- 역할: 재료 관리 (DB 접근).
- 하는 일:
- 데이터베이스(냉장고) 문을 열고 닫습니다.
- 주방장(Service)이 "양파 줘" 하면 DB에서 데이터를 꺼내옵니다(
SELECT). - "이거 저장해 줘" 하면 DB에 저장합니다(
INSERT).
- 핵심: 어려운 SQL을 직접 짜지 않아도 되게 도와주는 역할을 합니다 (JPA).
2. 코드로 보는 차이 (나쁜 예 vs 좋은 예)
만약 "회원 가입" 기능을 만든다고 가정해 봅시다.
❌ 나쁜 예: Controller 혼자 다 할 때
웨이터가 주문도 받고, 요리도 하고, 재료도 꺼내오는 상황입니다. 코드가 엄청나게 길고 복잡해집니다.
// Controller
@PostMapping("/join")
public String join(Member member) {
// 1. 중복 회원인지 확인 (로직)
// 2. 비밀번호 암호화 (로직)
// 3. DB 연결 (DB)
// 4. SQL 작성 및 저장 (DB)
// 5. 결과 반환
return "가입 완료";
}
- 문제점: 나중에 "비밀번호 암호화 방식을 바꿔줘"라고 하면 이 파일을 뜯어고쳐야 합니다. 유지보수가 지옥이 됩니다.
⭕ 좋은 예: 3단 분리
각자 자기 할 일만 딱 합니다.
// 1. Controller (웨이터)
@PostMapping("/join")
public String join(Member member) {
memberService.join(member); // "셰프님, 회원가입 요리 해주세요."
return "가입 완료";
}
// 2. Service (셰프)
public void join(Member member) {
validate(member); // 중복 검사
repository.save(member); // "창고지기야, 이거 냉장고에 넣어놔."
}
// 3. Repository (창고지기)
// (DB에 실제로 저장하는 역할만 담당)
- 장점: 코드가 깔끔하고, 나중에 수정할 때도 해당 담당자(파일)만 찾으면 됩니다.
3. 한눈에 보는 구조도
이 그림을 머릿속에 넣어두세요. 데이터는 항상 위에서 아래로(Controller → Service → Repository → DB) 흘러갑니다.

4. DTO는 또 뭔가요? (서빙 카트)
공부하다 보면 DTO (Data Transfer Object) 라는 말도 나옵니다.
이건 어렵게 생각할 것 없이 '서빙 카트'나 '도시락 통'이라고 생각하면 됩니다.
- 손님이 주문한 데이터나, DB에서 꺼낸 데이터를 이리저리 옮길 때 내용물이 흐르지 않게 담는 전용 그릇(Class)입니다.
- 계층 간에 데이터를 주고받을 때는 DTO에 담아서 전달하는 것이 정석입니다.
마무리
오늘은 스프링 부트 개발의 뼈대인 3계층 구조를 배웠습니다.
- Controller: 웨이터 (입구 컷, 안내)
- Service: 셰프 (핵심 업무 처리)
- Repository: 창고지기 (DB 담당)
이 구조를 모르면 나중에 코드가 엉망진창(스파게티 코드)이 되어버립니다.
이제 직원들의 역할을 알았으니, 이들에게 "너는 웨이터고, 너는 셰프야"라고 명찰을 달아줘야겠죠?
다음 시간에는 이 명찰 역할을 하는 어노테이션(@)들에 대해 정리해 보겠습니다. 이걸 알면 코드를 볼 때 "아, 얘가 셰프구나!" 하고 바로 알 수 있게 됩니다.
다음 편에서 만나요! 👋
'IT > SpringBoot' 카테고리의 다른 글
| [Spring Boot 입문 - 3] 5분 컷! IntelliJ로 첫 프로젝트 만들고 실행하기 (0) | 2026.02.13 |
|---|---|
| [Spring Boot 입문 - 7] 어노테이션(@) 지옥 탈출! 자주 쓰는 핵심 5총사 정리 (0) | 2026.02.12 |
| [Spring Boot 입문 - 4] 스프링 부트 동작 원리: 요청(Request)이 들어오면 벌어지는 일 (0) | 2026.02.11 |
| [Spring Boot 입문 - 2] 자바 개발자의 필수템, IoC와 DI 완벽 이해하기 (0) | 2026.02.10 |
| [Spring Boot 입문 - 1] Spring과 Spring Boot, 도대체 뭐가 다를까? (0) | 2026.02.10 |
