제어 흐름 설계 철학 (Java vs Go)

Gihongg·2025년 12월 28일

Java와 Go로 개발하다 보니 묘한 생각이 들어 쓰는 글.
결론적으로 실패 처리의 소유권에 대한 이야기

1. 왜 제어 흐름 설계가 중요한가?

  • 비즈니스 로직은 "무엇을 하는가" 보다 "어떻게 읽히는가"가 중요
  • 같은 기능이라도 제어 흐름에 따라 아래의 요소들이 달라짐
    • 가독성
    • 유지보수성
    • 에러 추적 난이도
    • 코드 컨벤션

      2. 제어 흐름 설계의 두 가지 관점

      Happy Path (성공 경로 중심)

      정상적으로 동작하는 시나리오를 따라감

실패 시 예외로 처리

주로 Java, Spring 진영에서 사용

장점

비즈니스 로직 집중도가 높음

코드가 짧고 깔끔함

Spring의 @ControllerAdvice와 잘 어울림

단점

  • 예외 흐름을 모르면 전체 로직 이해가 어려움

  • 예외가 많아지면 추적이 힘들어짐

예시 코드

@Service
public class OrderService {

    public void placeOrder(String token, Long productId) {

        User user = authService.authenticate(token); // 실패 시 예외

        Product product = productService.getProduct(productId); // 없으면 예외

        orderValidator.validateOrderable(user, product); // 검증 실패 시 예외

        Order order = Order.create(user, product);
        orderRepository.save(order);
    }
}

Fail Fast (실패 조건 소거)

  • 실패 가능성은 초반에 모두 제거

  • 모든 에러는 명시적으로 처리

  • 숨겨진 흐름이 없음

장점

에러 발생 지점을 바로 알 수 있음

디버깅이 쉬움

함수의 계약(contract)이 명확

단점

코드가 길어질 수 있음

성공 흐름이 중간중간 끊겨 보일 수 있음

예시 코드

func PlaceOrder(token string, productID int64) error {

	user, err := auth.Authenticate(token)
	if err != nil {
		return err
	}

	product, err := product.Get(productID)
	if err != nil {
		return err
	}

	if !order.CanOrder(user, product) {
		return errors.New("order not allowed")
	}

	order := NewOrder(user, product)

	if err := repository.Save(order); err != nil {
		return err
	}

	return nil
}

두 철학의 근본적인 차이

항목Happy Path (Java)Fail Fast (Go)
실패 처리Exceptionerror 반환
흐름 중심성공 시나리오실패 제거
가독성비즈니스 중심조건 중심
에러 노출암묵적명시적
중첩적음거의 없음

사실상 언어가 철학을 강제한다고 볼 수 있다.

필자는 개인적으로 Go 방식이 더 마음에 들었다.

예외를 일일이 신경써야 하는 점이 개발할 때 피곤하기도 한데 그래서 좀 재밌는 면이 있는 것 같다. 원시적인 느낌...

profile
전천후 개발자

0개의 댓글