ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 점진적 추상화 - 이승천
    세미나, 영상 요약정리 2023. 9. 26. 00:01

     

    https://www.inflearn.com/conf/infcon-2023

     

    인프콘 2023 - INFCON 2023

    인프런이 만드는 IT인의 축제, 인프콘으로 초대합니다. 인프콘과 함께 배우고 나누고 성장하세요. 다양한 발표 세션, 핸즈온, 네트워킹까지 만나보세요.

    inflearn.com

    인프콘 2023에서 점진적 추상화라는 주제로 발표한 토스증권의 이승천 님의 발표를 듣고 요약해보고자 합니다.

     

    발표의 목적

    하나의 예제를 통해 추가되는 요구사항에서 대응하며 느낀 추상화에서 느낀 주관적인 공유 합니다.

     

    요구사항

    • 원화/달러 입출금을 관리하는 시스템을 구축 중인 스타트업의 개발자
    • 내부 직원이 사용할 백오피스 입출금 API 개발
      • 입출금 요청 : 계좌번호, 입출금 타입(원화/달러), 금액
      • 기대동작: 요청내역 저장
      • 입출금 승인: 입출금 요청 객체 식별자
      • 기대동작: 타입별 입출금 실행

     

    심플한 구현

    원화 입금, 원화 출금, 달러 입금, 달러 출금이라는 타입으로 enum을 만들어서 if문을 통해 분기를 수행할 수 있습니다.

    이제 PR을 올리면 OCP에 위배되어 있는 코드로 보이며 확장에 열려있는 코드면 더욱 좋겠다는 피드백이 달립니다.

     

    타입을 축으로 추상화

    인터페이스를 만들고 4가지 형태의 구현체를 만들어냅니다.

    4개의 if문의 분기로직이 4가지 인터페이스의 구현클래스로 분리됩니다.

    if문으로 구현하는 것이 좋을까요? 추상화를 해서 구현하는 게 좋을까요?

     

    추가 요구사항!

    미국계좌는 미국지사 직원이 직접 트리거해야 합니다.

    달러 입출금은 승인과 처리를 분리해 주세요.

     

    if문에서는 process메서드를 만들어 달러 입출금을 분리해 낼 수 있습니다.

    하지만 인터페이스에서는 process라는 메서드가 추가되는 것이 자연스럽고, 이에 따른 4개의 구현체에 변경범위가 확대됩니다.

    즉, 인터페이스의 구현체를 추가하는 확장에는 열려있으나.. 인터페이스 자체를 변경하는 것을 쉽지 않습니다.

     

    어떤 방향으로 발전할 것인가?

    추상화를 두 가지 방향으로 할 수 있는데 위의 예제에서는 타입이 확장되었을 때 유리한 방향으로 추상화를 진행했었습니다.

    • 타입(원화 입출금, 달러 입출금)
    • 행위 (생성, 승인)

     

    하지만 행위가 확장되는 요구사항이 들어왔기 때문에 인터페이스를 변경해야 하는 일이 발생했습니다.

    소프트웨어 발전방향과 일치하는 추상화를 진행해야 하며 오히려 더 유지보수하기 힘든 코드가 탄생할 수 있습니다.

     

    현실에서는 매우 다양한 방향들이 있으며, 개발초기에 특정 방향으로 발전할 것이라 기대하고 추상화를 진행할 수 있습니다.

    하지만 구현과 소프트웨어 사이의 괴리가 점점 발생하게 되면 요구사항에 비해 훨씬 더 복잡한 코드가 되어 유지보수하기 어려운 코드가 됩니다.

     

    방향은 예측하기 쉽지 않다..

    추상화의 범위를 조금 좁혀보겠습니다.

    이전에는 create,  accepct를 추상화했다면 이번에는 코어로직인 승인만 추상화를 수행합니다.

     

    이렇게 되면 사용하는 서비스에서는 프로세서를 주입받거나 if문으로 선택하여 처리할 수 있게 됩니다.

     

    이제 다시 미국 계좌는 승인과 처리를 분리해야 한다는 요구사항을 처리해 보면 분기는 들어갈 수 있지만 인터페이스의 변경 없이 요구사항에 대응할 수 있습니다.

     

    여기서 얻을 수 있는 점은 너무 넓은 범위를 추상화하면 인터페이스의 변경되는 리스크에 노출됨

    따라서 인터페이스 추상화는 필요한 만큼만 진행하는지 점검해 보는 것이 좋습니다.

     

    끊임없는 요구사항

    • 인프콘 포인트 계좌가 추가되었습니다.
    • 인프콘 포인트도 입출금이 가능하도록 해주세요
    • 인프콘 포인트는 승인 즉시 입출금이 수행되어야 합니다.

    운이 좋게도 인프콘 포인트는 승인 즉시 입출금이 수행되어야 한다는 문장 때문에 인터페이스의 클래스를 만들어서 요구사항에 대응할 수 있습니다.

     

    만약 달러처럼 승인과 처리가 분리가 되어야 했다면..? 

     

    다시 한번 If문으로 돌아와서 요구사항에 대응한다면

    함수로 분리되어 있어 전체 흐름이 명확하게 보이는 장점이 있습니다.

    이제 계좌 기준으로 뭔가 묶여있는 게 보이고 이를 기준으로 추상화를 진행해 봅니다.

    때로는 날것의 코드가 좋은 인사이트를 주기도 합니다.

     

    3가지 Adapter로 사용해 보고, 하나의 인터페이스인 AccountAdapter를 바라보도록 구현할 수 있습니다.

     

     

    이전에 비해서 인터페이스의 메서드는 조금 더 많아졌지만 구현클래스는 6개에서 3개로 줄었습니다.

     

    오른쪽의 코드를 보면 입출금에 관련된 코드임이 더 잘 드러납니다.

    왼쪽을 읽었을 때 승인되면 "Processer의 process는 무엇을 하는 거지?" 라면  오른쪽을 읽었을 때는 승인이 되면 계좌 입출금에 관련된 로직을 수행하는구나를 알 수 있게 됩니다.

     

    트레이드오프의 개념이고 왼쪽에서는 process란 이름으로 조금 더 포괄적인 다른 기능을 추가할 수 있다면, 오른쪽의 코드는 행위를 명확하게 정해놓았다고 볼 수 있습니다.

     

    저는 개인적으로 오른쪽의 코드가 더 마음에 듭니다.

     

    끊임없는 요구사항

    • 환차손익 계산을 위해 달러 입금 시에는 환율정보를 기록해야 합니다.

    Adapter에는 deposit에서 환율이 추가되어야 하고 nullable 한 필드가 됩니다. (인프콘 포인트는 환차익이 없기 때문에)

     

    콜백 메서드 패턴으로 이를 활용할 수 있습니다. (함수를 파라미터로 받는다, like 람다식)

    함수가 일급 객체인 언어에서는 함수를 통해 전체 구현체의 변경 없이 구현체 별 시그니처를 독립적으로 가져갈 수 있습니다.

    (처음 문장을 읽었을 때는 잘 안 와닿습니다)

     

    인터페이스에 묶이지 않아도 하위 구현체들을 관리할 수 있게 됩니다.

    하지만 코드가 복잡해진다면 이것 역시 많은 분기문으로 복잡해질 수 있습니다.

     

     

    추상화에 대한 3줄 요약

    • 추상화는 비용이다 (혜택 없는 비용도 있을 수 있다)
    • 적절한 방향, 적절한 범위, 적절한 시기가 고민해야 한다
    • 함수를 추출하는 것부터 시작해서 점진적으로 추상화

     

    댓글

Designed by Tistory.