Skip to content
isdnetworks
Go back

앞 단계에서 이미 받아 둔 것

한 처리 흐름이 눈에 띄게 느려서 어디서 시간을 쓰는지 봤다. 특별히 무거운 계산은 없었고 같은 행을 세 번 SELECT 하고 있었다.

Table of contents

Open Table of contents

증상 — 세 번 가져온 같은 자료

grep 으로 흐름을 따라가 보니 process 가 orderNo 만 넘기고 각 단계가 다시 find 하고 있었다.

public function process(int $orderNo): void {
    $this->validate($orderNo);
    $this->calculate($orderNo);
    $this->notify($orderNo);
}

private function validate(int $orderNo): void {
    $order = $this->repo->find($orderNo);   // 1번째
}

private function calculate(int $orderNo): void {
    $order = $this->repo->find($orderNo);   // 2번째
}

private function notify(int $orderNo): void {
    $order = $this->repo->find($orderNo);   // 3번째
}

번호를 받은 쪽은 그 번호로 다시 find 하는 것 말고 할 수 있는 것이 없었다.

validate 든 calculate 든 따로 보면 아무 문제가 없다는 것이 이 구조의 성질이었다. 자기가 필요한 것을 find 해서 쓸 뿐이므로 한 함수만 열어서는 안 보인다.

조치 — 번호 대신 객체를 넘기기

그래서 process 가 한 번 find 하고 그 order 를 넘기게 고쳤다.

public function process(int $orderNo): void {
    $order = $this->repo->find($orderNo);
    $this->validate($order);
    $this->calculate($order);
    $this->notify($order);
}

세 번 나가던 SELECT 가 한 번으로 줄었다.

넘기는 것을 바꾸면 각 단계가 자기 것을 스스로 챙기지 않으므로 앞 단계에 의존하게 된다. 그 의존은 흐름을 읽을 때 드러나므로 감춰지는 것보다 낫다고 봤다. 대신 단계 하나를 따로 떼어 쓰기 어려워지는 것을 감수했다.

중간에 바꾼 값은 돌려준다

중간 단계에서 값을 UPDATE 하는 자리가 있었는데 이때 넘겨받은 것과 MySQL 의 값이 갈릴 수 있었다. 바꾼 뒤에도 넘겨받은 것을 그대로 다음으로 보내면 예전 값이 흘러간다.

그래서 값을 바꾸는 단계는 바꾼 결과를 돌려주게 했다. PHP 매뉴얼(Objects and references)은 객체 변수가 객체 자체가 아니라 식별자를 담고 있어 인자로 넘긴 객체가 같은 객체를 가리킨다고 적으므로, 넘겨받은 객체의 속성을 그 자리에서 갱신하는 길도 있었다. 돌려주는 쪽을 골랐다. 이유는 어느 단계가 값을 바꾸는지가 서명에 드러난다는 점이다. 넘기는 방식으로 갈 때는 어디서 값이 바뀌는지를 함께 정해 둬야 했다.

넘길 것이 많아질 때

단계를 지나면서 넘길 것이 늘어나 인자가 다섯 개가 넘어가는 자리가 생겼고 그러면 함수 서명이 길어지고 순서를 헷갈리기 시작한다.

그런 자리는 한 묶음으로 만들어서 하나만 넘기게 했고 묶는 기준은 같은 흐름에서 함께 흘러가는 것들로 잡았다.

조회 횟수 세기와 담아 두기

고치고 나서 같은 행을 몇 번 SELECT 하는지 세는 것을 개발 환경에서 켜 뒀고 다른 흐름에서도 같은 모양이 있는지가 그 수로 보인다.

한 번 가져온 것을 캐시에 담아 두는 방법도 있었지만 그것은 나중으로 미뤘다. 캐시에 담으면 중복 SELECT 가 안 보이게 되므로 흐름을 드러내는 쪽을 먼저 하는 것이 순서였다.

정리


Share this post on:

Previous Post
양쪽에 똑같이 적용해 대칭으로 맞췄다
Next Post
속성처럼 쓴 메서드