상품 상세에 추천 상품이 안 뜬다는 얘기를 들었다. 코드를 봤더니 product_model 에 읽어서 그리는 부분이 멀쩡히 있었고 조회 쿼리도 맞았다.
Table of contents
Open Table of contents
테이블이 비어 있었다
쿼리를 직접 돌려 보니 한 건도 없었다.
SELECT COUNT(*) FROM product_recommend;
-- 0
product_recommend 는 만들어져 있고 읽는 코드도 있는데 안이 비어 있다. 그러면 읽는 쪽이 아니라 쓰는 쪽을 봐야 한다.
쓰는 코드가 없었다
grep -rn 에 --include=*.php 를 붙여 테이블 이름으로 소스를 전부 뒤졌다.
$ grep -rn "product_recommend" --include=*.php .
./application/models/product_model.php:212: ... FROM product_recommend ...
./application/models/product_model.php:238: ... FROM product_recommend ...
./application/views/product/detail.php:96: ...
세 군데 전부 SELECT 고 INSERT 가 한 줄도 없었다. 관리자 화면에도 추천 상품을 등록하는 메뉴가 없었다. 화면 설계에는 있는데 만들어지지 않은 것이다. 기능이 고장 난 것이 아니라 아직 없는 것이었다.
왜 이렇게 되는지는 짐작이 갔다. 화면을 먼저 그려야 확인이 되니까 조회부터 만들고, 시험 데이터를 직접 넣어 화면이 나오는 것을 보면 그 부분은 끝난 것으로 넘어간다. 등록 화면은 뒤로 밀리고 시험 데이터는 정리하면서 지워진다. 남는 것이 읽는 코드와 빈 테이블이다. 읽는 쪽만 보면 완성된 것처럼 보인다.
확인 순서를 바꿨다
안 나온다는 얘기를 들었을 때 보는 순서를 정했다. COUNT(*) 로 데이터가 있는지를 먼저 센다. 있으면 WHERE 를 뗀 쿼리와 비교해 조회 조건이 맞는지 본다. 조건이 맞으면 화면까지 오는지를 중간에 찍어 본다. 첫 번째가 0 이면 아래는 볼 필요가 없는데 그걸 안 보고 조회 코드부터 읽으면 시간이 많이 든다.
이 순서로 몇 건을 더 확인했더니 비슷한 것이 두 개 더 나왔다. 상품 태그 테이블은 SELECT 만 있고 등록 화면이 없었다. 배송비 정책은 등록 화면이 있는데 INSERT 가 다른 테이블로 가고 있었다. 두 번째가 더 나빴다. 저장은 되니까 화면에는 저장됐다는 문구가 뜬다.
조회 실패와 0 건을 log_message 에서 구분하게도 했다. 둘 다 화면에는 아무것도 안 나오지만 손볼 곳이 다르다.
$list = $this->product_model->get_recommend($no);
if ($list === null) {
log_message('error', "추천 조회 실패: product {$no}");
} else if (count($list) === 0) {
log_message('info', "추천 없음: product {$no}");
}
같은 상태를 한 번에 찾기
같은 테이블이 더 있는지 행 수로 훑었다.
SELECT TABLE_NAME, TABLE_ROWS
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'shopdb'
ORDER BY TABLE_ROWS ASC;
TABLE_ROWS 는 InnoDB 에서 옵티마이저가 쓰는 어림수라 그 값을 그대로 믿으면 안 된다. 0 에 가까운 것만 골라 COUNT(*) 로 실제로 세어 봤다. 0 건인 테이블이 아홉 개였고 그중 다섯은 아직 안 쓰는 기능이었으며 네 개가 이번 같은 경우였다.
찾은 자리에는 표시를 남겼다. get_recommend 위에 한 줄만 적어 두면 다음에 보는 사람이 조회 로직 대신 데이터를 먼저 의심한다.
// 등록 화면 미구현 — 데이터 없음
public function get_recommend($product_no) {
정리
- 안 나온다는 얘기에는 데이터가 0 건인 경우가 있다
- 읽는 쪽만 보면 완성돼 보인다 —
grep -rn으로INSERT가 있는지 찾는다 - 확인 순서는
COUNT(*)다음WHERE제거 비교 다음 화면 도달이다 INSERT가 다른 테이블로 가는 경우가 더 나쁘다. 화면에는 성공이 뜬다- 조회 실패와 0 건을
log_message에서 나눈다 information_schema.TABLES로 같은 상태를 한 번에 찾는다TABLE_ROWS는 어림수라COUNT(*)로 다시 센다- 미완성이면 그 자리에 한 줄 남긴다