Skip to content
isdnetworks
Go back

메뉴를 코드에서 찾고 있었다

관리자 화면에 메뉴를 하나 추가해 달라는 요청을 받고 grep -rn 으로 코드를 뒤졌는데 안 나왔다.

Table of contents

Open Table of contents

자료에 있었다

views/ 의 화면 코드는 목록을 받아 그리기만 하고 있었다. 그 목록이 어디서 오는지 따라가니 admin_menu 표였다. parent_no 로 계층을 만들고 sort_no 로 순서를 정하는 구조다.

CREATE TABLE admin_menu (
  menu_no    INT NOT NULL AUTO_INCREMENT,
  parent_no  INT NULL,
  name       VARCHAR(50) NOT NULL,
  url        VARCHAR(200) NULL,
  sort_no    INT NOT NULL DEFAULT 0,
  use_yn     CHAR(1) NOT NULL DEFAULT 'Y',
  PRIMARY KEY (menu_no)
);

메뉴가 자료였으므로 추가하려면 INSERT 한 줄이면 됐다. 코드에 없는 것을 코드에서 찾으면 안 나온다. 무엇이 코드에 있고 무엇이 자료에 있는지를 먼저 확인해야 했다.

자료로 둔 이유

왜 이렇게 했는지 물어보니 둘이었다. 메뉴마다 필요한 권한이 있어 사람에 따라 다르게 보여야 하고, 새 기능을 열고 닫는 것을 배포 없이 해야 한다. 둘 다 코드로 하면 배포가 필요한데 자료면 화면에서 한다.

편한 대신 따라오는 것도 있었다. 코드만 봐서는 어디에 무엇이 있는지 모른다. 없는 url 을 넣어도 저장된다. sort_noparent_no 가 자료라 꼬일 수 있다. 부모가 없는 자식이나 순환 참조 같은 것이다.

검사를 넣었다

메뉴를 저장할 때 ucfirst 로 컨트롤러 파일명을 만들어 그 화면이 실제로 있는지 확인하게 했다.

$file = APPPATH . 'controllers/' . ucfirst($controller) . '.php';
if (!file_exists($file)) {
    return '해당 주소의 화면이 없습니다: ' . $url;
}

file_exists 로 보는 것이라 완벽하지는 않지만 오타는 잡힌다. 저장은 되고 눌러야 404 가 나는 것보다 낫다.

계층도 확인했다. 자기 자신이나 자기 자손을 parent_no 로 지정하는 것을 막았다.

순환이 생기면 메뉴를 그리는 재귀 함수가 안 끝난다. 안 끝나면 어떻게 되는지 직접 돌려 보니 PHP 는 재귀 깊이 자체에 제한을 두지 않고 스택이 쌓이다 memory_limit 에 걸려 Allowed memory size exhausted 로 죽는다. 화면은 빈 채로 끝나고 Allowed memory size exhaustederror_log 에만 남는다.

구조를 보는 화면도 만들었다. 코드를 읽어도 안 나오니 어딘가에서는 보여야 했다.

상품관리
  ├ 상품목록      /product/list
  ├ 상품등록      /product/write
  └ 분류관리      /category/list
주문관리
  ├ 주문목록      /order/list
  └ 정산          /settle/list       [사용안함]

url 을 같이 보여 주니 어느 코드가 어느 메뉴인지 대응이 된다. use_ynN 인 메뉴도 표시만 다르게 해서 남겼다. 없는 것과 꺼진 것은 다르다.

양방향으로 대조했다

admin_menu 에 없는 화면이 있는지도 봤다. controllers/ 의 파일 이름을 basenamestrtolower 로 뽑아 url 목록과 맞댔다. 자료에서 코드로만 확인하면 자료에 적힌 것이 맞는지만 알 수 있고 반대쪽은 안 나온다.

foreach ($files as $f) {
    $name = strtolower(basename($f, '.php'));
    $found = false;
    foreach ($urls as $u) {
        if (strpos($u, '/' . $name . '/') === 0) { $found = true; break; }
    }
    if (!$found) echo "메뉴 없음: {$name}\n";
}

7개가 나왔고 셋은 메뉴를 안 만든 것이었으며 넷은 안 쓰는 화면이었다. 어느 쪽 목록에만 있는지를 양방향으로 봐야 빠진 것과 남은 것이 다 드러난다.

정리


Share this post on:

Previous Post
설정을 바꿨는데 아무 일도 안 일어났다
Next Post
결제 통지가 두 번 왔다