Spring Boot
강의

#3 - 사고방식을 코드로 옮긴다는 것

중년개발자
중년개발자

@loxo

24일 전

31

사고방식을 코드로 옮긴다는 것

Spring 전문가 관점에서 본
"프론트를 믿지 않는 백엔드"를 Spring Boot 4로 구현하는 방법


1. Spring Boot는 구조를 강요하지 않는다 (그래서 더 위험하다)

Spring Boot는 빠르게 만들 수 있게 해주지만,
올바르게 만들게 강제하지는 않는다.

그래서 초보 단계에서는 흔히 이런 구조가 나온다.

controller └── service └── repository

그리고 모든 검증, 모든 판단, 모든 예외가 Service 하나에 쌓이기 시작한다.

👉 이 순간부터 사고방식과 구조가 어긋난다.


2. 사고방식 → 구조 변환의 핵심 원칙

백엔드 사고방식을 Spring Boot 구조로 옮길 때 전문가들이 공유하는 핵심 원칙은 단순하다.

✅ 원칙 1. "의심은 가장 바깥에서 시작한다"

  • HTTP 요청은 가장 위험하다
  • 따라서 Controller 레벨에서 1차 방어가 필요하다

✅ 원칙 2. "비즈니스 규칙은 중앙에 둔다"

  • Service는 흐름 제어자가 아니다
  • 규칙의 소유자

✅ 원칙 3. "데이터는 스스로를 지킨다"

  • Entity는 단순한 DTO가 아니다
  • 불변성과 상태 전이를 책임진다

3. Controller: 신뢰하지 않는 입구

Controller의 역할은 단 하나다.

"이 요청을 시스템 안으로 들일 자격이 있는가?"

3.1 Controller에서 해야 할 것

  • 요청 구조 검증 (형태)
  • 필수 값 검증
  • 인증/인가 컨텍스트 확보
java
@RestController @RequiredArgsConstructor class OrderController { private final OrderService orderService; @PostMapping("/orders") public ResponseEntity<Void> create(@Valid @RequestBody CreateOrderRequest req) { orderService.create(req); return ResponseEntity.ok().build(); } }

👉 @Valid프론트를 믿지 않겠다는 선언이다.


3.2 Controller에서 하면 안 되는 것

  • 비즈니스 판단
  • 상태 변경 로직
  • 계산

Controller가 똑똑해질수록, 시스템은 빠르게 무너진다.


4. DTO: 거짓을 담는 그릇

전문가 관점에서 DTO는 이렇게 정의된다.

"아직 믿지 않기로 한 데이터"

DTO 설계 원칙

  • Entity와 절대 1:1 매핑하지 않는다
  • 의미 없는 필드는 허용하지 않는다
java
public record CreateOrderRequest( @NotNull Long productId, @Positive int quantity ) {}

DTO에 검증이 많아질수록, Service는 더 순수해진다.


5. Service: 최종 심판

Service는 흐름을 처리하는 곳이 아니다.

Service는 비즈니스 규칙의 최종 심판이다.

java
@Service @RequiredArgsConstructor @Transactional class OrderService { private final ProductRepository productRepository; private final OrderRepository orderRepository; public void create(CreateOrderRequest req) { Product product = productRepository.findById(req.productId()) .orElseThrow(() -> new BusinessException("상품 없음")); Order order = Order.create(product, req.quantity()); orderRepository.save(order); } }

👉 Service는 **"이게 가능한가?"**만 묻는다.


6. Entity: 가장 신뢰받는 영역

Entity는 시스템에서 가장 안쪽에 있다.

그래서 오히려 가장 엄격해야 한다.

6.1 Entity는 setter를 갖지 않는다

java
@Entity class Order { @Id @GeneratedValue private Long id; private int quantity; protected Order() {} public static Order create(Product product, int quantity) { if (quantity <= 0) { throw new IllegalArgumentException("수량 오류"); } return new Order(product, quantity); } }

Entity가 스스로를 방어하지 못하면, 그 어떤 레이어도 안전하지 않다.


7. 예외 전략: 실패를 설계한다

초보자는 예외를 "처리"하려 하고, 전문가는 예외를 "설계"한다.

글로벌 예외 핸들링

java
@RestControllerAdvice class GlobalExceptionHandler { @ExceptionHandler(BusinessException.class) ResponseEntity<String> handle(BusinessException e) { return ResponseEntity.badRequest().body(e.getMessage()); } }

👉 예외는 정책이다.


8. Spring Boot 4에서 이 사고방식이 더 중요해진 이유

  • API 증가
  • 비동기 처리
  • 멀티 클라이언트 (Web / App / 외부)

이제 프론트는 하나가 아니다.

그래서 백엔드는 더 이상 가정하면 안 된다.


9. 전문가의 한 문장 정리

  • Controller는 의심한다
  • Service는 판단한다
  • Entity는 거부한다

Spring Boot 4는 이 역할 분리를 방해하지도, 대신해주지도 않는다.

결국 구조는 사고방식의 그림자다.


다음 단계에서는 이 구조를 기반으로
테스트, 트랜잭션 경계, 비동기 처리까지 확장한다.

목차

댓글 0

Ctrl + Enter를 눌러 등록할 수 있습니다
※ AI 다듬기는 내용을 정제하는 보조 기능이며, 최종 내용은 사용자가 확인해야 합니다.