정적 기록자는 이제 그만

수십년간 적응력있는 소프트웨어를 만들기 위한 노력이 지속되고 있다. 우리는 많은 원칙들과 패턴들을 도출했고 또 일부는 퇴출시켰다. 도메인은 가장 높은 적응력을 가져야 하는 소프트웨어 구성요소로 거론되고 있다. 간혹 도메인을 호스팅하는 웹 응용프로그램 코드가 도메인 코드보다 물리적으로 더 큰 비중을 차지하더라도 도메인의 중요성은 여전히 가장, 그리고 월등히, 높다.

아키텍처는 점점 다양해지고 그 수명은 점점 짧아진다. 변화하는 비즈니스 상황에 따라 동일한 도메인 논리는 다양한 호스팅 환경으로 확산되어 구동된다. 서비스 초기에는 단순한 웹 응용프로그램 호스트면 충분하다. 그러다 아마 곧 반응성에 대한 사용자들의 불만이 생겨날 것이고, 도메인 구성요소의 일부를 작업자 프로세스로 이동시켜 비동기적으로 실행해 반응성을 높여야 한다. 서비스가 성장하면 이제 도메인은 외부 서비스들과 교류하게 되고 개방형 API와 웹 훅을 통해 도메인 논리가 트리거된다. 아, 그렇지! 지금은 클라우드 시대다. FaaS(Function as a Service)를 빠뜨릴 수 없다. 다시 한 번 언급하면 도메인 논리는 동일하다. 외부 변화에 따라 다른 아키텍처로 이동되거나 확산될 뿐이다.

물론 상당수의 서비스는 성장하지 못하고 생을 다한다. 하지만 성장의 기회가 왔을 때 정적 기록자(static logger) 변수 따위가 도메인의 발목을 잡는다면 모습이 우스을 것이다. 그것도 화려하고 무거운 무언가를 도입하는 것이 아니라 고작 담백한 한 두 줄 코드 추가가 부담되어 그랬다면 말이다.

예를 들어보자. 클라우드 작업자 호스트 서비스나 FaaS는 간단하게 도메인을 호스팅한다. 작은 연산 단위로 격리된 절차가 수행되고 이것들의 조합이 시스템을 이룬다. 호스트는 각 연산마다 독립된 기록자를 제공하고 모든 연산의 수행 과정은 개별 파일에 독립적으로 기록이 남는다. 수행된 연산 목록 중 실패했거나 조사가 필요한 것을 발견했다면 당신은 그저 해당 연산의 기록이 담긴 텍스트 파일 하나를 열어보면 된다.

[QueueTrigger("job-queue")]
public static void ProcessPayload(string payload, ILogger logger)
{
    var domain = AssembleModule<DomainModule>(logger);
    domain.Run(payload);
}

도메인 모듈이 명시적으로 공유된 정적 기록자 변수에 중요한 이벤트를 기록하도록 되어있다면,

public class DomainModule
{
    private static readonly ILogger _staticLogger = GetLogger();
}

어쩌면 그것들이 모두 증발해 버렸거나 어딘가에 기록되었더라도 당신은 수많은 프로세스와 스레드가 경쟁적으로 섞어놓은 문자들의 더미 속에서 단서를 조합하기 위해 수고할 것이다. 그에 앞서 GetLogger() 메서드가 실패할 가능성도 높다.

반면 기록자에 의존관계 역전 원칙(dependency inversion principle)을 적용했다면,

public class DomainModule
{
    private readonly ILogger _logger;

    public DomainModule(ILogger logger)
    {
        _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }
}

당신의 도메인 모듈은 호스팅 환경이 제공하는 기능을 멋지게 활용해 당신에게 양질의 피드백을 제공한다. 당신은 그저 조사하고 싶은 연산의 기록 파일을 더블클릭하기만 하면 된다.

테스트 케이스 또한 각각 아주 유용한 도메인 호스트 응용프로그램이다. 기록자에 의해 기록되는 이벤트 중 일부는 도메인의 주요 특징(feature)이고 테스트 대상이다. 정적 변수에 담긴 자원은 테스트 케이스에게는 공유 메모리 모델 만큼이나 아주 곤욕스러운 대상이다. 특히 병렬 테스팅에서는 더욱 그렇다.

특정 응용프로그램 플랫폼이나 프레임워크는 정적 기록자 변수를 지원한다. 그런데, 만약 당신의 도메인이 그것에 종속된다면 다양한 원칙과 멋진 패턴들은 얼마나 가치가 있을까? 계층을 나누고 결합도를 낮추어 무엇을 얻을까? 그저 작은 컨트롤러 하나면 모두 구현할 수 있는 것은 아닐까? 이것을 과도한 우려라고 말하기에는 도메인 설계를 정적 기록자 변수로부터 보호하는 방법은 너무나 소박하고 평범하다(plain-old). 적응력있고(adaptive) 확장성을 가지며(scalable) 테스트하기 쉬운(testable) 도메인을 원한다면 정적 기록자는 이제 그만 버리자.

정적 기록자는 이제 그만”에 대한 4개의 생각

  1. jino

    잘읽었습니다. 디자인과 아키텍처에 대한 이야기가 요즘 공부하는 것들을 정리해준 것 같아 도움이 됐습니다.
    아직 테스트를 잘 몰라서 정적인게 어떤 어려움이 있는지는 모르겠네요. 테스트를 공부하고 다시 읽으러 와야할 것 같아요.
    지금 하고 계신 아키텍처에 대한 이야기 공유도 기대하고 있을게요.

    응답
  2. 권남

    안녕하세요, 이 게시물에 대한 의견을 제 facebook에 남겼습니다.

    내용도 길고, 제 개인의견으로 제 타임라인에 남겨놓고 싶어서 제 페북에 쓰고, 댓글로 따로 달지는 않았으나 함께 논의해보는 것도 좋을 것 같아서 공유합니다.

    응답
    1. Gyuwon 글의 글쓴이

      읽어주셔서 고맙습니다. 그런데 작성하신 게시물 링크라도 알려주셔야 논의가 가능하겠습니다.

      응답
    2. Gyuwon 글의 글쓴이

      WordPress.com에 뭔가 오류가 있는 것 같습니다. 모바일 앱 알림과 웹 앱에서는 링크가 보이지 않는데 지금 확인해 보니 메일로 온 알림에는 링크가 보이네요. 의견 훑어봤는데 페북 게시물에서 논의하기에는 문맥이 흩어지고 대화가 곧 휘발되는 것이 일반적이라 이 곳에서 대화하는 것이 더 좋아보입니다. 페북에 적어주신 의견을 여기에도 남겨주시면 하나씩 답변 드리겠습니다.

      응답

댓글 남기기