← 블로그 목록

SQL 포맷터 완벽 가이드 - SQL 정렬·들여쓰기·가독성 향상 무료 온라인 도구 | HMApps

SQL 포맷터로 복잡한 쿼리를 깔끔하게 정렬하고, 가독성을 높여 디버깅 시간을 줄여보세요. 설치 없이 브라우저에서 바로 사용하는 SQL 포맷팅 완벽 가이드와 실전 팁을 소개합니다.

광고

SQL 포맷터란 무엇인가요?

SQL(Structured Query Language)은 데이터베이스를 다루는 개발자라면 매일 사용하는 언어입니다. 간단한 SELECT 문부터 수십 개의 JOIN과 서브쿼리가 중첩된 복잡한 분석 쿼리까지, SQL은 현대 소프트웨어 개발에서 빠질 수 없는 핵심 도구입니다.

그런데 실제 업무에서 마주치는 SQL은 대부분 가독성을 전혀 고려하지 않은 형태입니다. ORM이 자동 생성한 쿼리, 레거시 코드에서 복사한 쿼리, 또는 데이터베이스 로그에서 추출한 쿼리는 아래처럼 한 줄로 뭉쳐진 경우가 많습니다.

SELECT u.id,u.name,u.email,o.order_id,o.total_price,p.product_name FROM users u INNER JOIN orders o ON u.id=o.user_id INNER JOIN order_items oi ON o.order_id=oi.order_id INNER JOIN products p ON oi.product_id=p.product_id WHERE u.created_at>='2026-01-01' AND o.status='completed' ORDER BY o.total_price DESC LIMIT 100

이런 쿼리를 그대로 읽고 수정하기란 쉽지 않습니다. SQL 포맷터는 이렇게 가독성이 낮은 SQL을 키워드 줄 맞춤, 들여쓰기, 절(clause) 분리를 적용해 사람이 읽기 쉬운 형태로 변환해주는 도구입니다. HMApps SQL 포맷터(hmapps.kr/sql-formatter)는 설치나 회원가입 없이 브라우저에서 바로 사용할 수 있습니다.

SQL 포맷터 사용 방법

HMApps SQL 포맷터는 직관적인 인터페이스로 누구나 쉽게 사용할 수 있습니다.

  1. SQL 붙여넣기: 입력창에 포맷팅할 SQL 쿼리를 붙여넣습니다.
  2. 포맷 버튼 클릭: [포맷] 버튼을 누르면 즉시 들여쓰기와 키워드 정렬이 적용된 SQL이 출력됩니다.
  3. 결과 확인: 정렬된 SQL을 확인하고 가독성이 개선된 구조를 한눈에 파악합니다.
  4. 복사: [복사] 버튼으로 포맷팅된 SQL을 클립보드에 저장합니다.
  5. 압축: 반대로 [압축] 기능을 사용하면 공백을 제거해 한 줄짜리 SQL로 만들 수도 있습니다.

위의 한 줄 SQL을 포맷터에 넣으면 다음처럼 변환됩니다.

SELECT
  u.id,
  u.name,
  u.email,
  o.order_id,
  o.total_price,
  p.product_name
FROM
  users u
  INNER JOIN orders o ON u.id = o.user_id
  INNER JOIN order_items oi ON o.order_id = oi.order_id
  INNER JOIN products p ON oi.product_id = p.product_id
WHERE
  u.created_at >= '2026-01-01'
  AND o.status = 'completed'
ORDER BY
  o.total_price DESC
LIMIT
  100

한눈에 보이는 차이가 느껴지시나요? JOIN이 몇 개인지, WHERE 조건이 무엇인지, 정렬 기준이 무엇인지를 단번에 파악할 수 있게 됩니다.

SQL 포맷터가 꼭 필요한 5가지 상황

1. ORM이 생성한 쿼리 분석

