π[Backend Development] Java Spring νλ μμν¬μ κ³μΈ΅ - Business Layer(λΉμ¦λμ€ κ³μΈ΅)
β Business Layer (λΉμ¦λμ€ κ³μΈ΅)
-
μ£Όμ μ»΄ν¬λνΈ :
@Service
- μν : μ ν리μΌμ΄μ μ ν΅μ¬ λΉμ¦λμ€ λ‘μ§μ μ²λ¦¬ν©λλ€.
- μ€λͺ : μ¬μ©μμ μμ²μ λν μ€μ μμ (e.g, βκ²μκΈμ μ μ₯νλ€β, βμ¬μ©μ λ±κΈμ μ λ°μ΄νΈνλ€β)μ μνν©λλ€. μ¬λ¬ λ°μ΄ν° μ κ·Ό κ³μΈ΅μ κΈ°λ₯μ μ‘°ν©νμ¬ νλμ νΈλμμ μΌλ‘ λ¬Άκ±°λ, 볡μ‘ν κ³μ°μ μ²λ¦¬νλ λ± λΉμ¦λμ€μ βκ·μΉβκ³Ό βμ μ± βμ ꡬννλ λΆλΆμ λλ€.
β 1. ν΅μ¬ λΉμ¦λμ€ λ‘μ§ (Core Business Logic)
βμ΄ μλΉμ€λ₯Ό 무μ λλ¬Έμ μ¬μ©νλκ°?βλΌλ μ§λ¬Έμ λν λ΅μ μ½λλ‘ κ΅¬νν κ²μ
λλ€.
μ¦, μ ν리μΌμ΄μ
μ μ‘΄μ¬ μ΄μ μ΄μ ν΅μ¬ κΈ°λ₯ κ·Έ μ체λ₯Ό μλ―Έν©λλ€.
- κ°λ : λ°μ΄ν°λ₯Ό λ¨μν μ μ₯νκ³ λ³΄μ¬μ£Όλ κ²μ λμ΄, νΉμ λͺ©μ μ μν΄ λ°μ΄ν°λ₯Ό κ°κ³΅νκ³ μ²λ¦¬νλ λͺ¨λ κ³Όμ μ λλ€.
-
μμ (μΌνλͺ°) :
- βμ£Όλ¬Έ μ²λ¦¬β λ‘μ§: μ¬μ©μκ° βμ£Όλ¬ΈνκΈ°β λ²νΌμ λλ₯΄λ©΄, μμ€ν μ μνμ μ¬κ³ λ₯Ό νμΈνκ³ , μ¬μ©μμ μΏ ν°μ μ μ©νμ¬ μ΅μ’ κ²°μ κΈμ‘μ κ³μ°νκ³ , μ¬μ©μμ λ±κΈμ λ°λΌ ν¬μΈνΈλ₯Ό μ 립ν ν, λ°°μ‘ μ 보λ₯Ό μμ±ν©λλ€. μ΄ λͺ¨λ κ³Όμ μ μ‘°ν©μ΄ λ°λ‘ βμ£Όλ¬Έ μ²λ¦¬βλΌλ νλμ ν΅μ¬ λΉμ¦λμ€ λ‘μ§μ λλ€.
β 2. νΈλμμ (Transaction)
μλ‘ κ΄λ ¨λ μ¬λ¬ κ°μ μμ μ νλμ λ¬ΆμμΌλ‘ μ²λ¦¬νλ κ²μ μλ―Έν©λλ€. μ΄ λ¬Άμ μμ μμ λ€μ βλͺ¨λ μ±κ³΅νκ±°λ λͺ¨λ μ€ν¨ν΄μΌβ ν©λλ€ (All or Nothing).
- κ°λ : λ°μ΄ν°μ μΌκ΄μ±κ³Ό 무결μ±μ 보μ₯νκΈ° μν λ§€μ° μ€μν κΈ°λ₯μ λλ€. μ€κ°μ νλμ μμ μ΄λΌλ μ€ν¨νλ©΄, μ΄μ μ μ±κ³΅νλ λͺ¨λ μμ μ μλ μνλ‘ λλ립λλ€(Rollback).
-
μμ (κ³μ’ μ΄μ²΄) :
- Aμ κ³μ’μμ 1λ§ μμ μΆκΈνκ³ , Bμ κ³μ’μμ 1λ§ μμ μ κΈνλ κ²μ λ κ°μ μμ μ λλ€.
- λ§μ½ μΆκΈμ μ±κ³΅νλλ°, μμ€ν μ€λ₯λ‘ μ κΈμ΄ μ€ν¨νλ©΄ λμ΄ κ³΅μ€μΌλ‘ μ¬λΌμ§κ² λ©λλ€.
- βνΈλμμ
βμ μ΄ λ μμ
μ νλλ‘ λ¬Άμ΄, μ
κΈμ΄ μ€ν¨νλ©΄ μ±κ³΅νλ μΆκΈκΉμ§ μ·¨μμμΌ λ°μ΄ν°κ° νμ΄μ§λ κ²μ λ§μμ€λλ€. Springμμλ
@Transactional
μ΄λ Έν μ΄μ μΌλ‘ κ°λ¨νκ² μ μ©ν μ μμ΅λλ€.
β 3. λΉμ¦λμ€μ κ·μΉ (Business Rule)
μ ν리μΌμ΄μ
μ΄ λ°λΌμΌ νλ ꡬ체μ μ΄κ³ λͺ
νν 쑰건μ΄λ μ μ½μ¬νμ λ§ν©λλ€.
λ³΄ν΅ βμ°Έ/κ±°μ§βμΌλ‘ νλ³ν μ μλ λͺ
μ ννλ₯Ό λ±λλ€.
- κ°λ : λ°μ΄ν°λ νλ‘μΈμ€κ° μ ν¨ν μνλ₯Ό μ μ§νκΈ° μν κ°λ³μ μΈ κ²μ¬ νλͺ©μ λλ€.
-
μμ (μΌνλͺ°) :
- βνμκ°μ μ λΉλ°λ²νΈλ λ°λμ 8μ μ΄μμ΄μ΄μΌ νλ€.β
- βμνμ μ¬κ³ κ° 0μ΄λ©΄ βνμ β μνλ‘ νμν΄μΌ νλ€.β
- βλ―Έμ±λ μλ μ£Όλ₯λ₯Ό ꡬ맀ν μ μλ€.β
β 4. λΉμ¦λμ€μ μ μ± (Business Policy)
μ¬λ¬ λΉμ¦λμ€ κ·μΉλ€μ΄ λͺ¨μ¬μ λ§λ€μ΄μ§, λ λμ λ²μμ μ΄μ λ°©μΉ¨μ΄λ μ λ΅μ μλ―Έν©λλ€.
- κ°λ : νλμ κ·μΉμ΄λΌκΈ°λ³΄λ€λ, νΉμ μν©μμ λΉμ¦λμ€κ° μ΄λ»κ² μ΄μλ μ§μ λν μ λ°μ μΈ κ°μ΄λλΌμΈμ λλ€.
-
μμ (μΌνλͺ°) :
- βλ°°μ‘λΉ μ μ± β : βκΈ°λ³Έ λ°°μ‘λΉλ 3,000μμ΄λ€(κ·μΉ1). νμ§λ§, 5λ§ μ μ΄μ ꡬ맀 μ λ°°μ‘λΉλ 무λ£λ€(κ·μΉ2). λν, μ μ£Ό λ° λμ μ°κ° μ§μμ μΆκ° λ°°μ‘λΉ 5,000μμ΄ λΆλλ€(κ·μΉ3).β μ΄ κ·μΉλ€μ μ§ν©μ΄ βλ°°μ‘λΉ μ μ± βμ΄λΌλ νλμ μ μ± μ μ΄λ£Ήλλ€.
- βνλΆ μ μ± β : βꡬ맀 ν 7μΌ μ΄λ΄μλ§ νλΆμ΄ κ°λ₯νλ€(κ·μΉ1). μνμ ν¬μ₯μ΄ νΌμλμ§ μμμΌ νλ€(κ·μΉ2).β
β Serviceμ μν μ 무μμΈκ°μ?
Service
μ ν΅μ¬ μν μ λΉμ¦λμ€ λ‘μ§μ ꡬννλ κ²μ
λλ€. Controllerλ‘λΆν° μμ²μ λ°μ, λ°μ΄ν°λ₯Ό κ°κ³΅νκ±°λ μ¬λ¬ λ°μ΄ν° μμ€λ₯Ό μ‘°ν©νλ λ± μ€μ μ μΈ βμ
무βλ₯Ό μ²λ¦¬ν©λλ€.
- λΉμ¦λμ€ λ‘μ§ μ€μν : μ ν리μΌμ΄μ μ ν΅μ¬ λ‘μ§μ ν κ³³μ λͺ¨μ κ΄λ¦¬ν¨μΌλ‘μ¨ μ½λμ μΌκ΄μ±μ μ μ§νκ³ μ€λ³΅μ λ°©μ§ν©λλ€.
- νΈλμμ κ΄λ¦¬ : μ¬λ¬ λ°μ΄ν°λ² μ΄μ€ μμ μ νλμ λ¨μ(νΈλμμ )λ‘ λ¬Άμ΄ λ°μ΄ν°μ μΌκ΄μ±μ 보μ₯ν©λλ€. μλ₯Ό λ€μ΄, μΆκΈκ³Ό μ κΈμ΄ λͺ¨λ μ±κ³΅ν΄μΌλ§ κ³μ’μ΄μ²΄κ° μλ£λλλ‘ κ΄λ¦¬ν©λλ€.
-
Controllerμ Repository λΆλ¦¬ :
Service
λ Controllerκ° λΉμ¦λμ€ λ‘μ§μ μ§μ μμ§ λͺ»νκ² νκ³ , Repositoryκ° λ¨μν λ°μ΄ν° CRUD(μμ±, μ‘°ν, μμ , μμ )μλ§ μ§μ€νλλ‘ νλ μ€κ° λ€λ¦¬ μν μ μνν©λλ€.
β Serviceλ μΈμ μ¬μ©νλμ?
Controllerκ° λ°μ μμ²μ μ²λ¦¬νκΈ° μν΄ λ¨μν λ°μ΄ν° μ λ¬ μ΄μμ μμ μ΄ νμν λ μ¬μ©ν©λλ€.
- νλμ κΈ°λ₯μ΄ μ¬λ¬ λ°μ΄ν°λ² μ΄μ€ μμ μ νμλ‘ ν λ (e.g, κ²μκΈ μμ± μ κ²μκΈ μ μ₯ ν, μ¬μ©μ ν¬μΈνΈ μ λ°μ΄νΈ)
- λ°μ΄ν°λ₯Ό κ°κ³΅νκ±°λ λΉμ¦λμ€ κ·μΉμ μ μ©ν΄μΌν λ (e.g, μ¬μ©μ λμ΄λ₯Ό κ³μ°νκ±°λ, μ£Όλ¬Έ κΈμ‘μ λ°λΌ λ°°μ‘λΉλ₯Ό κ²°μ ν λ)
- νΈλμμ μ²λ¦¬κ° νμνμ¬ λ°μ΄ν°μ μμμ±(All or Nothing)μ 보μ₯ν΄μΌ ν λ
β Serviceλ μ΄λ»κ² μ¬μ©νλμ?
@Service
μ΄λ
Έν
μ΄μ
μ ν΄λμ€μ λΆμ¬ μ¬μ©νλ©°, λ°μ΄ν°λ² μ΄μ€ μ κ·Όμ μν΄ Repository
λ₯Ό μ£Όμ
λ°μ λΉμ¦λμ€ λ‘μ§μ ꡬνν©λλ€.
μλλ id
λ‘ μ¬μ©μλ₯Ό μ‘°ννλ, μμ κ²½μ° μμΈλ₯Ό λ°μμν€λ κ°λ¨ν Service
μμ μ½λμ
λλ€.
// μ΄ ν΄λμ€κ° λΉμ¦λμ€ λ‘μ§μ μ²λ¦¬νλ Serviceμμ μ μΈν©λλ€.
@Service
public class UserService {
// λ°μ΄ν°λ² μ΄μ€ μ κ·Όμ μν UserRepositoryλ₯Ό μ°κ²°ν©λλ€. (μμ‘΄μ± μ£Όμ
)
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRespository;
}
/**
* μ¬μ©μ IDλ‘ μ¬μ©μλ₯Ό μ‘°ννλ λ©μλ
* @Transactional(readOnly = true)λ μ΄ λ©μλκ° λ°μ΄ν°λ² μ΄μ€λ₯Ό μ½κΈ°λ§ νλ
* μμ
μ΄λ©°, μ½κ°μ μ±λ₯ μ΅μ νλ₯Ό μ 곡ν©λλ€.
*/
@Transactional(readOnly = true)
public User findUserById(Long id) {
// Repositoryλ₯Ό ν΅ν΄ IDλ‘ μ¬μ©μλ₯Ό μ°Ύκ³ ,
// λ§μ½ μ¬μ©μκ° μμΌλ©΄ μμΈλ₯Ό λ°μμν€λ 'λΉμ¦λμ€ λ‘μ§'μ μνν©λλ€.
return userRepository.findById(id)
.orElseThrow(() -> new IllegalArgumentException("ν΄λΉ μ¬μ©μκ° μμ΅λλ€. id=" + id));
}
}
// Controllerμμλ μ΄ Serviceλ₯Ό μ£Όμ
λ°μ μ¬μ©ν©λλ€.
@RestController
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/api/users/{id}")
public User getUserById(@PathVariable Long id) {
// Controllerλ λΉμ¦λμ€ λ‘μ§μ μ§μ μννμ§ μκ³ Serviceμ λ©μλλ₯Ό νΈμΆν©λλ€.
return userService.findUserById(id);
}
}
β 1. Business Layerλ μΈμ μ¬μ©νλμ?
μ ν리μΌμ΄μ
μ ν΅μ¬ κΈ°λ₯μ μνν΄μΌ ν λ νμ μ¬μ©ν©λλ€.
Controllerλ‘λΆν° μμ²μ λ°μ, λ¨μν λ°μ΄ν°λ₯Ό μ λ¬νλ κ²μ λμ΄ λ°μ΄ν°λ₯Ό κ°κ³΅νκ±°λ, λΉμ¦λμ€ κ·μΉμ μ μ©νκ³ , μ¬λ¬ λ¨κ³μ μμ
μ νλμ λ¬Άμ(νΈλμμ
)μΌλ‘ μ²λ¦¬ν΄μΌ ν λ μ΄ κ³μΈ΅μ΄ μ€μ¬μ μΈ μν μ ν©λλ€.
β 2. Business Layerλ μ΄λμ μ¬μ©νλμ?
μ ν리μΌμ΄μ
μν€ν
μ²μμ Presentation Layer(Controller)μ Data Access Layer(Repositoty) μ¬μ΄μ μ€κ° κ³μΈ΅μ μμΉν©λλ€.
μΈλΆμ μμ²μ μ²λ¦¬νλ λΆλΆκ³Ό λ°μ΄ν°λ² μ΄μ€μ μ§μ μ κ·Όνλ λΆλΆμ λΆλ¦¬νμ¬, κ·Έ μ¬μ΄μμ μ€μ§μ μΈ μ
무λ₯Ό μ²λ¦¬νλ βλλβμν μ λ΄λΉν©λλ€.
β 3. Business Layerλ μ΄λ»κ² μ¬μ©νλμ?
μ£Όλ‘ @Service
μ΄λ
Έν
μ΄μ
μ μ¬μ©νμ¬ ν΄λμ€λ₯Ό μ μνκ³ , μ΄ ν΄λμ€ μμμ λΉμ¦λμ€ λ‘μ§μ λ©μλλ‘ κ΅¬νν©λλ€.
-
@Service
ν΄λμ€λ λ°μ΄ν°λ² μ΄μ€ μ κ·Όμ μν΄@Repository
λ₯Ό μ£Όμ (Injection) λ°μ΅λλ€. - Controllerλ‘λΆν° μ λ¬λ°μ λ°μ΄ν°λ₯Ό μ¬μ©νμ¬, Repositoryλ₯Ό ν΅ν΄ λ°μ΄ν°λ₯Ό μ‘°ννκ±°λ μ μ₯ν©λλ€.
- λ°μ΄ν°λ₯Ό κ°κ³΅νκ³ , λΉμ¦λμ€ κ·μΉμ μ μ©νλ©°,
@Transactional
μ΄λ Έν μ΄μ μ ν΅ν΄ λ°μ΄ν° μ²λ¦¬μ μΌκ΄μ±μ 보μ₯ν©λλ€.
β 4. Business Layerλ μ μ¬μ©νλμ?
κ°μ₯ μ€μν μ΄μ λ κ΄μ¬μ¬μ λΆλ¦¬(Separation of Concerns) λ₯Ό ν΅ν΄ μ»λ μ¬λ¬ μ΄μ λλ¬Έμ λλ€.
- μ μ§λ³΄μμ± ν₯μ : λΉμ¦λμ€ μ μ± (e.g, ν μΈμ¨ λ³κ²½)μ΄ λ°λ λ, λ€λ₯Έ κ³μΈ΅μ 건λλ¦¬μ§ μκ³ Business Layerμ κ΄λ ¨ μ½λλ§ μμ νλ©΄ λλ―λ‘ κ΄λ¦¬κ° λ§€μ° μ©μ΄ν©λλ€.
- μ½λ μ¬μ¬μ©μ± μ¦κ° : νλμ λΉμ¦λμ€ λ‘μ§(e.g, νμκ°μ )μ λ§λ€μ΄μ£Όλ©΄, μΉ Controller, λͺ¨λ°μΌ API Controller λ± μ¬λ¬ κ³³μμ ν΄λΉ Serviceλ₯Ό νΈμΆνμ¬ μ¬μ¬μ©ν μ μμ΅λλ€.
- νΈλμμ κ΄λ¦¬ : μ¬λ¬ κ°μ λ°μ΄ν°λ² μ΄μ€ λ³κ²½ μμ μ νλμ λ Όλ¦¬μ μΈ λ¨μλ‘ λ¬Άμ΄ μ²λ¦¬νκΈ°μ κ°μ₯ μ ν©ν μμΉμ λλ€. μ΄λ₯Ό ν΅ν΄ λ°μ΄ν°μ μ ν©μ±μ μμ νκ² μ§ν¬ μ μμ΅λλ€.
- ν μ€νΈ μ©μ΄μ± : μΉ μλ²λ λ°μ΄ν°λ² μ΄μ€ μμ΄λ μμ λΉμ¦λμ€ λ‘μ§ μ체μ μ νμ±μ λ 립μ μΌλ‘ ν μ€νΈνκΈ° νΈλ¦¬ν©λλ€.