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 포맷터는 직관적인 인터페이스로 누구나 쉽게 사용할 수 있습니다.
- SQL 붙여넣기: 입력창에 포맷팅할 SQL 쿼리를 붙여넣습니다.
- 포맷 버튼 클릭: [포맷] 버튼을 누르면 즉시 들여쓰기와 키워드 정렬이 적용된 SQL이 출력됩니다.
- 결과 확인: 정렬된 SQL을 확인하고 가독성이 개선된 구조를 한눈에 파악합니다.
- 복사: [복사] 버튼으로 포맷팅된 SQL을 클립보드에 저장합니다.
- 압축: 반대로 [압축] 기능을 사용하면 공백을 제거해 한 줄짜리 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" = completed2. 레거시 코드의 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 구조도 올바르게 정렬해 줍니다.