역할의 완벽한 분리: Handler, Service, Repository
코드가 꼬이지 않도록 HTTP 요청, 비즈니스 로직, 데이터베이스 접근으로 역할을 명확히 나누는 계층 분리 원칙을 학습합니다.
이전 회차에서 우리는 `internal` 폴더 안에 `user`, `post`처럼 주제별로 방을 만들었습니다. 그렇다면 `user` 폴더 안에는 무슨 파일들이 있어야 할까요? 유저가 웹에서 로그인 버튼을 누르고 DB에서 정보가 조회되어 응답이 나가기까지, 이 일련의 과정들을 하나의 긴 코드에 다 욱여넣으면 코드는 재앙이 됩니다. 코드를 깨끗하게 유지하려면 공장의 컨베이어 벨트처럼 역할을 철저하게 4가지 직업군으로 쪼개야 합니다. 실무 백엔드 개발의 척추와도 같은 Model, Repository, Service, Handler의 역할을 파헤쳐 봅시다.
데이터의 생김새를 정의하다: 모델 (Model / Entity)
공장의 컨베이어 벨트 위를 굴러가는 '부품'의 설계도입니다. 이곳에는 지난 시간에 배운 구조체(Struct)가 위치합니다. "유저란 무엇인가? 유저는 숫자 ID, 문자 이름, 문자 이메일로 이루어져 있다"라고 뼈대를 정의합니다. 이 모델 설계도가 나머지 3개의 층을 넘나들며 배달됩니다.
영원한 데이터의 창고지기: 레포지토리 (Repository)
레포지토리는 데이터베이스(PostgreSQL) 창고 문을 열고 닫을 수 있는 유일한 창고지기입니다.
이 계층에는 `INSERT`, `SELECT` 같은 SQL 쿼리문들이 집중적으로 모여 있습니다. 만약 나중에 데이터베이스를 PostgreSQL에서 MySQL로 바꾸게 된다면, 우리는 이 창고지기(Repository) 코드만 수정하면 되고 다른 계층은 전혀 건드릴 필요가 없습니다.
Repository 계층의 절대 규칙
- 1레포지토리는 오직 '창고에 물건 넣기', '창고에서 물건 빼오기' 역할만 합니다.
- 2이곳에서 '비밀번호가 맞는지 틀린지' 검사하는 등의 똑똑한 판단을 내리게 해서는 절대 안 됩니다. 창고지기는 판단하지 않습니다.
핵심 업무 규칙의 뇌: 서비스 (Service)
백엔드 서버의 가장 똑똑한 뇌이자, 핵심 비즈니스 로직을 담당하는 실질적인 일꾼입니다.
서비스는 핸들러에게 "유저가 이런 정보를 줬어"라고 전달받으면, 깐깐하게 검사를 시작합니다. "비밀번호가 8자리가 넘는가? (검사) -> 이미 가입된 이메일인가? (창고지기에게 물어봄) -> 비밀번호를 암호화하자 (계산) -> 다 끝났으니 창고지기(Repository)에게 저장하라고 시켜야지!"
바이브코딩으로 버그가 터졌을 때 여러분이 가장 많이 열어보고 뜯어고쳐야 할 파일이 바로 이 Service 계층의 코드입니다.
웹과의 소통을 담당하는 문지기: 핸들러 (Handler / Controller)
핸들러는 프론트엔드(웹브라우저, 스마트폰 앱)와 가장 먼저 맞닿아 있는 문지기입니다.
문지기는 인터넷을 타고 날아온 복잡한 HTTP 요청(JSON 데이터)을 뜯어서 예쁜 Go 언어 구조체로 포장한 뒤, "이런 요청이 왔습니다!" 하고 똑똑한 뇌(Service)에게 던져줍니다. 그리고 Service가 일을 마치고 결과를 주면, 문지기는 다시 웹이 알아들을 수 있는 언어(JSON)로 포장하여 유저의 화면으로 쏴줍니다.
4계층 아키텍처의 데이터 흐름 (로그인 예시)
웹 브라우저 (유저)
JSON 데이터 전송
핸들러 (Handler)
핸들러 (Handler)
아이디/비번 포장 후 전달
서비스 (Service)
서비스 (Service)
이 아이디 가진 유저 찾아와!
레포지토리 (Repository)
레포지토리 (Repository)
SQL로 조회 (SELECT)
PostgreSQL 데이터베이스
AI 코딩 시 빈번하게 발생하는 끔찍한 혼종
오해 또는 실수
문지기가 창고 문을 열기
바로잡기
가끔 AI가 Handler 파일 안에서 HTTP JSON을 뜯자마자 곧바로 SQL 쿼리(DB 접근)를 쏴버리는 끔찍한 코드를 짭니다. 이 구조는 나중에 절대로 재사용할 수 없습니다.
오해 또는 실수
똑똑해진 창고지기
바로잡기
Repository 파일 안에서 비밀번호를 암호화하거나 이메일 형식을 검사합니다. 창고지기는 창고만 관리해야 합니다. 암호화는 반드시 Service 파일로 옮기라고 지시하세요.
오해 또는 실수
해결책 지시 프롬프트
바로잡기
AI에게 '로직이 너무 섞여 있어. Handler는 HTTP 요청/응답만 처리하고, 핵심 로직은 Service로 빼고, DB 접근은 Repository로 철저하게 분리해서 코드를 다시 짜줘'라고 꾸짖어야 합니다.
역할의 완벽한 분리 예시
우리가 `internal/user` 폴더를 열었을 때 `user_handler.go`, `user_service.go`, `user_repository.go` 세 개의 파일이 나란히 놓여 있다면, 여러분은 이미 실무에서 가장 깔끔한 백엔드 아키텍처를 구축한 것입니다.
개념 퀴즈
퀴즈 답을 맞춰야 학습 완료가 됩니다.AI가 작성한 백엔드 코드를 검수하고 있습니다. 사용자가 입력한 게시글 제목에 욕설이 포함되어 있는지 검열하고, 유저의 하루 작성 한도를 초과하지 않았는지 확인하는 '비즈니스 로직'이 가득 담겨야 하는 가장 올바른 계층(파일)은 어디인가요?
3줄 요약
- 1코드를 한 파일에 섞어 짜지 않고, 데이터 구조(Model), DB 접근(Repository), 핵심 논리(Service), HTTP 통신(Handler) 4가지 역할로 쪼개어 관리합니다.
- 2핸들러는 프론트엔드와의 통신(JSON)만 담당하고, 레포지토리는 DB와 소통하는 SQL 구문만 관리해야 결합도가 낮아져 유지보수가 편해집니다.
- 3바이브코딩 시 AI가 핸들러에서 직접 DB를 찌르는 등 역할을 침범하면, 즉시 'Service와 Repository로 역할을 철저히 분리하라'고 지시해야 합니다.