소프트웨어 개발의 역사는 끊임없는 추상화의 역사였다. 기계어를 벗어나 어셈블리어로, 고급 언어로, 프레임워크로, 이제는 클라우드 서비스와 AI 도우미까지. 각 단계에서 우리는 더 적은 코드로 더 많은 일을 할 수 있게 되었고, 그만큼 생산성은 높아졌다. 그런데 이상하게도, 그 추상화의 끝자락에서 만나는 것은 여전히 CRUD라는 이름의 반복 작업이다. Create, Read, Update, Delete. 네 개의 동사로 요약되는 이 패턴은 데이터베이스와 애플리케이션 사이의 기본적인 상호작용을 정의한다. 단순해 보이지만, 이 단순함이 오히려 문제를 일으킨다.
CRUD의 문제는 그것이 너무 직관적이어서, 그리고 너무 보편적이어서 아무도 그 한계를 의심하지 않는다는 데 있다. RESTful API의 시대에도, GraphQL이 등장한 후에도, 심지어 서버리스 아키텍처가 주류가 된 지금도, 대부분의 백엔드 시스템은 여전히 CRUD의 변형일 뿐이다. 사용자 프로필을 수정한다? Update. 게시물을 삭제한다? Delete. 주문을 조회한다? Read. 이 패턴은 개발자에게 친숙하고, 비즈니스 요구사항을 빠르게 구현할 수 있게 해주지만, 그만큼 시스템의 복잡성을 은폐한다.
예를 들어, “사용자 계정 비활성화”라는 단순한 요구사항을 생각해 보자. CRUD 관점에서 이는 Update 연산으로 구현될 것이다. is_active 필드를 false로 바꾸는 것. 하지만 실제 비즈니스 로직은 그보다 복잡하다. 계정이 비활성화되면 연관된 결제 정보는 어떻게 처리할까? 예약된 작업은 취소해야 할까? 다른 사용자와의 관계는 어떻게 정리할까? 이런 복잡성은 CRUD의 단순한 네 가지 연산으로는 표현되지 않는다. 결국 개발자는 이러한 규칙들을 서비스 레이어에 숨기게 되고, 그 결과 코드는 점점 더 두꺼워지며 유지보수가 어려워진다.
이 문제는 특히 마이크로서비스 아키텍처에서 더 두드러진다. 서비스가 작아질수록 각 서비스는 더 단순한 CRUD 인터페이스를 노출하게 되지만, 비즈니스 로직은 여러 서비스에 걸쳐 분산된다. 예를 들어, “주문 취소”라는 작업은 주문 서비스, 결제 서비스, 재고 서비스, 알림 서비스 등 여러 곳에 영향을 미친다. 각 서비스는 자신의 CRUD 연산을 수행하지만, 전체적인 일관성을 유지하기 위해서는 복잡한 보상 트랜잭션이나 사가 패턴이 필요하다. CRUD의 단순함은 여기서 오히려 장애물이 된다. 각 서비스가 독립적으로 동작하도록 설계되었지만, 비즈니스 프로세스는 독립적이지 않기 때문이다.
CRUD는 데이터베이스와 애플리케이션 사이의 계약이 아니라, 개발자와 비즈니스 요구사항 사이의 불일치를 숨기는 베일이다.
그렇다면 대안은 무엇일까? 이 글에서 제안하는 것은 “행위 기반 설계”다. 즉, 시스템이 수행해야 하는 실제 비즈니스 행위(예: “주문 취소”, “사용자 정지”, “구독 갱신”)를 중심으로 API를 설계하라는 것이다. 이는 REST의 리소스 중심 접근법과 대비된다. 예를 들어, 주문 취소는 PUT /orders/{id}/cancel과 같은 엔드포인트로 표현될 수 있다. 이 접근법의 장점은 비즈니스 로직이 API 레벨에서 명확히 드러난다는 점이다. 또한, 각 행위는 독립적으로 테스트되고 확장될 수 있다.
하지만 이 대안에도 한계는 있다. 행위 기반 설계는 API의 복잡성을 증가시킬 수 있으며, 특히 행위가 많아질수록 엔드포인트 수도 기하급수적으로 늘어날 수 있다. 또한, 이는 RESTful API의 표준에서 벗어나는 것이기 때문에, 기존 도구들과의 통합이 어려울 수 있다. 그럼에도 불구하고, 이 접근법은 시스템의 복잡성을 더 투명하게 드러내고, 비즈니스 요구사항과 기술 구현 사이의 간극을 좁히는 데 도움이 된다.
CRUD의 문제는 그것이 잘못되었다는 것이 아니다. 오히려 너무 옳아서, 그 한계를 보지 못하게 만든다는 것이 문제다. 개발자는 항상 더 나은 추상화를 찾아왔지만, CRUD는 그 추상화가 가져온 편리함에 안주하게 만든다. 하지만 시스템이 복잡해질수록, 그 편리함은 오히려 개발자의 발목을 잡는다. 이제 우리는 CRUD라는 이름의 베일을 걷어내고, 시스템이 실제로 해야 할 일을 직시해야 할 때다.
이 글이 제기하는 질문은 개발자에게 불편하지만 중요한 것이다. 우리가 매일 작성하는 코드가 비즈니스 문제를 해결하고 있는지, 아니면 그저 데이터베이스 테이블의 행을 조작하고 있는 것은 아닌지. 그 답은 아마도 둘 다일 것이다. 하지만 그 균형을 어떻게 잡을지는 여전히 개발자의 몫이다. 원문 링크
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.