비즈니스 로직(Business Logic)은 컴퓨터 프로그램에서 실제 비즈니스 규칙에 따라 데이터를 생성, 표시, 저장, 변경하는 핵심적인 부분으로, 서비스의 본질적인 동작 방식을 정의하는 코드입니다. 이는 UI(화면)나 DB(저장소)와는 구분되며, "주문 시 재고 차감"이나 "신규 회원 10% 할인"처럼 실제 업무 규칙을 구현하여 기술 환경이 바뀌어도 유지되는 핵심 논리를 의미합니다. - Gemini 3
예시 : 쇼핑몰
"회원 등급이 GOLD 이상이면 10% 할인, 쿠폰이 있으면 추가 5% 할인, 단 최대 할인율은 30%를 넘길 수 없다"
이것이 비즈니스 로직이다. DB에 어떻게 저장하는지, API응답을 어떻게 내려주는지는 비즈니슬 로직에 해당하지 않는다.
// 비즈니스 로직 — "무엇을, 왜" 하는가
public int calculateDiscount(Member member, Coupon coupon) {
int rate = 0;
if (member.getGrade().isAbove(Grade.GOLD)) rate += 10;
if (coupon != null && coupon.isValid()) rate += coupon.getRate();
return Math.min(rate, 30); // 최대 30%
}
// 기술 로직 — "어떻게" 처리하는가
orderRepository.save(order); // DB 저장
paymentGateway.requestPayment(amount); // PG사 API 호출
rabbitTemplate.send("order.created"); // 메시지 발행
| 구분 | 비즈니스 로직 | 기술(인프라)로직 |
|---|---|---|
| 질문 | "왜 이렇게 해야 하지?" | "어떻게 처리하지?" |
| 변경 주체 | 기획자 / PM이 요구 | 개발자가 판단 |
| 예시 | 할인 계산, 주문 검증, 등급 산정 등 | DB 쿼리, API 호출, 캐싱, 트랜잭션 등 |
| 바뀌는 시점 | 정책이 바뀔 때 | 기술 스택이 바뀔 때 |
결국 기획자가 이해할 수 있는 규칙이면 비즈니스 로직, 개발자만 이해하는 처리면 기술 로직 이다.
Q.비즈니스 로직은 말 그대로 '돈 되는 로직'이니까, 보안에 철저해야겠네요.
그렇다. 그리고 그 보안에는 단순히 암호화만 의미하는 것이 아니고, 비즈니스 로직 자체를 보호하는 여러 층위가 존재한다.
// Controller 계층 — 형식 검증
@PostMapping("/orders")
public ResponseEntity<?> createOrder(@Valid @RequestBody OrderRequest request) { }
// Entity/Service 계층 — 비즈니스 규칙 검증
public void applyDiscount(int rate) {
if (rate < 0 || rate > 30) {
throw new IllegalArgumentException("할인율은 0~30% 사이여야 합니다");
}
}
// 인증: 너 누구야? (로그인)
// 인가: 너 이거 할 수 있어? (권한)
@PreAuthorize("hasRole('ADMIN')")
public void cancelOrder(Long orderId) { }
// 또는 서비스에서 직접 검증
public void cancelOrder(Long memberId, Long orderId) {
Order order = orderRepository.findById(orderId).orElseThrow();
if (!order.isOwnedBy(memberId)) {
throw new AccessDeniedException("본인 주문만 취소 가능합니다");
}
}
애플리케이션 로직이 뚫려도 DB에서 막아주어야 한다.
-- 비즈니스 규칙을 DB 제약조건으로도 보장
ALTER TABLE orders ADD CONSTRAINT chk_amount CHECK (amount > 0);
ALTER TABLE members ADD CONSTRAINT uk_email UNIQUE (email);
클라이언트 (프론트) → UX용 검증 (신뢰하지 않음)
↓
Controller → 형식 검증 (@Valid), 인증 확인
↓
Service → 인가 확인, 비즈니스 규칙 검증, 트랜잭션
↓
Entity → 자기 상태 보호 (private 필드, 검증 로직)
↓
DB → 제약조건 (NOT NULL, UNIQUE, CHECK)
Q. MVC 패턴에서 비즈니스 로직은 언제 Entity에 작성하고, 언제 Service에 작성하는가?
A : 핵심 기준 - "이 로직이 자기 자신의 데이터만으로 완결되는가?"
엔티티에 넣는 경우
자기 자신의 필드만으로 판단/변경이 완결되는 로직
@Entity
public class Member {
private int loginFailCount;
private MemberStatus status;
// ✅ 자기 필드만 사용 → 엔티티에 작성
public void loginFailed() {
this.loginFailCount++;
if (this.loginFailCount >= 5) {
this.status = MemberStatus.BLOCKED;
}
}
public void changeNickname(String nickname) {
if (nickname.length() > 20) {
throw new IllegalArgumentException("닉네임은 20자 이하");
}
this.nickname = nickname;
}
}
서비스에 넣는 경우
다른 엔티티, 외부 시스템, repository 조회 등이 필요한 로직
@Service
@RequiredArgsConstructor
@Transactional
public class OrderService {
private final OrderRepository orderRepository;
private final MemberRepository memberRepository;
private final PaymentGateway paymentGateway; // 외부 시스템
// ✅ 여러 엔티티 + 외부 시스템 조합 → 서비스에 작성
public Long createOrder(Long memberId, Long productId, int quantity) {
Member member = memberRepository.findById(memberId)
.orElseThrow(() -> new IllegalArgumentException("회원 없음"));
Product product = productRepository.findById(productId)
.orElseThrow(() -> new IllegalArgumentException("상품 없음"));
Order order = Order.create(member, product, quantity); // 엔티티의 생성 로직
paymentGateway.requestPayment(order.getTotalPrice()); // 외부 API 호출
orderRepository.save(order);
return order.getId();
}
}
Entity
- 자기 필드만으로 완결
- 유효성 검증 (자기 데이터)
- 상태 변경 (자기 상태)
Service
- 다른 엔티티와 협력 필요
- Repository 조회 필요
- 외부 API / 시스템 호출
- 트랜잭션 조율