Blog
기술 공유 XE-Core 내장 함수 getNumberingPath
2014.07.14 18:11
XE에는 getNumberingPath
라는 함수가 있습니다.
config/func.inc.php
에 정의 되어 /modules/comment/comment.item.php
, /modules/document/document.item.php
,/modules/file/file.controller.php
등등에서 사용 되어지고 있습니다.
이 함수가 하는 역할은 업로드 되는 파일들을 효율적으로 분산시켜 서버에 저장하기 위해
디렉토리를 구분하는 것입니다.
그 이미지 주소중에 위 이미지에서 보이는 것 처럼 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
이상이 되기 때문에 속도 저하를 일으킬 수 있습니다.
댓글 6
-
GG
2014.07.14 18:19
-
KrteamENT
2014.07.14 18:22
오호..좋은팁 감사합니다 ㅇㅅㅇ!
-
숭숭군
2014.07.14 19:09
굳이에요 굳굳
-
키스투엑스이
2014.07.14 19:46
오오 좋네요. -
KANTSOFT
2014.07.14 20:59
이러한 API설명 참 좋습니다.
-
gu
2014.07.16 13:45
오오.... 한폴더당 10000개가 넘어가면 속도저하를 일으키는군요.. 꼼수로 cache 쪽에 만들어놓은거 있는데 수정해야겠네요 ㅠ
함수가 어딧는지 찾다가 귀찮아서 에이 몰라 하고 포기하고 그랬는데 이거였군요~
고맙습니다 :)