Django ORM, SQLAlchemy, JPA(Hibernate) 등의 ORM 프레임워크는 자동으로 SQL을 생성합니다. 쿼리 성능을 최적화하거나 N+1 문제를 디버깅할 때, ORM이 실제로 어떤 SQL을 실행하는지 확인해야 합니다. ORM이 출력하는 SQL은 대부분 한 줄짜리 압축 형태이기 때문에 포맷터 없이는 읽기 어렵습니다.

-- ORM이 출력한 raw SQL (읽기 어려움)
SELECT "users"."id","users"."name","orders"."total" FROM "users" INNER JOIN "orders" ON ("users"."id"="orders"."user_id") WHERE "orders"."status"=completed

-- 포맷터 적용 후 (구조가 명확해짐)
SELECT
  "users"."id",
  "users"."name",
  "orders"."total"
FROM
  "users"
  INNER JOIN "orders" ON ("users"."id" = "orders"."user_id")
WHERE
  "orders"."status" = completed

2. 레거시 코드의 SQL 리팩터링

오래된 코드베이스에는 수백 줄짜리 SQL 문자열이 한 줄로 연결된 경우가 많습니다. 이를 포맷팅하면 중복 조건, 불필요한 서브쿼리, 잘못된 JOIN 방향 등의 문제를 쉽게 찾아낼 수 있습니다. 리팩터링 전 포맷터로 먼저 구조를 파악하는 것이 시간을 절약하는 핵심 습관입니다.

3. 코드 리뷰에서 SQL 변경 사항 검토

Pull Request에서 SQL 파일이나 마이그레이션 스크립트를 리뷰할 때, 압축된 SQL은 변경 내용을 파악하기 어렵습니다. 포맷터로 정렬한 버전을 비교하면 어떤 테이블이 추가됐고, 어떤 조건이 바뀌었는지 명확히 확인할 수 있습니다. HMApps의 텍스트 비교 도구와 함께 활용하면 SQL 변경 diff를 한눈에 볼 수 있습니다.

4. 데이터 분석용 복잡한 쿼리 작성

데이터 분석가나 데이터 엔지니어가 작성하는 쿼리는 종종 수십 개의 CTE(Common Table Expressions), 윈도우 함수, 집계 함수가 중첩됩니다. 이런 쿼리를 처음부터 포맷팅된 형태로 작성하면 논리적 흐름을 유지하고 동료와의 협업이 훨씬 수월해집니다.

5. 면접 준비와 SQL 학습

SQL 면접 문제를 풀거나 학습할 때, 포맷팅된 예제 쿼리를 보면서 각 절의 역할과 실행 순서를 시각적으로 이해하기 훨씬 쉽습니다. 특히 복잡한 서브쿼리나 JOIN 로직을 공부할 때 포맷터가 큰 도움이 됩니다.

SQL 포맷팅 Best Practice - 협업 가독성을 높이는 작성 규칙

포맷터를 사용하는 것과 함께, 처음부터 좋은 SQL을 작성하는 규칙을 지키면 팀 전체의 생산성이 높아집니다. 다음은 많은 팀에서 채택하는 SQL 스타일 가이드입니다.

키워드 대소문자

스타일예시권장 여부
대문자 키워드SELECT id FROM users WHERE active = true✅ 권장 (가장 일반적)
소문자 키워드select id from users where active = true⚠️ 일부 팀에서 사용
혼용Select id From users Where active = true❌ 비권장

들여쓰기와 줄 맞춤

-- ❌ 가독성 낮음
SELECT id, name, email, created_at FROM users WHERE status = 'active' AND age > 18 ORDER BY created_at DESC;

-- ✅ 가독성 높음
SELECT
  id,
  name,
  email,
  created_at
FROM
  users
WHERE
  status = 'active'
  AND age > 18
ORDER BY
  created_at DESC;

별칭(Alias) 사용

-- ❌ 가독성 낮음
SELECT u.id, u.name, COUNT(o.id) FROM users u JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.name;

-- ✅ 가독성 높음
SELECT
  u.id,
  u.name,
  COUNT(o.id) AS order_count
FROM
  users AS u
  JOIN orders AS o ON u.id = o.user_id
