[데이터베이스] SQL 안티 패턴

Yoon Uk·2023년 8월 3일
0

데이터베이스

목록 보기
10/20

SQL 안티 패턴이란 SQL 쿼리나 데이터베이스 설계에서 흔히 발생하는 잘못된 패턴을 말합니다. SQL 안티 패턴은 성능 저하, 데이터 무결성 손상, 보안 취약점 등의 문제를 야기할 수 있습니다. 따라서 SQL 안티 패턴을 인식하고 피하는 것이 중요합니다.

이번 글에서는 SQL 안티 패턴에서 소개된 내용 중 몇 가지 예시와 그에 대한 대안을 소개하겠습니다.

1. SELECT * FROM

의미

SELECT * FROM은 테이블의 모든 컬럼을 조회하는 쿼리입니다. 이 쿼리는 테이블의 구조가 변경되거나 컬럼이 추가되면 예상치 못한 결과를 가져올 수 있습니다. 또한 필요하지 않은 컬럼까지 조회하므로 네트워크 부하와 메모리 사용량을 증가시킵니다.

해결법

따라서 필요한 컬럼만 명시적으로 조회하는 것이 좋습니다.

예시

SELECT * FROM users; -- 안티 패턴
SELECT id, name, email FROM users; -- 권장

2. 문자열 연결로 동적 쿼리 생성

의미

문자열 연결로 동적 쿼리를 생성하는 것은 SQL 인젝션 공격에 취약합니다.
SQL 인젝션 공격이란 악의적인 사용자가 입력값에 SQL 구문을 삽입하여 데이터베이스에 접근하거나 조작하는 공격입니다.
문자열 연결로 동적 쿼리를 생성하면 입력값을 검증하지 않고 쿼리에 포함시키므로 SQL 인젝션 공격에 노출될 수 있습니다.

해결법

따라서 문자열 연결 대신 파라미터화된 쿼리나 저장 프로시저를 사용하는 것이 좋습니다.

예시

name = request.getParameter("name");
sql = "SELECT * FROM users WHERE name = '" + name + "'"; -- 안티 패턴
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);

name = request.getParameter("name");
sql = "SELECT * FROM users WHERE name = ?"; -- 권장
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, name);
rs = pstmt.executeQuery();

3. 잘못된 데이터 타입 사용

의미

데이터 타입은 데이터의 종류와 크기를 정의하는 것입니다. 데이터 타입을 잘못 사용하면 데이터의 정확성과 효율성이 떨어질 수 있습니다.
예를 들어, 날짜나 시간을 문자열로 저장하면 날짜나 시간 관련 함수를 사용할 수 없고, 정렬이나 비교도 제대로 되지 않습니다. 또한, 숫자를 문자열로 저장하면 숫자 관련 연산이나 집계가 불가능하고, 공간도 낭비됩니다.

해결법

따라서 데이터의 성격과 범위에 맞는 데이터 타입을 사용하는 것이 좋습니다.

예시

CREATE TABLE orders (
  id INT PRIMARY KEY,
  order_date VARCHAR(10), -- 안티 패턴
  amount VARCHAR(10) -- 안티 패턴
);

CREATE TABLE orders (
  id INT PRIMARY KEY,
  order_date DATE, -- 권장
  amount DECIMAL(10,2) -- 권장
);

4. 다중 칼럼 속성

의미

하나의 엔터티에 여러 개의 값을 칼럼으로 만들어 대응하는 것입니다.

이렇게 하면 아래와 같은 부분에서 문제점이 생길 수 있습니다.

  • 검색
    원하는 정보가 어느 칼럼에 있는지 모두 확인해야 합니다.
SELECT * 
FROM member
WHERE hobby1 = 'soccer'
   OR hobby2 = 'soccer'
   OR hobby3 = 'soccer';
  • 수정
    여러 칼럼 중 어떤 칼럼을 수정(Update)해야 할 지 확인하고 수정해야합니다.

  • 일관성
    여러 칼럼에 중복되는 값이 입력되어 저장되는 것을 예방하기가 어렵습니다.

  • 테이블 잠금
    칼럼 하나의 값을 수정하기 위해 테이블 전체가 잠금이 설정될 수 있습니다.

해결법

종속 테이블을 생성해 사용합니다.

예시

-- 안티 패턴
CREATE TABLE member (
  id INT PRIMARY KEY,
  name VARCHAR(10), 
  hobby1 VARCHAR(10), // 취미1
  hobby2 VARCHAR(10), // 취미2
  hobby3 VARCHAR(10), // 취미3
);

-- 권장
CREATE TABLE member (
  member_id INT PRIMARY KEY,
  name VARCHAR(10), 
  hobby_id INT FOREIGN KEY REFERENCES hobby(hobby_id)
);

CREATE TABLE hobby (
  hobby_id INT PRIMARY KEY,
  name VARCHAR(10)
);

마무리

썸네일에 있는 책을 학습해 계속 업데이트 하도록 하겠습니다.

0개의 댓글