이미지 로딩 중...
AI Generated
2025. 11. 22. · 3 Views
SQL SELECT 기초 완벽 가이드 - 데이터 조회의 모든 것
SQL의 가장 기본이 되는 SELECT 문을 완벽하게 마스터해보세요. 데이터베이스에서 원하는 데이터를 조회하는 방법부터 중복 제거, 결과 개수 제한까지 실무에서 바로 사용할 수 있는 모든 기법을 다룹니다. 초급 개발자도 쉽게 따라할 수 있도록 친절하게 설명합니다.
목차
1. SELECT 기본 문법
시작하며
여러분이 도서관에서 책을 찾을 때를 생각해보세요. "저기 있는 책장에서 소설책 좀 찾아줘"라고 사서에게 부탁하는 것처럼, 데이터베이스에도 "이 테이블에서 이런 데이터 좀 찾아줘"라고 요청해야 합니다.
실제 개발 현장에서는 수백만 개의 데이터가 테이블에 저장되어 있습니다. 회원 정보, 주문 내역, 상품 목록 등 우리가 필요한 정보를 찾으려면 올바른 방법으로 요청해야 하죠.
잘못 요청하면 엉뚱한 데이터를 받거나, 아예 데이터를 못 받을 수도 있습니다. 바로 이럴 때 필요한 것이 SELECT 문입니다.
SELECT는 SQL(데이터베이스 언어)에서 가장 기본이 되는 명령어로, "데이터를 조회해줘"라는 의미입니다.
개요
간단히 말해서, SELECT 문은 데이터베이스 테이블에서 원하는 데이터를 가져오는 명령어입니다. 실무에서 여러분이 쇼핑몰을 만든다고 가정해볼까요?
사용자가 "내 주문 내역 보기"를 클릭하면, 서버는 데이터베이스에 "이 사용자의 주문 내역을 가져와줘"라고 요청해야 합니다. 이때 바로 SELECT 문을 사용합니다.
기존에는 데이터를 찾기 위해 파일을 하나하나 열어봐야 했다면, 이제는 SELECT 한 줄로 원하는 데이터를 정확하게 찾을 수 있습니다. SELECT 문의 핵심 특징은 첫째, 어떤 컬럼(열)을 가져올지 지정할 수 있고, 둘째, 어느 테이블에서 가져올지 명확히 할 수 있으며, 셋째, 필요한 조건을 추가해 원하는 데이터만 골라낼 수 있다는 것입니다.
이러한 특징들이 있기 때문에 수백만 개의 데이터 중에서도 정확히 원하는 것만 빠르게 찾을 수 있습니다.
코드 예제
-- 기본 SELECT 문법
-- 형식: SELECT 컬럼명 FROM 테이블명;
SELECT name, email
FROM users;
-- 모든 컬럼 조회
SELECT *
FROM products;
-- 조건을 추가한 SELECT (WHERE 절 사용)
SELECT product_name, price
FROM products
WHERE price > 10000;
설명
이것이 하는 일: SELECT 문은 지정한 테이블에서 원하는 컬럼의 데이터를 가져옵니다. 마치 엑셀 파일에서 특정 열만 복사하는 것과 비슷합니다.
첫 번째로, SELECT 키워드 뒤에 가져올 컬럼 이름을 적습니다. 예를 들어 SELECT name, email이라고 하면 "name과 email 컬럼만 가져와줘"라는 의미입니다.
여러 개의 컬럼을 가져올 때는 쉼표(,)로 구분합니다. 이렇게 하는 이유는 필요한 데이터만 가져와서 속도를 빠르게 하고, 불필요한 정보는 제외하기 위해서입니다.
그 다음으로, FROM 키워드 뒤에 테이블 이름을 적습니다. FROM users라고 하면 "users라는 테이블에서"라는 의미입니다.
데이터베이스에는 여러 개의 테이블이 있을 수 있으므로, 어느 테이블에서 데이터를 가져올지 반드시 명시해야 합니다. WHERE 절을 추가하면 조건에 맞는 데이터만 골라낼 수 있습니다.
WHERE price > 10000이라고 하면 "가격이 10000보다 큰 상품만"이라는 조건을 추가하는 것입니다. 이렇게 하면 전체 데이터 중에서 우리가 원하는 것만 정확하게 찾을 수 있습니다.
여러분이 이 코드를 사용하면 데이터베이스에서 원하는 정보를 빠르고 정확하게 가져올 수 있습니다. 실무에서는 데이터 조회 속도가 매우 중요한데, 필요한 컬럼만 선택하면 네트워크 전송량이 줄어들고, 애플리케이션 성능이 크게 향상됩니다.
또한 보안 측면에서도 민감한 정보(예: 비밀번호)는 제외하고 필요한 정보만 가져올 수 있어 안전합니다.
실전 팁
💡 SELECT 문을 작성할 때는 항상 필요한 컬럼만 명시하세요. SELECT *는 편리하지만 불필요한 데이터까지 가져와서 성능이 떨어질 수 있습니다.
💡 컬럼 이름이나 테이블 이름을 잘못 쓰면 에러가 발생합니다. 오타가 없는지 꼭 확인하고, 대소문자 구분이 있는 데이터베이스도 있으니 주의하세요.
💡 복잡한 쿼리를 작성하기 전에 간단한 SELECT 문으로 먼저 테스트해보세요. 테이블에 어떤 데이터가 있는지 확인한 후 조건을 추가하면 실수를 줄일 수 있습니다.
💡 주석을 활용해서 쿼리의 목적을 명확히 적어두세요. 나중에 다른 개발자가 보거나, 여러분이 다시 볼 때 이해하기 쉽습니다.
💡 데이터베이스 관리 도구(예: MySQL Workbench, pgAdmin)를 사용하면 쿼리 결과를 바로 확인할 수 있어 학습하기 좋습니다.
2. 모든 컬럼 조회하기 (SELECT *)
시작하며
여러분이 처음 데이터베이스를 배울 때, 또는 새로운 테이블을 처음 접했을 때 이런 고민을 해본 적 있나요? "이 테이블에 어떤 컬럼들이 있지?
어떤 데이터가 저장되어 있을까?" 이런 상황은 실제 개발 현장에서 매우 자주 발생합니다. 새로운 프로젝트에 투입되었을 때, 다른 팀이 만든 데이터베이스를 분석해야 할 때, 또는 테이블 구조를 파악해야 할 때 말이죠.
일일이 컬럼 이름을 찾아서 적기에는 시간이 너무 오래 걸립니다. 바로 이럴 때 필요한 것이 SELECT * (별표) 문법입니다.
단 한 글자로 테이블의 모든 컬럼을 한눈에 볼 수 있습니다.
개요
간단히 말해서, SELECT 는 테이블의 모든 컬럼을 가져오는 단축 명령어입니다. 별표()는 "전부 다"라는 의미입니다.
실무에서 새로운 테이블을 처음 접했을 때, 테이블 구조를 빠르게 파악하거나, 샘플 데이터를 확인하고 싶을 때 매우 유용합니다. 예를 들어, 동료가 만든 'customers' 테이블에 어떤 고객 정보가 저장되어 있는지 확인하고 싶다면, SELECT *로 모든 컬럼을 한 번에 볼 수 있습니다.
기존에는 데이터베이스 스키마 문서를 찾아보거나, 테이블 정의를 일일이 확인해야 했다면, 이제는 SELECT * 한 줄로 실제 데이터와 함께 모든 컬럼을 확인할 수 있습니다. SELECT *의 핵심 특징은 첫째, 빠르고 간편하게 모든 데이터를 볼 수 있고, 둘째, 테이블 구조 파악에 탁월하며, 셋째, 개발 중 디버깅할 때 전체 데이터를 확인하기 좋다는 것입니다.
다만 주의할 점은, 프로덕션 환경에서는 성능 문제가 있을 수 있으므로 조심해서 사용해야 합니다.
코드 예제
-- 모든 컬럼 조회 (기본)
SELECT *
FROM products;
-- LIMIT과 함께 사용하여 샘플 데이터 확인
SELECT *
FROM customers
LIMIT 5;
-- 조건과 함께 사용
SELECT *
FROM orders
WHERE order_date >= '2024-01-01';
-- 여러 테이블 조회 시 (JOIN)
SELECT *
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id
LIMIT 10;
설명
이것이 하는 일: SELECT *는 지정한 테이블에 있는 모든 컬럼의 데이터를 가져옵니다. 컬럼 이름을 하나하나 적지 않아도 되므로 매우 편리합니다.
첫 번째로, SELECT 키워드 뒤에 별표(*)를 적으면 "모든 컬럼을 가져와줘"라는 의미가 됩니다. 예를 들어 products 테이블에 id, name, price, stock, description 등 10개의 컬럼이 있다면, 이 10개를 모두 가져옵니다.
이렇게 하는 이유는 테이블의 전체 구조를 한눈에 파악하거나, 어떤 데이터가 저장되어 있는지 빠르게 확인하기 위해서입니다. 그 다음으로, LIMIT 절과 함께 사용하면 더욱 효과적입니다.
SELECT * FROM customers LIMIT 5라고 하면 모든 컬럼을 가져오되, 처음 5개 행만 가져옵니다. 테이블에 수백만 개의 행이 있어도 샘플만 빠르게 확인할 수 있어서, 개발할 때 매우 유용합니다.
WHERE 절을 함께 사용하면 조건에 맞는 데이터의 모든 컬럼을 볼 수 있습니다. 예를 들어 특정 날짜 이후의 주문 데이터를 전부 확인하고 싶을 때, SELECT * FROM orders WHERE order_date >= '2024-01-01'처럼 사용합니다.
이렇게 하면 조건을 만족하는 주문의 모든 정보를 확인할 수 있습니다. 여러분이 이 코드를 사용하면 개발 속도가 크게 빨라집니다.
새로운 테이블을 분석할 때 몇 초 만에 전체 구조를 파악할 수 있고, 디버깅할 때 데이터 전체를 확인해서 문제를 빠르게 찾을 수 있습니다. 다만 실제 서비스 코드에서는 필요한 컬럼만 명시하는 것이 좋습니다.
SELECT *는 불필요한 데이터까지 가져와서 네트워크 부하가 커지고, 나중에 테이블에 새 컬럼이 추가되면 예상치 못한 문제가 생길 수 있기 때문입니다.
실전 팁
💡 개발 단계에서는 SELECT *가 편리하지만, 실제 서비스 코드에서는 필요한 컬럼만 명시하세요. 성능과 유지보수성이 크게 향상됩니다.
💡 큰 테이블을 조회할 때는 반드시 LIMIT을 함께 사용하세요. SELECT * FROM big_table LIMIT 100 처럼 하면 실수로 수백만 개의 행을 가져오는 것을 방지할 수 있습니다.
💡 테이블 구조를 파악할 때는 DESCRIBE 또는 SHOW COLUMNS 명령어도 활용하세요. 이 명령어들은 컬럼의 데이터 타입, 제약조건 등 메타 정보를 보여줍니다.
💡 여러 테이블을 JOIN할 때 SELECT 를 사용하면 어느 테이블의 컬럼인지 헷갈릴 수 있습니다. 이럴 때는 SELECT o., c.name, c.email 처럼 일부만 명시하는 방법을 사용하세요.
💡 프로덕션 환경에서 SELECT *를 사용했다면, 코드 리뷰 때 꼭 지적받을 수 있으니 개발이 끝나면 필요한 컬럼만 명시하도록 리팩토링하세요.
3. 특정 컬럼만 선택하기
시작하며
여러분이 온라인 쇼핑몰에서 상품 목록을 보여주는 페이지를 만든다고 생각해보세요. 사용자에게는 상품 이름, 가격, 이미지만 보여주면 되는데, 데이터베이스에서 재고 수량, 공급업체 정보, 내부 메모까지 모두 가져온다면 어떻게 될까요?
이런 문제는 실제 개발 현장에서 성능 저하의 주요 원인이 됩니다. 불필요한 데이터를 가져오면 네트워크 전송 시간이 길어지고, 서버 메모리를 낭비하며, 응답 속도가 느려져서 사용자 경험이 나빠집니다.
또한 보안 측면에서도 민감한 정보가 노출될 위험이 있습니다. 바로 이럴 때 필요한 것이 특정 컬럼만 선택하는 기법입니다.
필요한 데이터만 정확히 가져와서 효율성을 극대화할 수 있습니다.
개요
간단히 말해서, SELECT 문에서 원하는 컬럼 이름을 쉼표로 구분해서 나열하면, 그 컬럼들의 데이터만 가져올 수 있습니다. 실무에서는 거의 대부분의 경우 특정 컬럼만 선택합니다.
예를 들어, 사용자 목록을 보여주는 관리자 페이지에서는 이름, 이메일, 가입일만 필요하지, 비밀번호 해시나 내부 설정 같은 것은 필요 없습니다. 이런 경우 SELECT name, email, created_at FROM users 처럼 필요한 컬럼만 명시합니다.
기존에 SELECT *로 모든 컬럼을 가져왔다면, 이제는 필요한 것만 골라서 가져옴으로써 데이터 전송량을 크게 줄일 수 있습니다. 예를 들어 테이블에 20개의 컬럼이 있는데 3개만 필요하다면, 데이터 전송량을 약 85% 줄일 수 있습니다.
특정 컬럼 선택의 핵심 특징은 첫째, 성능이 크게 향상되고, 둘째, 보안이 강화되며(민감한 정보 제외), 셋째, 코드 가독성이 좋아진다는 것입니다(어떤 데이터를 사용하는지 명확함). 이러한 특징들이 있기 때문에 프로페셔널한 개발자들은 거의 항상 필요한 컬럼만 명시합니다.
코드 예제
-- 기본: 특정 컬럼 3개만 선택
SELECT name, email, phone
FROM customers;
-- 컬럼에 별칭 붙이기 (AS 사용)
SELECT
product_name AS name,
price AS cost,
stock_quantity AS stock
FROM products;
-- 계산된 값 포함
SELECT
product_name,
price,
price * 0.9 AS discounted_price,
stock_quantity
FROM products
WHERE stock_quantity > 0;
-- 여러 테이블에서 선택 (JOIN)
SELECT
c.name,
c.email,
o.order_date,
o.total_amount
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id;
설명
이것이 하는 일: SELECT 문에서 가져올 컬럼 이름들을 명시하면, 테이블에서 그 컬럼들의 데이터만 가져옵니다. 마치 엑셀에서 필요한 열만 복사하는 것과 같습니다.
첫 번째로, SELECT 키워드 뒤에 원하는 컬럼 이름을 쉼표(,)로 구분해서 나열합니다. SELECT name, email, phone이라고 하면 이 세 개의 컬럼만 가져옵니다.
이렇게 하는 이유는 데이터베이스가 필요한 데이터만 읽어서 처리하므로 속도가 빨라지고, 네트워크로 전송할 데이터 양이 줄어들어 응답 시간이 단축되기 때문입니다. 그 다음으로, AS 키워드를 사용하면 컬럼에 별칭을 붙일 수 있습니다.
SELECT product_name AS name이라고 하면, 결과에서 'product_name' 대신 'name'이라는 이름으로 표시됩니다. 이는 컬럼 이름이 길거나 복잡할 때, 또는 프론트엔드에서 사용하기 쉬운 이름으로 바꾸고 싶을 때 유용합니다.
또한 price * 0.9 AS discounted_price처럼 계산된 값에도 이름을 붙일 수 있습니다. 계산식도 컬럼처럼 선택할 수 있습니다.
SELECT price, price * 0.9 AS discounted_price라고 하면 원래 가격과 함께 10% 할인된 가격도 함께 조회됩니다. 이렇게 하면 데이터베이스에서 직접 계산을 수행하므로, 애플리케이션 코드에서 따로 계산할 필요가 없어집니다.
여러 테이블을 JOIN할 때는 테이블 별칭을 사용하면 코드가 훨씬 깔끔해집니다. SELECT c.name, o.order_date처럼 테이블별칭.컬럼명 형식으로 작성하면, 어느 테이블의 컬럼인지 명확히 알 수 있습니다.
같은 이름의 컬럼이 여러 테이블에 있을 때는 이 방법이 필수입니다. 여러분이 이 코드를 사용하면 애플리케이션 성능이 크게 향상됩니다.
실제로 필요한 3개의 컬럼만 가져오는 것과 20개 컬럼을 모두 가져오는 것은 속도 차이가 몇 배나 날 수 있습니다. 또한 코드의 의도가 명확해져서 다른 개발자가 볼 때도 "아, 이 쿼리는 사용자의 이름과 이메일만 필요하구나"라고 바로 이해할 수 있습니다.
보안 측면에서도 password_hash, social_security_number 같은 민감한 정보를 제외할 수 있어 안전합니다.
실전 팁
💡 컬럼 이름을 적을 때 순서는 상관없지만, 중요한 컬럼을 앞에 배치하면 데이터를 확인할 때 편리합니다. 보통 ID, 이름, 날짜 순으로 배치합니다.
💡 JOIN을 사용할 때는 항상 테이블 별칭을 붙이고 테이블.컬럼 형식으로 작성하세요. 나중에 쿼리가 복잡해져도 어느 테이블의 컬럼인지 명확합니다.
💡 AS 키워드는 생략 가능합니다. SELECT name AS customer_name과 SELECT name customer_name은 동일하지만, AS를 쓰는 것이 더 읽기 쉽습니다.
💡 계산식을 사용할 때는 반드시 별칭을 붙이세요. 별칭이 없으면 결과 컬럼 이름이 price * 0.9 같은 식으로 나와서 프로그램에서 사용하기 어렵습니다.
💡 프론트엔드와 협업할 때는 컬럼 이름을 camelCase나 snake_case로 통일하세요. SELECT user_name AS userName 처럼 하면 JavaScript에서 바로 사용하기 편리합니다.
4. DISTINCT로 중복 제거
시작하며
여러분이 온라인 쇼핑몰에서 "우리 쇼핑몰에 어떤 브랜드의 제품들이 있는지 목록을 보여줘"라는 요청을 받았다고 상상해보세요. products 테이블에는 같은 브랜드의 제품이 수십 개씩 있을 텐데, 브랜드 목록만 보고 싶은데 중복된 브랜드 이름이 계속 나타난다면 어떻게 될까요?
이런 상황은 실무에서 매우 흔합니다. 설문조사에서 어떤 지역의 사람들이 참여했는지, 주문 데이터에서 어떤 결제 수단이 사용되었는지, 회원 데이터에서 어떤 직업군이 가입했는지 등 "종류"나 "카테고리"를 파악해야 할 때 중복된 값들이 계속 나타나는 문제가 생깁니다.
바로 이럴 때 필요한 것이 DISTINCT 키워드입니다. 중복된 값을 자동으로 제거하고 고유한 값만 보여주어, 데이터의 종류를 한눈에 파악할 수 있게 해줍니다.
개요
간단히 말해서, DISTINCT는 SELECT 결과에서 중복된 행을 제거하고 고유한 값만 반환하는 키워드입니다. 실무에서는 데이터 분석, 통계 작성, 필터 옵션 생성 등 다양한 곳에서 사용됩니다.
예를 들어, 쇼핑몰의 상품 필터에서 "브랜드" 옵션을 만들 때 SELECT DISTINCT brand FROM products를 사용하면 중복 없이 모든 브랜드 목록을 가져올 수 있습니다. 또는 어떤 도시의 사용자들이 있는지 파악할 때 SELECT DISTINCT city FROM users로 도시 목록만 뽑아낼 수 있습니다.
기존에는 데이터를 가져온 후 프로그래밍 언어(JavaScript, Python 등)에서 반복문을 돌려 중복을 제거해야 했다면, 이제는 데이터베이스에서 DISTINCT 한 단어만 추가하면 자동으로 중복이 제거된 결과를 받을 수 있습니다. DISTINCT의 핵심 특징은 첫째, 중복 제거가 자동으로 이루어지고, 둘째, 데이터베이스 레벨에서 처리되어 효율적이며, 셋째, 여러 컬럼의 조합에도 적용할 수 있다는 것입니다.
이러한 특징들 덕분에 데이터의 고유값을 빠르게 파악하고, 불필요한 데이터 전송을 줄일 수 있습니다.
코드 예제
-- 기본: 중복 제거하여 고유한 브랜드만 조회
SELECT DISTINCT brand
FROM products;
-- 여러 컬럼의 조합으로 중복 제거
SELECT DISTINCT city, country
FROM customers;
-- COUNT와 함께 사용하여 고유값 개수 세기
SELECT COUNT(DISTINCT category) AS unique_categories
FROM products;
-- 조건과 함께 사용
SELECT DISTINCT payment_method
FROM orders
WHERE order_date >= '2024-01-01';
-- 정렬과 함께 사용
SELECT DISTINCT brand
FROM products
ORDER BY brand ASC;
설명
이것이 하는 일: DISTINCT 키워드를 SELECT 바로 뒤에 붙이면, 쿼리 결과에서 중복된 행을 자동으로 제거하고 고유한 값들만 반환합니다. 첫 번째로, SELECT DISTINCT brand FROM products라고 하면 products 테이블의 brand 컬럼에서 중복을 제거한 고유한 브랜드 이름만 가져옵니다.
예를 들어 products 테이블에 'Nike' 제품이 100개, 'Adidas' 제품이 50개 있어도, 결과는 'Nike'와 'Adidas' 단 2개의 행만 반환됩니다. 이렇게 하는 이유는 "어떤 브랜드가 있는지" 종류만 알면 되기 때문입니다.
그 다음으로, 여러 컬럼을 함께 사용하면 그 조합이 고유한 행만 반환됩니다. SELECT DISTINCT city, country FROM customers라고 하면, '서울, 한국'과 '부산, 한국'은 다른 조합으로 취급되어 둘 다 결과에 포함됩니다.
하지만 '서울, 한국'이라는 조합이 100번 나타나도 결과에는 한 번만 표시됩니다. COUNT 함수와 함께 사용하면 고유한 값의 개수를 셀 수 있습니다.
SELECT COUNT(DISTINCT category) FROM products는 제품 카테고리가 총 몇 종류인지 알려줍니다. 예를 들어 1000개의 제품이 있지만 카테고리는 10종류라면, 결과는 10이 됩니다.
이는 데이터 분석이나 통계를 낼 때 매우 유용합니다. WHERE 절과 함께 사용하면 특정 조건을 만족하는 데이터 중에서 고유값만 추출할 수 있습니다.
예를 들어 SELECT DISTINCT payment_method FROM orders WHERE order_date >= '2024-01-01'은 "2024년 이후 주문에서 사용된 결제 수단 종류"를 보여줍니다. 여러분이 이 코드를 사용하면 데이터 분석이 훨씬 쉬워집니다.
쇼핑몰의 상품 필터(브랜드, 카테고리, 색상 등)를 만들 때 DISTINCT로 옵션 목록을 가져올 수 있고, 사용자 통계를 낼 때 "몇 개 도시에서 접속했는지", "어떤 직업군이 있는지" 등을 빠르게 파악할 수 있습니다. 또한 데이터 품질을 검증할 때도 유용합니다.
예를 들어 "status 컬럼에 어떤 값들이 들어있는지" 확인해서 오타나 잘못된 데이터를 찾아낼 수 있습니다.
실전 팁
💡 DISTINCT는 모든 컬럼을 비교해서 중복을 판단하므로, 컬럼이 많을수록 처리 시간이 길어집니다. 꼭 필요한 컬럼만 선택하세요.
💡 대용량 데이터에서 DISTINCT를 사용하면 느릴 수 있습니다. 이럴 때는 GROUP BY를 사용하는 것이 더 빠를 수 있으니 성능 테스트를 해보세요.
💡 NULL 값도 하나의 고유값으로 취급됩니다. 여러 행에 NULL이 있어도 결과에는 NULL이 한 번만 나타납니다.
💡 DISTINCT COUNT는 SELECT COUNT(DISTINCT column)처럼 사용해야 합니다. SELECT DISTINCT COUNT(column)은 의미가 다르니 주의하세요.
💡 정렬(ORDER BY)과 함께 사용하면 고유값을 알파벳순이나 숫자순으로 정렬해서 볼 수 있어 더욱 편리합니다.
5. LIMIT으로 결과 개수 제한
시작하며
여러분이 블로그 사이트를 만들면서 "최신 게시글 10개만 보여주기" 기능을 구현한다고 생각해보세요. 데이터베이스에는 수천 개의 게시글이 있는데, 전부 가져와서 프로그램에서 10개만 자르면 어떻게 될까요?
이런 문제는 실제 서비스에서 심각한 성능 저하를 일으킵니다. 수천 개의 데이터를 모두 읽어서 네트워크로 전송하고, 메모리에 올린 다음 10개만 사용하고 나머지는 버린다면, 엄청난 자원 낭비가 발생합니다.
사용자는 페이지 로딩이 느려지고, 서버는 불필요한 부하를 받게 됩니다. 바로 이럴 때 필요한 것이 LIMIT 절입니다.
데이터베이스에서 처음부터 필요한 개수만 가져오도록 제한해서, 효율성을 극대화할 수 있습니다.
개요
간단히 말해서, LIMIT은 SELECT 쿼리 결과의 개수를 제한하는 키워드입니다. "최대 N개만 가져와"라는 의미입니다.
실무에서는 페이지네이션(pagination, 페이지 나누기), 최신 데이터 미리보기, 샘플 데이터 확인 등에 필수적으로 사용됩니다. 예를 들어, SNS의 피드에서 "더보기" 버튼을 누를 때마다 10개씩 추가로 로딩하는 기능, 관리자 대시보드에서 "최근 주문 5건"을 보여주는 기능 등이 모두 LIMIT을 사용합니다.
기존에는 데이터를 모두 가져온 후 프로그래밍 언어에서 배열을 자르는 방식(예: array.slice(0, 10))을 사용했다면, 이제는 데이터베이스에서 처음부터 필요한 개수만 읽어오므로 I/O, 네트워크, 메모리 사용량이 모두 줄어듭니다. LIMIT의 핵심 특징은 첫째, 데이터베이스가 필요한 개수만 읽으므로 매우 빠르고, 둘째, OFFSET과 함께 사용하면 페이지네이션을 구현할 수 있으며, 셋째, ORDER BY와 함께 사용하면 "상위 N개", "최신 N개" 같은 기능을 쉽게 만들 수 있다는 것입니다.
이러한 특징들 덕분에 대용량 데이터를 다루는 모든 애플리케이션에서 필수적으로 사용됩니다.
코드 예제
-- 기본: 최신 게시글 10개만 조회
SELECT title, created_at
FROM posts
ORDER BY created_at DESC
LIMIT 10;
-- OFFSET과 함께 사용 (페이지네이션)
-- 2페이지(11~20번째) 조회
SELECT title, author
FROM posts
ORDER BY id DESC
LIMIT 10 OFFSET 10;
-- 가장 비싼 상품 5개 조회
SELECT product_name, price
FROM products
ORDER BY price DESC
LIMIT 5;
-- 조건과 함께 사용
SELECT name, email
FROM customers
WHERE city = 'Seoul'
LIMIT 100;
-- 랜덤 샘플 추출 (데이터베이스에 따라 문법 다름)
SELECT *
FROM products
ORDER BY RANDOM()
LIMIT 5;
설명
이것이 하는 일: LIMIT 키워드를 쿼리 끝에 붙이면, 데이터베이스가 지정한 개수만큼만 결과를 반환합니다. 나머지 데이터는 읽지도 않습니다.
첫 번째로, SELECT * FROM posts ORDER BY created_at DESC LIMIT 10이라고 하면, 게시글을 최신순으로 정렬한 후 처음 10개만 가져옵니다. 중요한 점은 데이터베이스가 10개를 찾으면 즉시 멈춘다는 것입니다.
테이블에 10,000개의 게시글이 있어도 10개만 읽으므로 매우 빠릅니다. ORDER BY와 함께 사용하는 것이 일반적이며, 정렬 없이 LIMIT만 사용하면 어떤 데이터가 반환될지 예측할 수 없습니다.
그 다음으로, OFFSET을 함께 사용하면 "건너뛰기"를 할 수 있습니다. LIMIT 10 OFFSET 10은 "처음 10개는 건너뛰고, 그 다음 10개를 가져와"라는 의미입니다.
이는 페이지네이션에 핵심적으로 사용됩니다. 1페이지는 LIMIT 10 OFFSET 0, 2페이지는 LIMIT 10 OFFSET 10, 3페이지는 LIMIT 10 OFFSET 20 이런 식으로 구현합니다.
다만 OFFSET이 커질수록(예: OFFSET 10000) 성능이 나빠지는 단점이 있습니다. ORDER BY와 조합하면 강력한 기능들을 만들 수 있습니다.
ORDER BY price DESC LIMIT 5는 가격이 높은 순서로 정렬해서 상위 5개를 가져옵니다. 즉, "가장 비싼 상품 5개"를 조회하는 것입니다.
반대로 ORDER BY price ASC LIMIT 5는 "가장 저렴한 상품 5개"를 가져옵니다. WHERE 절과 함께 사용하면 조건을 만족하는 데이터 중에서 제한된 개수만 가져올 수 있습니다.
SELECT * FROM customers WHERE city = 'Seoul' LIMIT 100은 서울 거주 고객 중 처음 100명만 가져옵니다. 전체 서울 고객이 10,000명이어도 100명만 읽으므로 훨씬 빠릅니다.
여러분이 이 코드를 사용하면 애플리케이션의 응답 속도가 극적으로 빨라집니다. 실제 서비스에서 "전체 게시글 조회"와 "최신 10개 게시글 조회"는 속도 차이가 수백 배까지 날 수 있습니다.
또한 모바일 앱이나 웹에서 "무한 스크롤" 기능을 구현할 때 LIMIT과 OFFSET을 사용하면 사용자가 스크롤할 때마다 추가 데이터를 효율적으로 로딩할 수 있습니다. 서버 자원도 아끼고, 네트워크 비용도 줄이며, 사용자 경험도 개선되는 일석삼조의 효과가 있습니다.
실전 팁
💡 LIMIT을 사용할 때는 반드시 ORDER BY를 함께 사용하세요. 정렬 없이 사용하면 매번 다른 결과가 나올 수 있어 예측 불가능합니다.
💡 페이지네이션에서 OFFSET이 매우 클 때(예: 1000페이지)는 성능이 나쁩니다. 이럴 때는 "커서 기반 페이지네이션"(WHERE id > last_id LIMIT 10)을 고려하세요.
💡 데이터베이스마다 문법이 다릅니다. MySQL/PostgreSQL은 LIMIT, SQL Server는 TOP, Oracle은 ROWNUM 또는 FETCH를 사용합니다.
💡 대용량 테이블에서 샘플 데이터를 빠르게 확인하려면 LIMIT 10이나 LIMIT 100을 습관화하세요. 실수로 수백만 건을 조회하는 것을 방지할 수 있습니다.
💡 COUNT(*)와 함께 사용할 때 주의하세요. SELECT COUNT(*) FROM table LIMIT 10은 의미가 없습니다. COUNT는 항상 1개의 행만 반환하기 때문입니다.
6. 주석 작성 방법
시작하며
여러분이 6개월 전에 작성한 복잡한 SQL 쿼리를 다시 봤는데, "이 쿼리가 뭐 하는 거였지?"라고 고민해본 적 있나요? 또는 동료가 작성한 쿼리를 수정해야 하는데, 어떤 의도로 작성했는지 이해하기 어려웠던 경험은요?
이런 문제는 실제 개발 팀에서 매우 자주 발생합니다. SQL 쿼리가 복잡해질수록, 특히 여러 테이블을 JOIN하거나 복잡한 조건이 있을 때, 코드만 보고는 의도를 파악하기 어렵습니다.
이는 유지보수 시간을 늘리고, 실수를 유발하며, 팀 협업을 어렵게 만듭니다. 바로 이럴 때 필요한 것이 SQL 주석입니다.
코드의 의도, 주의사항, 작성 이유 등을 명확히 기록해서 나중에 자신도, 다른 개발자도 쉽게 이해할 수 있게 만듭니다.
개요
간단히 말해서, SQL 주석은 쿼리에 설명을 추가하는 방법으로, 실행에는 영향을 주지 않고 사람이 읽기 위한 메모를 남기는 것입니다. 실무에서는 복잡한 비즈니스 로직을 설명하거나, 특정 쿼리를 작성한 이유를 기록하거나, 주의해야 할 점을 알리는 데 사용됩니다.
예를 들어, "왜 이 인덱스를 사용하는지", "특정 날짜 범위를 왜 이렇게 설정했는지", "성능 이슈로 인해 어떤 최적화를 했는지" 등을 주석으로 남깁니다. 기존에는 별도의 문서에 쿼리 설명을 작성했다면, 이제는 코드 바로 옆에 주석을 달아서 코드와 설명이 함께 있게 할 수 있습니다.
이렇게 하면 문서와 코드가 따로 놀아서 불일치하는 문제를 방지할 수 있습니다. SQL 주석의 핵심 특징은 첫째, 한 줄 주석(--)과 여러 줄 주석(/* */)을 모두 지원하고, 둘째, 실행 성능에 전혀 영향을 주지 않으며, 셋째, 코드 리뷰와 협업에 매우 유용하다는 것입니다.
프로페셔널한 개발자는 복잡한 쿼리에 반드시 주석을 달아서 유지보수성을 높입니다.
코드 예제
-- 한 줄 주석: 최근 30일간 활성 사용자 조회
SELECT name, email, last_login
FROM users
WHERE last_login >= CURRENT_DATE - INTERVAL '30 days'
ORDER BY last_login DESC;
/*
여러 줄 주석:
이 쿼리는 월간 매출 리포트를 생성합니다.
- 취소된 주문은 제외
- VAT 포함 가격으로 계산
- 작성자: 홍길동
- 작성일: 2024-01-15
*/
SELECT
DATE_TRUNC('month', order_date) AS month,
SUM(total_amount * 1.1) AS revenue_with_vat -- VAT 10% 포함
FROM orders
WHERE status != 'cancelled' -- 취소 주문 제외
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY month DESC;
-- 임시로 주석 처리하여 코드 비활성화
SELECT product_name, price
FROM products
-- WHERE category = 'Electronics' -- 테스트를 위해 임시 비활성화
LIMIT 10;
설명
이것이 하는 일: SQL 주석은 쿼리에 설명을 추가하여 코드를 읽는 사람(미래의 자신 포함)이 쉽게 이해할 수 있도록 돕습니다. 주석은 데이터베이스 실행 시 완전히 무시됩니다.
첫 번째로, 한 줄 주석은 하이픈 두 개(--)로 시작합니다. -- 이것은 주석입니다처럼 작성하면 그 줄의 끝까지가 주석으로 처리됩니다.
짧은 설명이나 간단한 메모를 남길 때 유용합니다. 예를 들어 WHERE status != 'cancelled' -- 취소 주문 제외처럼 코드 옆에 바로 설명을 붙일 수 있습니다.
이렇게 하면 "왜 취소 주문을 제외하는지" 즉시 알 수 있습니다. 그 다음으로, 여러 줄 주석은 /* */로 감쌉니다.
/* 이것은 여러 줄 주석입니다 */ 형태로 작성하며, 시작(/) 과 끝(/) 사이의 모든 내용이 주석 처리됩니다. 긴 설명이나 문서화가 필요할 때 사용합니다.
쿼리 맨 위에 작성자, 작성 목적, 주의사항 등을 상세히 적으면 다른 개발자가 코드를 이해하기 훨씬 쉽습니다. 주석은 코드를 임시로 비활성화할 때도 사용됩니다.
디버깅 중에 특정 조건을 잠시 끄고 싶을 때, 해당 줄 앞에 --를 붙이면 됩니다. 예를 들어 -- WHERE category = 'Electronics'처럼 하면 이 조건이 적용되지 않습니다.
나중에 다시 활성화하려면 --만 지우면 되므로 매우 편리합니다. 복잡한 비즈니스 로직을 설명할 때 주석은 필수입니다.
예를 들어 SUM(total_amount * 1.1) AS revenue_with_vat -- VAT 10% 포함처럼 하면, 왜 1.1을 곱하는지 명확히 알 수 있습니다. 주석 없이 코드만 보면 "왜 1.1을 곱하지?"라고 혼란스러울 수 있지만, 주석이 있으면 즉시 이해됩니다.
여러분이 이 코드를 사용하면 팀 협업이 훨씬 원활해집니다. 코드 리뷰할 때 리뷰어가 의도를 바로 파악할 수 있고, 나중에 유지보수할 때 "왜 이렇게 작성했는지" 고민하는 시간을 크게 줄일 수 있습니다.
특히 복잡한 JOIN 쿼리, 성능 최적화를 위한 특수한 기법, 비즈니스 규칙을 반영한 계산식 등은 반드시 주석으로 설명해야 합니다. 6개월 후의 여러분이 감사할 것입니다.
실전 팁
💡 "무엇을"보다 "왜"를 설명하세요. WHERE status = 'active' -- 활성 사용자만보다는 WHERE status = 'active' -- 비활성 사용자는 로그인 불가하므로 제외가 더 유용합니다.
💡 복잡한 쿼리는 섹션별로 주석을 나누세요. "1. 기본 데이터 조회", "2. 집계 계산", "3. 필터링" 같은 식으로 구조를 설명하면 이해하기 쉽습니다.
💡 성능 관련 결정(예: 특정 인덱스 사용, LIMIT 추가)은 반드시 주석으로 이유를 남기세요. 나중에 "왜 이렇게 했지?"하는 의문을 방지할 수 있습니다.
💡 임시 코드나 테스트용 쿼리는 주석에 날짜와 "TODO" 또는 "TEMP"를 표시하세요. -- TODO 2024-11-22: 프로덕션 배포 전 제거 같은 식으로 작성하면 놓치지 않습니다.
💡 주석을 너무 많이 달아도 오히려 가독성이 떨어집니다. 자명한 코드(SELECT name FROM users -- 이름 조회)에는 주석이 불필요합니다. 복잡하거나 특별한 이유가 있는 부분에만 달아주세요.
댓글 (0)
함께 보면 좋은 카드 뉴스
SQL 실전 종합 프로젝트 완벽 가이드
전자상거래 시스템을 직접 구축하면서 배우는 SQL 실전 프로젝트입니다. DB 설계부터 성능 최적화까지, 실무에서 필요한 모든 SQL 기술을 단계별로 마스터할 수 있습니다. 초급 개발자도 따라하기 쉬운 친절한 가이드로 구성되어 있습니다.
실무 데이터 분석 SQL 완벽 가이드
실제 업무에서 자주 사용하는 SQL 데이터 분석 기법을 단계별로 학습합니다. 매출 집계부터 고객 세분화까지, 실전 대시보드 쿼리 작성 방법을 배워보세요.
데이터 모델링과 정규화 완벽 가이드
데이터베이스 설계의 핵심인 데이터 모델링과 정규화를 초급 개발자 눈높이에서 쉽게 설명합니다. ERD 작성부터 제1~3정규형, 정규화의 장단점, 비정규화 전략, 실무 설계 패턴까지 실전에서 바로 활용할 수 있는 노하우를 담았습니다.
트랜잭션과 ACID 원칙 완벽 가이드
데이터베이스의 핵심 개념인 트랜잭션과 ACID 원칙을 초급 개발자도 쉽게 이해할 수 있도록 실무 예제와 함께 설명합니다. 안전한 데이터 처리를 위한 필수 지식을 친근하게 배워보세요.
인덱스와 쿼리 성능 최적화 완벽 가이드
데이터베이스 성능의 핵심인 인덱스를 처음부터 끝까지 배워봅니다. B-Tree 구조부터 실행 계획 분석까지, 실무에서 바로 사용할 수 있는 인덱스 최적화 전략을 초급자도 이해할 수 있게 설명합니다.