GROUP BY
  u.id,
  u.name;

CTE로 복잡한 쿼리 분리

-- 서브쿼리 중첩 대신 CTE 활용
WITH active_users AS (
  SELECT id, name
  FROM users
  WHERE status = 'active'
    AND created_at >= '2026-01-01'
),
user_orders AS (
  SELECT
    user_id,
    COUNT(*) AS order_count,
    SUM(total_price) AS total_spent
  FROM orders
  WHERE status = 'completed'
  GROUP BY user_id
)
SELECT
  au.name,
  uo.order_count,
  uo.total_spent
FROM
  active_users AS au
  JOIN user_orders AS uo ON au.id = uo.user_id
ORDER BY
  uo.total_spent DESC;

CTE를 사용하면 복잡한 로직을 단계별로 분리해 각 단계의 의도를 명확히 표현할 수 있습니다. HMApps SQL 포맷터는 CTE 구조도 올바르게 정렬해 줍니다.

광고

SQL 성능 최적화를 위한 핵심 팁

포맷팅은 가독성을 높이지만, 진정한 SQL 실력은 성능까지 고려하는 데서 나옵니다. 포맷팅된 SQL을 보며 함께 점검해볼 성능 최적화 포인트를 정리했습니다.

💡 팁 1: SELECT * 피하기

-- ❌ 불필요한 컬럼까지 조회
SELECT * FROM users WHERE id = 1;

-- ✅ 필요한 컬럼만 명시
SELECT id, name, email FROM users WHERE id = 1;

SELECT *는 인덱스 커버링이 불가능하고, 불필요한 데이터 전송으로 성능이 낮아집니다. 컬럼을 명시하면 쿼리 의도도 명확해지는 이중 효과가 있습니다.

💡 팁 2: WHERE 절에서 함수 사용 주의

-- ❌ 인덱스를 타지 못함
SELECT * FROM orders WHERE YEAR(created_at) = 2026;

-- ✅ 범위 조건으로 인덱스 활용
SELECT * FROM orders
WHERE created_at >= '2026-01-01'
  AND created_at < '2027-01-01';

WHERE 절에서 컬럼에 함수를 적용하면 인덱스를 사용할 수 없어 풀 테이블 스캔이 발생합니다. 범위 조건으로 변환하면 인덱스를 효과적으로 활용할 수 있습니다.

💡 팁 3: N+1 쿼리 문제 해결

-- ❌ N+1 패턴 (사용자마다 별도 쿼리)
-- 1번: SELECT * FROM users LIMIT 100
-- N번: SELECT * FROM orders WHERE user_id = ?

-- ✅ JOIN으로 한 번에 조회
SELECT
  u.id,
  u.name,
  o.order_id,
  o.total_price
FROM
  users AS u
  LEFT JOIN orders AS o ON u.id = o.user_id
LIMIT 100;

💡 팁 4: EXISTS vs IN 선택

-- IN: 서브쿼리 결과가 작을 때 유리
SELECT name FROM users
WHERE id IN (
  SELECT user_id FROM orders WHERE status = 'completed'
);

-- EXISTS: 서브쿼리 결과가 크거나 NULL이 포함될 때 유리
SELECT name FROM users u
WHERE EXISTS (
  SELECT 1 FROM orders o
  WHERE o.user_id = u.id
    AND o.status = 'completed'
);

일반적으로 서브쿼리 결과 집합이 클수록 EXISTS가 유리합니다. EXISTS는 조건을 만족하는 행을 하나 찾으면 즉시 탐색을 중단하기 때문입니다.

💡 팁 5: EXPLAIN으로 실행 계획 확인

-- 쿼리 실행 전 실행 계획 확인
EXPLAIN SELECT
  u.id,
  u.name,
  COUNT(o.id) AS order_count
FROM
  users AS u
  JOIN orders AS o ON u.id = o.user_id
WHERE
  u.status = 'active'
GROUP BY
  u.id, u.name;

