Offcanvas

How To / 개발자 / 경력관리

블로그 | '오히려 기회'··· 개발자가 SQL에 겁먹을 필요 없는 7가지 이유

2023.10.16 Charly Batista  |  InfoWorld
SQL(Structured Query Language)은 1970년대 초 발명된 이후 데이터베이스와의 상호작용을 관리하는 기본 수단으로 쓰이고 있다. 스택 오버플로우에 따르면 SQL은 여전히 상위 5개 프로그래밍 언어 중 하나이고 개발자의 약 50%가 업무에 사용하고 있다. 하지만 이런 보편성에도 불구하고 아직도 SQL은 어렵고 부담스럽다는 말을 많이 한다. 그러나 어떻게 작동하는지만 이해하면 SQL은 전혀 어렵지 않다. 더구나 오늘날 기업은 생성되는 데이터에 점점 더 많은 가치를 부여하고 있으므로 SQL을 알면 소프트웨어 개발자로서 더 뛰어난 역량을 발휘하고 경력을 발전시킬 기회를 잡을 수 있다. 개발자가 SQL에 대해 알아야 할 것과 조심해야 할 문제를 정리했다.
 
ⓒ Getty Image Bank
 

SQL을 두려워하지 말라

SQL은 구조적이므로 사용하기 쉽고, 여러 쿼리의 조합 방법을 엄격하게 규정하므로 읽고 이해하기 쉽다. 타인이 작성한 코드를 볼 때 쿼리 구조를 살펴보는 것으로 그 사람이 원하는 것이 무엇인지를 이해할 수 있어야 한다. 이렇게 되면 특히 복잡한 연산과 JOIN에서 향후 쿼리를 튜닝하고 성능을 개선하기도 더 쉬워진다. 

그러나 많은 개발자가 처음 접했을 때의 경험을 이유로 SQL을 멀리한다.  큰 이유 중 하나가 처음 배우는 명령인 SELECT의 사용 방법에 있다. 개발자가 SQL을 작성하기 시작하면서 가장 일반적으로 저지르는 실수는, 다루고자 하는 요소를 SELECT로 선택하는 것이다. 그러나 SELECT *처럼 SELECT를 너무 폭넓게 사용하면 성능에 큰 영향을 미칠 수 있고 나중에 쿼리를 최적화하기 어려워진다.

쿼리에 모든 것을 포함해야 하는가, 아니면 더 구체적으로 좁힐 수 있는가? 이 질문은 상황마다 다를 수 있다. 서버가 효율적으로 기능하기 위해 필요한 메모리 공간에 영향을 미치는 방대한 ResultSet 응답으로 이어질 수 있기 때문이다. 쿼리가 다루는 데이터가 너무 많으면 특히 클라우드 서비스에서 데이터베이스를 실행 중인 경우 필요 이상의 메모리를 할당하게 된다. 클라우드에서 사용량은 곧 비용이므로 SQL을 잘못 작성하면 이것만으로도 훨씬 더 많은 비용을 지출하게 될 수 있다.
 

데이터 형식 알기 

개발자가 SQL을 사용할 때 겪는 또 다른 일반적인 문제는 열의 데이터 형식과 관련된다. 개발자가 기대하는 데이터 형식은 크게 2가지로, 정수와 가변 문자, 즉 varchar다. 정수 필드에는 숫자가 포함되지만 varchar 필드에는 숫자와 문자가 포함될 수 있다. 한 가지 형식, 일반적으로 정수를 예상하면서 데이터에 접근했는데 다른 데이터 형식을 받게 되면 예측 결과의 데이터 형식이 일치하지 않게 된다. 

이 문제를 피하려면 정기적으로 사용하는 문 명령과 준비된 문 스크립트에 대한 접근 방식에 주의를 기울여야 한다. 그러면 예상과 다른 결과가 발생하는 상황을 방지하는 데 도움이 된다. 마찬가지로, 데이터베이스 테이블을 JOIN할 때도 접근 방식을 점검해서 서로 다른 데이터 형식을 가진 열을 사용하지 않도록 해야 한다. 데이터를 확인하면 JOIN 실행 시 데이터 값이 있는 필드가 잘리거나 데이터 값이 다른 값으로 변환되는 등의 데이터 손실을 방지할 수 있다. 

간과하는 경우가 많은 또 다른 문제는 문자 집합, 즉 charset이다. 깜박 잊기 쉽지만, 애플리케이션과 데이터베이스가 작업에서 동일한 charset을 사용 중인지 항상 확인해야 한다. 서로 다른 charset을 사용하면 인코딩 불일치가 발생하고 이로 인해 애플리케이션 뷰가 망가지고 특정 언어나 기호를 사용할 수 없게 된다. 최악의 경우 데이터 손실 또는 디버그하기 어려운 난해한 오류로 이어진다.
 

