Blog

XE에는 getNumberingPath라는 함수가 있습니다.

config/func.inc.php 에 정의 되어 /modules/comment/comment.item.php/modules/document/document.item.php,/modules/file/file.controller.php 등등에서 사용 되어지고 있습니다.
이 함수가 하는 역할은 업로드 되는 파일들을 효율적으로 분산시켜 서버에 저장하기 위해
디렉토리를 구분하는 것입니다.

스크린샷_2014-07-11_오후_11_48_10.png


첨부되는 이미지 주소는 다들 한번씩은 보았을 것입니다.
그 이미지 주소중에 위 이미지에서 보이는 것 처럼 getNumberingPath로 생성된 경로는 글 고유번호를 뒤에서 부터 3자리씩 나눈 숫자로 나타내고 있습니다.

참고로 getNumberingPath 경로 앞에 숫자는 모듈 번호이고, 3자리씩 나누었을때 모자른 자리는 '0'으로 채워집니다.

그렇다면 왜 디렉토리를 구분해야 하는 것일까요?

기본적으로 시스템에서 파일을 찾기위해선 탐색이라는 동작을 수행해야 합니다. 그런데 이 탐색이 제약없이
균일한 퍼포먼스를 제공하지는 않습니다. 일정이상의 파일이 한 디렉토리내에 존재하게 되면 특정파일을 탐색하는 시간이 파일 수에 비례하여 증가 하게됩니다.
일반적으로 한 디렉토리내에 5,000개 이상의 파일이 존재할 경우 상당한 속도저하를 체감할 수 있고, 10,000개가 넘어가면 심각한 수준에 이르게 됩니다. 이 경우 삭제동작시에도 엄청난 시간을 소모하게 됩니다.

그래서 효율적인 서비스를 위해 파일을 분산해서 저장할 필요가 있는 것입니다.

디렉토리를 구분하는 방법은 선택에 따라 다릅니다. 보통 날짜를 기준으로 디렉토리를 구분하는 경우는 많이 보았을 것입니다. 년/월 또는년/월/일과 같은 방식이죠.
이 방식의 단점은 파일들을 균등하게 분배하지 못한다는 것입니다.

예를 들면, 어떤 사이트를 하나 개발했다고 가정합니다. 초기에 마케팅을 하지 않아 방문자 수가 적고, 그에따라 업로드 되는 파일의 수도 적어서 하루에 약 20 ~ 30개 정도 업로드 되는 상황이였습니다.
그런데 적극적으로 마케팅활동을 벌여 방문자 수가 급격히 늘고 그에 따라 파일 수도 급격히 늘어나게 됩니다. 하루에 20 ~ 30개 업로드 되던 상황에서 500 ~ 1000개 이상 업로드 되는 것입니다.
초기엔 날짜 구분 방식이 아무 문제가 없었지만 이제 문제가 생기기 시작합니다. 특정 디렉토리에 파일이 너무 몰리게 되는 것입니다.

이렇게 되면 해당 디렉토리의 파일을 탐색할 때 위에서 언급한 바와 같이 속도 저하를 일으키게 되는 것입니다.

그래서 XE에서는 효율적인 서비스 제공을 위해 getNumberingPath 함수를 제공하는 것입니다.

소스를 보면,

function getNumberingPath($no, $size = 3)
{
    $mod = pow(10, $size);
    $output = sprintf('%0' . $size . 'd/', $no % $mod);
    if($no >= $mod)
    {
        $output .= getNumberingPath((int) $no / $mod, $size);
    }
    return $output;
}

이렇게 되어있습니다. 각 구문을 보면

$mod = pow(10, $size);
  • 10의 제곱수를 이용하여 번호별로 디렉토리를 지정합니다. default가 3이므로 나머지 연산 기준은 default가 1000입니다.
$output = sprintf('%0' . $size . 'd/', $no % $mod);
  • 디렉토리 이름을 만듭니다. $size = 3일경우 번호 인자 값을 1000으로 나눈 나머지를 3자리 정수로 표현합니다. 번호값이 123456 일 경우 반환되어지는 값은 456/이 됩니다.
if($no >= $mod)
{
    $output .= getNumberingPath((int) $no / $mod, $size);
}
  • 번호 값이 나머지 연산 기준값보다 클 경우 기준값 초과 부분을 기준값으로 나눈 정수를 재귀호출하여 반환되어지는 경로에 포함합니다.$size = 3일 경우 나머지 연산 기준값은 1000이 되고, 번호가 123456일 경우 456/뒤에 123/이 연결되어 최종 결과 값은456/123/이 됩니다.

내용을 보다 보면 의문점이 하나 생길 것입니다.

왜 번호표기 순이 아닌 3자리씩 역순으로 생성하는 것인가?

일단 default 로 $size값이 3인 이유는, 일반적으로 효율적으로 서비스를 제공하기 위해 한 디렉토리에 권장되는 파일의 수가 1,000개 이기 때문입니다.
역순표기는 디렉토리 분산 정도를 높이기 위함입니다. $size = 3을 기준으로 하여 생각하면, 최초 999개의 디렉토리에 분산 저장되는 것은 정순표기와 동일 하지만 그 다음부터는 정순표기는 한 디렉토리에 999개의 파일이 지정되고 그 이후 다음 디렉토리로 이동하지만 역순표기는 매번 다른 디렉토리를 지정해줄수 있습니다.
그래서 XE에서는 역순으로 디렉토리이름을 나열하며, 필요시 해당 디렉토리를 생성할 수 있도록 한 것입니다.

마지막으로, 소스를 보는 바와 같이 $size 값을 변경할 수 있도록 작성되어 있습니다. 상황에 따라 인자값을 변경해서 사용하 실 수 있으나 default로 설정되어있는 3을 초과하여 사용하지 않으셔야 합니다. 앞서 언급한데로 디렉토리당 제한 수가 10,000 이상이 되기 때문에 속도 저하를 일으킬 수 있습니다.