Spring Bootμ μμΈ μ²λ¦¬ μλ²½ κ°μ΄λ: κΈλ‘λ² μμΈ μ²λ¦¬ μ λ΅κ³Ό 컀μ€ν μλ¬ λ©μμ§ κ΅¬ν
Spring Boot μ ν리μΌμ΄μ
κ°λ°μμ μ€μν λΆλΆ μ€ νλλ μλ¬ μ²λ¦¬(μμΈ μ²λ¦¬) μ
λλ€. μ μ ν μμΈ μ²λ¦¬λ₯Ό ν΅ν΄ μ¬μ©μμκ² μ μ©ν μλ¬ λ©μμ§λ₯Ό μ 곡 νκ³ , μλΉμ€μ μμ μ±μ λμΌ μ μμ΅λλ€. μ΄λ² ν¬μ€ν
μμλ
@ControllerAdvice
μ
@ExceptionHandler
λ₯Ό νμ©ν μμΈ μ²λ¦¬ , κΈλ‘λ² μμΈ μ²λ¦¬ μ λ΅ , κ·Έλ¦¬κ³ API μλ΅μ 컀μ€ν
μλ¬ λ©μμ§λ₯Ό μ λ¬νλ λ°©λ² μ μμλ΄
λλ€.
λͺ©μ°¨
- Spring Boot μμΈ μ²λ¦¬μ κΈ°λ³Έ κ°λ
-
@ControllerAdvice
μ@ExceptionHandler
λ₯Ό νμ©ν μμΈ μ²λ¦¬ - κΈλ‘λ² μμΈ μ²λ¦¬ μ λ΅
- API μλ΅μ 컀μ€ν μλ¬ λ©μμ§ μ λ¬νκΈ°
- μλ¬ μ²λ¦¬μ μ€μμ±κ³Ό μ΅μ νΈλ λ
1. Spring Boot μμΈ μ²λ¦¬μ κΈ°λ³Έ κ°λ
μ ν리μΌμ΄μ
μ΄ μ€ν λμ€ μκΈ°μΉ μμ μμΈ(Exception) λ₯Ό λ§λλ©΄, μ΄λ₯Ό μ μ ν μ²λ¦¬νμ§ μμΌλ©΄ μλ²κ° μ€λ¨λκ±°λ μλͺ»λ μλ΅μ λ°νν μ μμ΅λλ€. Spring Bootλ μ€νλ§ μνλ¦¬ν° μ ν¨κ» μμΈ μ²λ¦¬λ₯Ό μν λꡬλ₯Ό μ 곡νλ©°, λνμ μΌλ‘
@ControllerAdvice
μ
@ExceptionHandler
κ° μμ΅λλ€.
μμΈ μ²λ¦¬μ νμμ±
- μ¬μ©μ κ²½ν ν₯μ : μ§κ΄μ μΈ μλ¬ λ©μμ§ μ 곡
- μλΉμ€ μμ μ± λ³΄μ₯ : μλ¬κ° λ°μν΄λ μ ν리μΌμ΄μ μ΄ μ€λ¨λμ§ μλλ‘ λ³΄νΈ
- λλ²κΉ μ©μ΄ : λ‘κ·Έμ μμΈν μλ¬ μ 보λ₯Ό κΈ°λ‘νμ¬ λ¬Έμ λ₯Ό λΉ λ₯΄κ² ν΄κ²°
2.
@ControllerAdvice
μ
@ExceptionHandler
λ₯Ό νμ©ν μμΈ μ²λ¦¬
@ControllerAdvice
λ?
@ControllerAdvice
λ λͺ¨λ 컨νΈλ‘€λ¬μμ λ°μνλ μμΈλ₯Ό μ μμ μΌλ‘ μ²λ¦¬ ν μ μλλ‘ λμμ£Όλ μ λν
μ΄μ
μ
λλ€. κ° μ»¨νΈλ‘€λ¬μμ κ°λ³μ μΌλ‘ μμΈ μ²λ¦¬λ₯Ό ꡬνν νμ μμ΄, μ μ μμΈ μ²λ¦¬ ν΄λμ€ μμ μ²λ¦¬ν μ μμ΅λλ€.
μμ μ½λ: μμΈ μ²λ¦¬ ꡬννκΈ°
UserNotFoundException.java (컀μ€ν μμΈ)
package com.example.demo.exception;
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
GlobalExceptionHandler.java (κΈλ‘λ² μμΈ μ²λ¦¬)
package com.example.demo.handler;
import com.example.demo.exception.UserNotFoundException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserNotFoundException.class)
public ResponseEntity<Map<String, Object>> handleUserNotFoundException(UserNotFoundException ex) {
Map<String, Object> response = new HashMap<>();
response.put("timestamp", LocalDateTime.now());
response.put("message", ex.getMessage());
response.put("status", HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(response, HttpStatus.NOT_FOUND);
}
}
μ½λ μ€λͺ
-
@ControllerAdvice
: λͺ¨λ 컨νΈλ‘€λ¬μ μμΈλ₯Ό μ²λ¦¬νλ ν΄λμ€μμ μ μΈν©λλ€. -
@ExceptionHandler
: νΉμ μμΈλ₯Ό μ²λ¦¬νλ λ©μλμ μ¬μ©ν©λλ€. -
ResponseEntity
: HTTP μν μ½λμ ν¨κ» 컀μ€ν μλ¬ λ©μμ§λ₯Ό λ°νν©λλ€.
3. κΈλ‘λ² μμΈ μ²λ¦¬ μ λ΅
Spring Bootμμλ λͺ¨λ 컨νΈλ‘€λ¬μμ λ°μν μ μλ μμΈλ₯Ό κΈλ‘λ²νκ² μ²λ¦¬ ν μ μμ΅λλ€. μ΄λ μ¬μ©λλ μ λ΅μ μλμ κ°μ΅λλ€:
μμΈ μ²λ¦¬ μ λ΅ | μ€λͺ | μμ |
---|---|---|
κΈλ‘λ² μμΈ μ²λ¦¬ |
@ControllerAdvice
λ‘ λͺ¨λ μμΈλ₯Ό μ²λ¦¬ν¨ |
λͺ¨λ 컨νΈλ‘€λ¬μ μμΈλ₯Ό νλμ ν΄λμ€μμ μ²λ¦¬ |
νΉμ μμΈ μ²λ¦¬ |
@ExceptionHandler
λ‘ νΉμ μμΈλ₯Ό μ²λ¦¬ν¨ |
UserNotFoundException
μ²λ¦¬ |
HTTP μν μ½λ 맀ν | μμΈμ λ§λ μν μ½λλ₯Ό λ°ν | 404: 리μμ€ μμ |
컀μ€ν μλ¬ λ©μμ§ | μλ¬ λ©μμ§μ μ¬μ©μ μ μ μ 보 μΆκ° | μ¬μ©μ IDκ° μλ κ²½μ° “μ¬μ©μ μμ” λ©μμ§ |
4. API μλ΅μ 컀μ€ν μλ¬ λ©μμ§ μ λ¬νκΈ°
컀μ€ν μλ¬ λ©μμ§ ν¬ν¨ μμ
μλλ μ¬μ©μ μ‘°ν APIμμ μ‘΄μ¬νμ§ μλ μ¬μ©μ IDλ‘ μμ²ν κ²½μ° μμΈλ₯Ό μ²λ¦¬νκ³ , 컀μ€ν λ©μμ§λ₯Ό μλ΅μΌλ‘ 보λ΄λ μμ μ λλ€.
UserController.java (μ¬μ©μ API 컨νΈλ‘€λ¬)
package com.example.demo.controller;
import com.example.demo.entity.User;
import com.example.demo.exception.UserNotFoundException;
import com.example.demo.repository.UserRepository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Optional;
@RestController
public class UserController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping("/users/{id}")
public User getUserById(@PathVariable Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("μ¬μ©μλ₯Ό μ°Ύμ μ μμ΅λλ€. ID: " + id));
}
}
μ μΆλ ₯ μμ
μμ² :
GET /users/999
μλ΅ :
{
"timestamp": "2024-10-13T12:34:56.789",
"message": "μ¬μ©μλ₯Ό μ°Ύμ μ μμ΅λλ€. ID: 999",
"status": 404
}
5. μλ¬ μ²λ¦¬μ μ€μμ±κ³Ό μ΅μ νΈλ λ
- μλ¬ μ²λ¦¬λ μ¬μ©μ κ²½νμ μ§κ²° λ©λλ€. μ μ ν λ©μμ§λ₯Ό μ 곡νμ§ μμΌλ©΄ μ¬μ©μλ νΌλμ λλ μ μμ΅λλ€.
- API μλ΅ μΌκ΄μ± : λͺ¨λ μλ¬ λ©μμ§λ₯Ό μΌκ΄λ νμμΌλ‘ μ 곡νλ κ²μ΄ μ€μν©λλ€.
- λ‘κ·Έμ λͺ¨λν°λ§ : μλ¬λ₯Ό λ‘κ·Έμ κΈ°λ‘νκ³ λͺ¨λν°λ§ λꡬμ μ°λν΄ μ€μκ°μΌλ‘ νμΈνλ κ²μ΄ νΈλ λμ λλ€.
- 컀μ€ν μμΈ μ²λ¦¬ μ ν¨κ» Spring Boot Actuator λ₯Ό μ¬μ©ν΄ μλ¬ μ 보λ₯Ό μ€μκ°μΌλ‘ λͺ¨λν°λ§νλ μ¬λ‘λ λμ΄λκ³ μμ΅λλ€.
κ΄λ ¨ λ§ν¬
Spring Boot μμΈ μ²λ¦¬ κ°μ΄λπ
Spring Boot Actuatorλ‘ λͺ¨λν°λ§ νκΈ°π
JUnitμ μ¬μ©ν μμΈ μ²λ¦¬ ν μ€νΈπ
FAQ
1. κΈλ‘λ² μμΈ μ²λ¦¬μ κ°λ³ μμΈ μ²λ¦¬μ μ°¨μ΄μ μ 무μμΈκ°μ?
- κΈλ‘λ² μμΈ μ²λ¦¬λ λͺ¨λ 컨νΈλ‘€λ¬μ μμΈ λ₯Ό ν κ³³μμ μ²λ¦¬νκ³ , κ°λ³ μμΈ μ²λ¦¬λ νΉμ 컨νΈλ‘€λ¬μμλ§ μ²λ¦¬ν©λλ€.
2. API μλ΅μ JSON νμμΌλ‘ μλ¬λ₯Ό λ°ννλ €λ©΄ μ΄λ»κ² νλμ?
ResponseEntity
λ₯Ό μ¬μ©ν΄ JSON νμμ 컀μ€ν λ©μμ§λ₯Ό λ°νν μ μμ΅λλ€.
3.
@ExceptionHandler
λ₯Ό μ¬λ¬ λ² μ¬μ©ν μ μλμ?
- λ€, ν ν΄λμ€μμ μ¬λ¬ μ’
λ₯μ μμΈλ₯Ό μ²λ¦¬νκΈ° μν΄ μ¬λ¬ κ°μ
@ExceptionHandler
λ©μλ λ₯Ό μ μΈν μ μμ΅λλ€.
4. 컀μ€ν μμΈλ₯Ό μΈμ μ¬μ©ν΄μΌ νλμ?
- λΉμ¦λμ€ λ‘μ§μ λ§λ λͺ νν μλ¬ μ²λ¦¬κ° νμν λ 컀μ€ν μμΈλ₯Ό μ μ ν΄ μ¬μ©νλ κ²μ΄ μ’μ΅λλ€.
5. Spring Bootμμ λ°μν μμΈλ₯Ό λ‘κ·Έμ κΈ°λ‘νλ €λ©΄ μ΄λ»κ² νλμ?
- Logger λ₯Ό μ¬μ©ν΄ μμΈ λ°μ μ λ‘κ·Έλ₯Ό λ¨κΈ°κ³ , λͺ¨λν°λ§ λꡬμ μ°λν΄ μ€μκ°μΌλ‘ νμΈν μ μμ΅λλ€.
λ§λ¬΄λ¦¬
μ΄λ² ν¬μ€ν μμλ Spring Bootμ μμΈ μ²λ¦¬ μ λ΅ μ μμΈν μ΄ν΄λ³΄μμ΅λλ€. κΈλ‘λ² μμΈ μ²λ¦¬ μ 컀μ€ν μμΈ λ©μμ§ λ μ ν리μΌμ΄μ μ μμ μ± κ³Ό μ¬μ©μ κ²½ν μ κ°μ νλ μ€μν μμμ λλ€. Spring Bootμ Spring Security λ₯Ό μ¬μ©νλ κ²½μ°μλ, λ€μν μμΈ μν©μ λ§μΆ μ κ΅ν μμΈ μ²λ¦¬ μ λ΅ μ νμμ μ λλ€.
μ΄μ μ¬λ¬λΆμ νλ‘μ νΈμ κΈλ‘λ² μμΈ μ²λ¦¬μ 컀μ€ν λ©μμ§ λ₯Ό λμ ν΄λ³΄μΈμ. μ΄λ₯Ό ν΅ν΄ API μλ΅μ μΌκ΄μ± μ μ μ§νκ³ , μ¬μ©μκ° λͺ ννκ² μ΄ν΄ν μ μλ μλ¬ λ©μμ§λ₯Ό μ 곡ν μ μμ΅λλ€. μ μ ν λ‘κ·Έ κ΄λ¦¬μ λͺ¨λν°λ§ λ ν¨κ» λμ νλ©΄ μλΉμ€μ μμ μ±μ νμΈ΅ λ λμΌ μ μμ΅λλ€.
λκΈ