-- MySQL 상세 분석
EXPLAIN ANALYZE SELECT ...

EXPLAIN을 사용하면 인덱스가 활용되는지, 풀 스캔이 일어나는지, 어떤 순서로 테이블이 조인되는지 확인할 수 있습니다. SQL을 포맷팅한 뒤 EXPLAIN을 실행하는 것이 성능 최적화의 첫 단계입니다.

데이터베이스별 SQL 문법 차이와 주의사항

SQL은 ANSI 표준이 있지만, 각 데이터베이스마다 고유한 문법과 확장 기능이 있습니다. 포맷팅된 SQL을 다른 데이터베이스로 이전할 때 알아야 할 주요 차이점을 정리했습니다.

기능MySQLPostgreSQLSQLiteMS SQL Server
페이징LIMIT 10 OFFSET 20LIMIT 10 OFFSET 20LIMIT 10 OFFSET 20OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
문자열 연결CONCAT(a, b)a || ba || ba + b
현재 시간NOW()NOW()datetime('now')GETDATE()
자동 증가 키AUTO_INCREMENTSERIAL 또는 GENERATEDAUTOINCREMENTIDENTITY(1,1)
UpsertINSERT ... ON DUPLICATE KEY UPDATEINSERT ... ON CONFLICT DO UPDATEINSERT OR REPLACEMERGE

HMApps SQL 포맷터는 표준 SQL 문법을 기반으로 포맷팅하므로, 특정 데이터베이스의 전용 문법도 구조적으로 정렬해줍니다.

SQL 포맷터와 함께 사용하면 좋은 HMApps 도구들

SQL 포맷터 하나만으로도 개발 생산성이 크게 높아지지만, 함께 사용하면 시너지를 발휘하는 HMApps 도구들을 소개합니다.

  • JSON 포맷터: API 응답 데이터나 JSON 컬럼 값을 포맷팅할 때 사용합니다. SQL 쿼리 결과로 얻은 JSON 데이터를 분석할 때 특히 유용합니다.
  • 텍스트 비교 도구: SQL 마이그레이션 스크립트의 변경 전후를 비교하거나, 두 버전의 쿼리 차이를 시각적으로 확인할 때 활용합니다.
  • YAML ↔ JSON 변환기: 데이터베이스 설정 파일(Kubernetes ConfigMap, Helm values 등)을 변환할 때 사용합니다.
  • 코드 압축/정리 도구: 환경 변수나 설정값으로 SQL을 한 줄로 압축해야 할 때 활용합니다.

마무리: SQL 포맷터를 개발 워크플로에 통합하세요

SQL 포맷터는 단순한 "정리 도구"가 아닙니다. 복잡한 쿼리의 구조를 즉시 파악하고, 숨겨진 버그를 발견하고, 팀원과의 소통을 명확하게 만드는 개발 생산성의 핵심 도구입니다.

실제로 많은 시니어 개발자와 DBA들이 SQL을 작성하거나 검토할 때 항상 포맷팅된 형태를 먼저 확인하는 습관을 갖고 있습니다. 가독성 좋은 SQL은 버그를 줄이고, 성능 문제를 빠르게 찾아내고, 새로운 팀원이 기존 쿼리를 이해하는 시간을 단축합니다.

  • ✅ ORM이 생성한 복잡한 쿼리를 분석하고 싶을 때
  • ✅ 레거시 SQL 코드를 리팩터링하기 전에 구조를 파악하고 싶을 때
  • ✅ 코드 리뷰에서 SQL 변경 사항을 명확하게 검토하고 싶을 때
  • ✅ 팀 내 SQL 작성 스타일을 통일하고 싶을 때
  • ✅ 설치 없이 빠르게 쿼리를 정리하고 싶을 때

지금 바로 hmapps.kr/sql-formatter를 북마크해두고, 다음에 읽기 어려운 SQL을 마주쳤을 때 바로 포맷팅해 보세요. 데이터베이스 작업의 효율이 눈에 띄게 달라질 것입니다.

광고