관리자 화면에서 상품 목록을 고쳤더니 사용자 화면이 깨졌다.
Table of contents
Open Table of contents
증상 — 같은 것을 쓰고 있었다
둘이 같은 조회 함수를 쓰고 있었다.
$this->Product_model->get_list();
관리자에서 숨긴 상품도 보여야 해서 조건을 뺐다.
// 뺌
// $this->db->where('is_visible', 1);
그러니 사용자 화면에도 숨긴 상품이 나왔다. is_visible 조건 하나를 뺀 것이 두 화면에 동시에 반영된 것이다.
한쪽에 맞춰 고치면 다른 쪽이 깨지는 구조였다.
참 거짓 인자로 나누려다 말았다
먼저 인자를 넣을까 생각했다.
get_list($includeHidden = false)
다만 이렇게 가면 인자가 계속 늘 것 같았다. 숨긴 것을 포함할지 품절을 포함할지 삭제된 것을 포함할지가 다 인자가 된다.
get_list(true, false, true); // 무슨 뜻인지 모름
참·거짓 인자가 여럿이 되면 부르는 쪽이 읽기 어려워진다. 다른 곳에서도 차이가 더 있었는데 ORDER BY 도 다르고 가져올 컬럼도 달랐다.
함수를 나누고 안쪽을 공유했다
인자 대신 함수를 나눴다.
get_list_for_front() // 보이는 것만
get_list_for_admin() // 전부
이름으로 뜻이 보인다. 다만 공통 부분은 나누지 않았다.
private function base_query() { ... }
public function get_list_for_front() {
return $this->base_query()->where('is_visible', 1)->get();
}
public function get_list_for_admin() {
return $this->base_query()->get();
}
base_query 를 안쪽에서 공유하니 차이만 다르고 나머지는 같다.
나누고 나서 다른 것도 나왔다. 관리자에는 등록자와 수정일과 상태와 재고가 필요한데 사용자 화면은 이름과 가격과 이미지면 된다.
$this->db->select('id, name, price, image'); // 사용자
$this->db->select('*'); // 관리자
전에는 둘 다 SELECT * 라 사용자 화면에서 안 쓰는 컬럼까지 읽었다. 하나였으면 못 나누고 가장 많이 필요한 쪽에 맞춰야 했을 것이다.
정렬과 인덱스
정렬도 갈렸다. 사용자는 인기순과 신상품순으로 보고 관리자는 등록일순과 수정일순으로 본다.
ORDER BY 가 다르면 Using filesort 를 없애는 인덱스도 다르다. 나누고 나서 각각 실행 계획을 보니 사용자 조회는 인기순 인덱스가 필요하고 관리자 조회는 수정일 인덱스가 필요했다.
하나였으면 어느 정렬에 맞출지 골라야 했는데 나누니 각각 맞출 수 있었다.
다만 둘 다 걸려니 개수가 걸렸다. 인덱스가 많으면 INSERT 마다 그만큼 더 쓰기 때문에 상품 등록과 수정이 느려진다.
사용자 화면은 많은 사람이 보고 관리자 화면은 몇 명이 본다. 인덱스를 하나만 걸어야 한다면 사용자 쪽에 걸기로 했다.
SHOW INDEX FROM products;
현재 인덱스를 세어 보니 이미 여럿이었다. 어느 것이 실제로 쓰이는지는 자주 도는 쿼리에 EXPLAIN 을 떠서 key 에 무엇이 잡히는지로 봤다.
전혀 안 잡히는 것이 몇 개 있었고 예전에 넣고 조건이 바뀌면서 안 쓰게 된 것들이었다.
SHOW CREATE TABLE products;
지우기 전에 정의를 떠서 적어 뒀다. 다시 걸어야 할 때 그대로 붙여 넣을 수 있다.
지운 뒤에는 느려진 화면이 없는지 봤다. 안 보면 어딘가 느려졌는데 모르고 보면 바로 알고 되돌린다. 지우는 것보다 지운 뒤를 보는 것이 이 작업의 실제 내용이었다.
정리
- 관리자와 사용자가 같은 조회를 쓰면 한쪽을 고칠 때 다른 쪽이 깨진다
- 참·거짓 인자로 나누면 부르는 쪽이 읽기 어려워진다
- 함수를 나누고
base_query같은 공통 부분만 공유한다 - 나누면
SELECT *를 걷어 내고 컬럼을 각각 맞출 수 있다 ORDER BY가 다르면Using filesort를 없애는 인덱스도 다르다- 인덱스가 늘면
INSERT마다 그만큼 더 쓴다 - 하나만 걸어야 한다면 많은 사람이 보는 쪽에 건다
SHOW INDEX로 세고EXPLAIN의key로 쓰이는지 본다- 지우기 전에
SHOW CREATE TABLE로 정의를 떠 둔다 - 지운 뒤에 느려진 것이 없는지 본다