SQL에서 데이터를 가져오기 위해 사용하는 DML인 SELECT문은 데이터베이스를 사용하는 프로그램을 작성할 때 필수로 사용한다. 그 만큼 게시판, 회원가입, 쇼핑몰 등등의 예제가 SELECT 문을 사용하는 방법에 대해 다루고 있으며 당장 구글에 검색만 해도 엄청나게 쏟아져 나온다.

 

그런데 이들 예제는 하나같이 SELECT * FROM ... 으로 시작한다.

 

SELECT * FROM 은 말 그대로 대상 테이블의 모든 컬럼을 조회하라는 의미이다. 사실 따지고 보면 나도 귀찮아서 이 짓을 가끔 이상으로 하는데 언젠가 고쳐야 할 나쁜 습관이기도 하다. 그래서, 한번 자세히 알아보았다.

 

느리다

모든 컬럼을 조회한다는 것은 그만큼 DBMS에서 가져오는 데이터가 많아진다는 의미이다. 컬럼 두 세개쯤 되는 테이블이라면 딱히 상관이 없을지도 모른다. 하지만 컬럼이 한 20~30개쯤 되거나, 대규모로 조인을 건다거나 하는 상황이라면 어떨까?

 

게다가 인덱스를 사용하는 테이블이라면, 인덱스를 기준으로 검색하는게 그렇지 않은 경우보다 훨씬 빠른 결과를 만들어낸다. SELECT *는 이런 이점을 누릴 수 없게 만드는 것이다.

 

번거롭다, 그리고 위험하다.

한 테이블에서 일부 컬럼만을 가져다가 사용자에게 보내야 한다고 할 때, 무작정 SELECT * 를 걸었다면 반드시 백엔드에서 필터링 해줄 필요가 있다.

 

댓글 시스템을 생각해보자. 익명 게시판이라면 댓글에 수정 혹은 삭제를 위한 비밀번호를 저장하고 있을 것이다. 댓글 UI가 AJAX로 업데이트 되는식으로 구성되어 있다면 분명 API 요청을 보낼 것이고 당연히 API 응답은 사용자가 개발자도구 등의 툴을 이용해서 볼 수 있다.

 

그런데, 만약 API 백엔드가 SELECT * 한 결과를 그대로 사용자에게 보내거나 Password 컬럼을 거르지 않았다면?

그대로 공격자가 써먹을 수 있게 된다.

 

동명이인

개별 row를 명확하게 식별해야 한다고 할때, 우리는 보통 PRIMARY KEY를 사용한다. 그리고 이들의 이름은 대충 id, key, name, ... 뭐 기타등등 이런 식일 것이다.

create table a (
    id         int primary key,
    friend_id  int,
    
    foreign key (friend_id) references b(id) on delete cascade
);

create table b (
    id         int primary key,
    name       varchar(32)
);

뭐 이런 식의 스키마가 있다고 치자. a와 b는 둘 다 id라는 컬럼을 가지고 있다. 만약 SELECT * 로 조인을 한다면 id, friend_id, id, name이 조회될 것이다.

 

중복 데이터는 여러모로 골치아프게 하는 감이 있다. a.id 를 의도했지만 b.id를 가져오는 경우도 있고, 앞서 말했듯 데이터 이동량이 많아지기 때문에 퍼포먼스를 저하시키기도 한다. 따라서 이는 쿼리단에서 필터링 되어야 할 필요가 있다.

 

무작정 쓰지 말라는 뜻은 아니다.

모든 컬럼이라는 의미로 쓰이는 * 은 지양되어야 겠다만, 이건 프로덕션에서 그렇다는 뜻이다. 개발 단계에서 디버깅을 할 필요가 있거나 하는 등의 상황에서는 얼마든지 써도 크게 상관 없다. 물론, 서비스 전에 전부 걷어내거나 치워야 한다.

 

또한, SELECT COUNT(*) 와 같이 *가 row의 의미로 쓰인다면 이 또한 괜찮다. 여기서 *는 여태까지 말한 의미가 아닌 row를 의미하기 때문에 그 테이블에 있는 행의 갯수를 알아야 할때는 얼마든지 써도 된다.

 

마치며

SQL은 참 다재다능하다. 신뢰할 수 있으며 빠른 DBMS와 결합되어 사용된다면 효율적인 데이터 관리를 바탕으로 좋은 프로그램을 만들어낼 수 있다.

 

하지만 그만큼 작성하는 사람의 역량이 좋지 못하면 그 능력을 써먹기가 어려울 것이다. 그러니, 공부하자.

 

References

https://use-the-index-luke.com/blog/2013-08/its-not-about-the-star-stupid

https://stackoverflow.com/questions/3639861/why-is-select-considered-harmful