데이터 순서가 중요한 경우 알기 

데이터베이스 작업을 처음 시작할 때 많은 개발자가 열의 순서가 더 이상 중요하지 않다고 생각한다. 실제로 많은 데이터베이스 제공업체가 개발자는 스키마를 알 필요가 없고 툴이 알아서 다 해준다고 주장한다. 그러나 겉보기에는 영향이 없는 것 같아도, 인프라에 상당한 정도의 계산 비용이 발생할 수 있다. 종량제 클라우드 서비스를 사용하는 경우 이 비용은 무시할 수 없을 정도다.

여기서 중요한 것은 데이터베이스와 인덱스가 천차만별이라는 사실을 이해하는 것이다. 예를 들어 복합 인덱스에서는 열의 순서가 매우 중요하다. 인덱스 생성 순서에서 가장 왼쪽부터 열이 평가되기 때문이다. 따라서 이 경우 시간이 지나면서 점차 성능에 영향을 미치게 된다. 그러나 WHERE 절의 열을 선언하는 순서에는 이 같은 영향이 없다. 데이터베이스에 쿼리를 실행하기에 가장 좋은 방법으로 재구성하는 쿼리 계획 및 쿼리 옵티마이저와 같은 구성요소가 있기 때문이다. 이들 구성요소는 WHERE 절의 열을 재구성하고 순서를 변경할 수 있지만 여전히 인덱스의 열 순서에 의존한다. 

정리하면 데이터 순서가 어느 부분에서 연산 및 인덱스에 영향을 미치는지를 아는 것이 중요하다. 그러면 전체적인 성능을 개선하고 설계를 최적화하기 위한 기회를 파악할 수 있다. 이를 위해서는 데이터와 연산자의 카디널리티(cardinality)가 매우 중요하다. 이 부분을 이해하면 설계를 더 개선하고 장기적인 가치를 끌어낼 수 있다. 
 

언어 차이에 주의 

SQL을 막 시작하는 개발자가 겪는 일반적인 문제 중 하나는 NULL과 관련된 문제다. 자바 개발자를 위해 자바 데이터베이스 커넥터(JDBC)는 애플리케이션을 데이터베이스에 연결하는 API를 제공한다. 단, JDBC는 SQL NULL을 자바 null에 매핑하지만 두 가지가 같지는 않다. SQL의 NULL 명령은 UNKNOWN이라고도 하는데, 이는 SQL NULL = NULL이 거짓이며 자바의 null == null과 같지 않음을 의미한다. 결과적으로, NULL을 사용한 산술 연산이 예상과 다른 결과를 도출할 수 있다. 이 불일치를 알면 애플리케이션의 한 요소를 데이터베이스 및 쿼리 설계로 변환하는 방법과 관련한 잠재적인 문제를 방지할 수 있다. 

자바 및 데이터베이스와 관련해 피해야 하는 몇 가지 다른 패턴도 있다. 모두 연산이 수행되고 처리되는 방법 및 위치와 관련된 패턴이다. 예를 들어 개별적인 여러 쿼리에서 맵으로 테이블을 로드한 다음 처리를 위해 자바 메모리에서 조인할 수 있다. 그러나 이는 메모리에서 수행하기에 훨씬 더 까다롭고 계산 비용도 큰 방법이다. 대신 데이터베이스에서 처리가 가능하도록 수학적인 모든 요소를 정렬, 집계 또는 실행하는 방법이 더 낫다. 대부분의 경우 이런 쿼리 및 계산은 자바 메모리에서 처리하는 것보다 SQL로 작성하는 편이 더 쉽다.
 

데이터베이스에 맡기기 

데이터베이스를 메모리에서 처리하면 구문 분석(parsing) 및 확인을 더 쉽게 해주고, 알고리즘보다 더 빠르게 계산을 수행할 수 있다. 하지만 이런 장점이 있다고 해서 꼭 그렇게 해야 한다는 의미는 아니다. 전체적인 속도를 이유로 그렇게 할 만한 가치는 없다. 다시 한 번 말하지만 인메모리 클라우드 서비스는 데이터베이스를 사용해 결과를 제공하는 방법에 비해 비용이 더 많이 든다. 

