PHpullh
학습 라이브러리/Go/서비스 패턴

GO · 구조체/인터페이스

서비스 패턴

비즈니스 로직을 서비스 계층에 캡슐화합니다. 리포지토리와 조합하여 클린 아키텍처를 구현합니다.

구조체/인터페이스고급servicepatternbusiness-logicclean

핵심 설명

비즈니스 로직을 서비스 계층에 캡슐화합니다. 리포지토리와 조합하여 클린 아키텍처를 구현합니다.

Go code

package main

import (
	"errors"
	"fmt"
)

type Order struct {
	ID     int
	UserID int
	Total  float64
	Status string
}

type OrderRepo interface {
	Save(o *Order) error
	FindByID(id int) (*Order, error)
}

// 서비스: 비즈니스 로직 담당
type OrderService struct {
	repo OrderRepo
}

func NewOrderService(r OrderRepo) *OrderService {
	return &OrderService{repo: r}
}

func (s *OrderService) PlaceOrder(userID int, total float64) (*Order, error) {
	if total <= 0 {
		return nil, errors.New("주문 금액은 0보다 커야 합니다")
	}
	order := &Order{UserID: userID, Total: total, Status: "pending"}
	if err := s.repo.Save(order); err != nil {
		return nil, fmt.Errorf("주문 저장 실패: %w", err)
	}
	return order, nil
}

// 간단한 인메모리 구현
type memOrderRepo struct{ orders map[int]*Order; seq int }
func (r *memOrderRepo) Save(o *Order) error { r.seq++; o.ID = r.seq; r.orders[o.ID] = o; return nil }
func (r *memOrderRepo) FindByID(id int) (*Order, error) { o, ok := r.orders[id]; if !ok { return nil, errors.New("없음") }; return o, nil }

func main() {
	repo := &memOrderRepo{orders: make(map[int]*Order)}
	svc := NewOrderService(repo)
	order, _ := svc.PlaceOrder(1, 29900)
	fmt.Printf("주문 생성: %+v\n", *order)
}

학습 팁

서비스 메서드에서 에러를 래핑(%w)하면 호출자가 에러 원인을 추적할 수 있습니다.

주의할 점

서비스에서 HTTP 응답을 직접 작성하면 웹과 CLI 간 재사용이 불가합니다. 서비스는 순수 비즈니스 로직만 담당하세요.

자주 묻는 질문

서비스 패턴란 무엇인가요?

비즈니스 로직을 서비스 계층에 캡슐화합니다. 리포지토리와 조합하여 클린 아키텍처를 구현합니다.

서비스 패턴 학습 시 주의할 점은 무엇인가요?

서비스에서 HTTP 응답을 직접 작성하면 웹과 CLI 간 재사용이 불가합니다. 서비스는 순수 비즈니스 로직만 담당하세요.