페이지 매김도 마찬가지다. 페이지 매김은 쿼리 결과를 한 페이지가 아닌 여러 페이지에 걸쳐 정렬하고 표시하는 방법을 다루는데, 데이터베이스 또는 자바 메모리에서 처리할 수 있다. 수학적 연산과 마찬가지로 페이지 매김 결과도 메모리가 아닌 데이터베이스에서 수행해야 한다. 이유는 간단하다. 메모리 내의 각 연산은 모든 데이터를 메모리로 가져와서 트랜잭션을 수행한 다음 데이터베이스로 돌려보내야 하기 때문이다. 이 모든 과정이 네트워크를 통해 이뤄지면 실행될 때마다 왕복 이동이 추가되고 그에 따른 트랜잭션 지연도 추가된다. 이런 트랜잭션은 메모리에서 작업을 수행하는 것보다 데이터베이스를 사용하는 편이 훨씬 더 효율적이다.

또한 데이터베이스에는 연산의 효율성을 더욱 높일 수 있는 유용한 명령이 많다. LIMIT, OFFSET, TOP, START AT, FETCH와 같은 명령을 활용하면 현재 작업 중인 데이터 집합을 처리하는 방식을 중심으로 페이지 매김 요청의 효율성을 더 높일 수 있다. 마찬가지로, 조기 행 조회를 방지해 성능을 더 개선할 수 있다. 
 

연결 풀링 사용 

애플리케이션을 데이터베이스에 연결하려면 연결이 설정되고 트랜잭션이 수행되기 전에 작업이 필요하고 시간도 걸린다. 따라서 애플리케이션이 정기적으로 활성화되는 경우 이 작업이 오버헤드가 될 수 있다. 이에 대한 표준적 접근 방식은 연결 풀을 사용하는 것이다. 연결 풀에서는 트랜잭션이 필요할 때마다 연결을 여닫을 필요 없이 일정 시간 동안 연결 집합이 열린 상태로 유지된다. 이는 JDBC 3.0에서 표준화됐다. 

이렇게 연결 풀링을 사용하는 시스템의 애플리케이션 성능은 이를 사용하지 않는 동일한 시스템에 비해 훨씬 더 높고, 전체적인 리소스 사용량은 낮다. 또한 연결 풀링은 연결 생성 시간을 줄이고 리소스 사용에 대한 더 폭넓은 통제력을 제공한다. 단, 애플리케이션과 데이터베이스 구성요소가 연결을 닫고 리소스 풀로 반환하는 부분에 관한 모든 JDBC 단계를 따르는지, 그리고 애플리케이션의 어느 요소가 실제 작동에서 이 부분을 담당하는지 확인하는 것이 중요하다.
 

배치 프로세스 활용 

지금은 실시간 트랜잭션을 강조하는 경우가 많다. 고객 또는 비즈니스 요구에 대응하기 위해 전체 애플리케이션이 실시간으로 작동해야 한다고 믿는다. 하지만 꼭 그런 것은 아니다. 여러 트랜잭션을 처리하는 데 있어서 여러 INSERT 연산을 실행하는 방법보다 일괄 처리가 여전히 가장 일반적이고 가장 효율적인 방법일 수 있다.

특히 JDBC를 활용하면 큰 도움이 된다. JDBC는 일괄 처리를 이해하기 때문이다. 예를 들어 하나의 SQL 문과 여러 바인드 값 집합으로 일괄 INSERT를 만드는 것이 독립적인 여러 작업보다 더 효율적이다. 한 가지 유의해야 할 것은 성능에 영향을 미치지 않도록 트랜잭션이 많지 않은 시간 동안 데이터를 로드해야 한다는 것이다. 이것이 불가능한 상황이라면 대신 더 작은 규모의 일괄 작업을 정기적으로 실행하는 방법이 있다. 이렇게 하면 데이터베이스를 최신 상태로 유지하기 쉽고 트랜잭션 목록을 작게 유지하고 잠재적인 데이터베이스 잠금 또는 경쟁 조건을 피할 수 있다. 

정리하면 SQL을 처음 시작하는 사람에게나 몇 년 동안 사용해 온 사람에게나 SQL은 여전히 미래를 위한 중요한 언어 기술이다. 여기서 살펴본 내용을 실무에 적용하면 애플리케이션 성능을 개선하고 SQL이 가진 이점을 활용할 수 있다. 
editor@itworld.co.kr
CIO Korea 뉴스레터 및 IT 트랜드 보고서 무료 구독하기
Sponsored
추천 테크라이브러리

회사명:한국IDG 제호: CIO Korea 주소 : 서울시 중구 세종대로 23, 4층 우)04512
등록번호 : 서울 아01641 등록발행일자 : 2011년 05월 27일

발행인 : 박형미 편집인 : 천신응 청소년보호책임자 : 한정규
사업자 등록번호 : 214-87-22467 Tel : 02-558-6950

Copyright © 2024 International Data Group. All rights reserved.