개발

기획자도 쉽게 배우는 SQL 기초

개발자들의 데이터 언어 배우기

2025년 5월 9일
#SQL

안녕하세요, IT 다이어리 독자 여러분! 🙋‍♀️

지난 시간에 데이터베이스의 기본 개념에 대해 알아봤는데요, 오늘은 기획자가 알아두면 진짜로 유용한 SQL 기초에 대해 알아볼게요. 처음 SQL을 배울 때 'JOIN', 'WHERE', 'GROUP BY' 이런 단어들이 어렵게 느껴질 수 있어요. 하지만 걱정마세요! 쉽게 설명해 드릴게요.

이 글을 읽고 나면 이런 것들을 할 수 있어요:

  • 개발자 도움 없이 간단한 데이터 조회하기
  • 직접 데이터를 분석해서 좋은 의견 내기
  • 회의 전에 필요한 데이터 미리 살펴보기

기획자, 왜 SQL을 알아야 할까요?

"개발자에게 데이터 달라고 하면 되는데, 왜 내가 배워야 하지?" 라고 생각할 수도 있어요. 하지만 이런 상황을 생각해보세요.

  • 기다림이 너무 길어요: "이 데이터 좀 줄 수 있어요?" → "지금 바빠서 다음 주에..." → "그럼 보고서 못 만들어요..."
  • 급한 상황: 발표 전날 밤에 갑자기 "내일 발표자료에 이번 달 가입자 데이터 넣어주세요"라는 요청이 왔을 때
  • 더 좋은 아이디어: 데이터를 직접 여러 방향으로 살펴보면서 새로운 아이디어를 찾을 수 있음

SQL을 배우면 이런 문제들을 해결할 수 있어요!

요즘은 IT 회사에서 기획자도 SQL을 할 줄 알면 더 강점이 있는 것 같아요. 채용 공고를 보면 'SQL 경험'이 있으면 유리하다고 많이 써 있기도 하구요!!

SQL이란 무엇인가요? 쉽게 설명해 드릴게요

SQL(Structured Query Language)은 데이터베이스와 대화하기 위한 언어예요. 쉽게 말해 "이런 데이터 보여줘"라고 컴퓨터에게 명령하는 방법이죠.

SQL의 주요 특징:

  • 비프로그래밍 언어: 일반 프로그래밍 언어보다 훨씬 배우기 쉬워요. 저도 학부생때 생각해보면 일주일 만에 기본 문법은 다 배웠어요! 정말 걱정 안하셔도 돼요!
  • 영어와 유사한 문법: SELECT, FROM, WHERE 등 영어 단어를 사용해 직관적이에요
  • 표준화된 언어: 대부분의 관계형 데이터베이스에서 비슷하게 사용돼요 (MySQL, PostgreSQL, Oracle 등 어디서든 비슷해요)
  • 선언적 언어: '무엇을' 원하는지만 명시하면 되고, '어떻게' 가져올지는 시스템이 알아서 처리해요

SQL은 크게 세 가지 유형으로 나눌 수 있어요:

  1. DDL(Data Definition Language): 데이터베이스 구조를 정의하는 명령어
    • CREATE: 테이블이나 데이터베이스 생성
    • ALTER: 테이블 구조 변경
    • DROP: 테이블이나 데이터베이스 삭제
  2. DML(Data Manipulation Language): 데이터를 조작하는 명령어
    • SELECT: 데이터 조회 (우리가 제일 많이 쓸 거예요!)
    • INSERT: 데이터 추가
    • UPDATE: 데이터 수정
    • DELETE: 데이터 삭제
  3. DCL(Data Control Language): 데이터 접근 권한을 제어하는 명령어
    • GRANT: 권한 부여
    • REVOKE: 권한 회수

기획자는 주로 DML, 그중에서도 SELECT 문을 가장 많이 사용하게 될 거예요. 아마 기획자가 이걸 사용한다면 거의 90% 이상이 SELECT 쿼리로 데이터 조회하는 걸거예요.

SQL을 연습할 수 있는 곳

SQL을 배우려면 연습할 곳이 필요해요. 몇 가지 방법을 알려드릴게요:

1. 회사 개발용 DB 사용하기:

실제 업무 데이터로 공부하는 제일 좋은 방법이에요.

  • 개발팀에 권한 요청하기: "SQL 공부하고 싶은데 개발DB 읽기 권한만 주세요~"
  • 읽기 전용 권한으로만 받는 게 좋아요. 실수로 데이터를 바꾸지 않게 절대!! 조심하기

처음 데이터베이스를 보면 많은 테이블이 있어요. 이게 바로 서비스의 모든 데이터예요! 😲

2. 온라인 SQL 연습 사이트 이용하기:

회사 DB를 쓸 수 없다면 이런 사이트를 써보세요:

처음 배울 때는 SQLBoltW3Schools SQL Tutorial 사이트가 좋아요. 한국어로도 볼 수 있어요!

3. 내 컴퓨터에 데이터베이스 설치하기:

  • MySQL, PostgreSQL 같은 프로그램 설치하기
  • 연습용 데이터 다운로드해서 써보기

처음에는 온라인 사이트로 시작하는 게 가장 쉬워요. 실제 데이터를 건드리지 않고 안전하게 연습할 수 있거든요.

SQL 기본 명령어 배우기 (제일 많이 쓰는 것만 골라봤어요!)

1. SELECT: 데이터 조회하기

가장 기본적인 명령어예요. 데이터를 볼 때 사용해요.

-- 기본 형태
SELECT 컬럼1, 컬럼2, ... FROM 테이블명;

-- 사용자 테이블에서 모든 정보 보기
SELECT * FROM users;

-- 사용자 테이블에서 이름과 이메일만 보기
SELECT name, email FROM users;

-- 결과에 별명(alias) 붙이기 (이거 진짜 유용해요!)
SELECT
    name AS 이름,
    email AS 이메일,
    join_date AS 가입일
FROM users;
  • “*“는 "모든 정보"를 의미해요. 하지만 실무에서는 필요한 정보만 골라서 보는 게 좋아요! 이유는:
    • 데이터가 더 빨리 보여요
    • 개인정보 같은 민감한 정보를 볼 필요가 없어요
    • 화면에 보기 좋게 정리돼요

2. WHERE: 조건으로 필터링하기

특정 조건에 맞는 데이터만 보고 싶을 때 사용해요.

-- 기본 형태
SELECT 컬럼1, 컬럼2, ... FROM 테이블명 WHERE 조건;

-- 서울에 사는 사용자만 보기
SELECT * FROM users WHERE location = '서울';

-- 2023년 이후 가입한 사용자만 보기
SELECT * FROM users WHERE join_date >= '2023-01-01';

-- 여러 조건 함께 쓰기 (AND, OR)
SELECT * FROM users
WHERE (location = '서울' OR location = '부산')
  AND join_date >= '2023-01-01';

많이 쓰는 비교 기호들:

  • = : 같다
  • != 또는 <> : 같지 않다
  • >, < : 크다, 작다
  • >=, <= : 크거나 같다, 작거나 같다
  • BETWEEN a AND b : a와 b 사이에 있다
  • IN (값1, 값2, ...) : 나열된 값 중 하나와 같다
  • LIKE '패턴' : 패턴과 일치 (%, _ 와일드카드 사용)
  • IS NULL, IS NOT NULL : NULL인지 아닌지 확인

패턴 매칭(LIKE)에서 많이 쓰는 와일드카드:

  • % : 아무 글자나 여러 개 (예: '김%'는 '김'으로 시작하는 모든 이름)
  • _ : 아무 글자나 딱 1개 (예: '김_'는 '김'으로 시작하는 두 글자 이름)
-- 이름이 '김'으로 시작하는 사용자 찾기
SELECT * FROM users WHERE name LIKE '김%';

-- 이메일이 gmail.com으로 끝나는 사용자 찾기
SELECT * FROM users WHERE email LIKE '%@gmail.com';

-- 전화번호의 중간 자리가 1234인 사용자 찾기
SELECT * FROM users WHERE phone LIKE '___-1234-____';

참고: 한국 데이터를 다룰 때는 LIKE가 정말 유용해요. 특히 이름이나 주소를 검색할 때 많이 써요!

3. ORDER BY: 결과 정렬하기

조회 결과를 특정 기준으로 순서대로 보고 싶을 때 사용해요.


-- 기본 형태
SELECT 컬럼1, 컬럼2, ... FROM 테이블명 ORDER BY 정렬기준컬럼 [ASC|DESC];

-- 사용자를 가입일 기준 최신순으로 정렬
SELECT * FROM users ORDER BY join_date DESC;

-- 이름 가나다순, 같은 이름이면 나이 내림차순으로 정렬
SELECT * FROM users ORDER BY name ASC, age DESC;
  • ASC: 오름차순 정렬 (기본값, 안 써도 돼요)
  • DESC: 내림차순 정렬 (최신순, 높은 순 등)

참고: 보고서나 분석할 때 정렬은 정말 중요해요. 특히 DESC(내림차순)는 "최근 가입자", "가장 많이 구매한 고객" 같은 중요한 정보를 위로 올려서 볼 때 꼭 필요해요!

4. LIMIT: 결과 개수 제한하기

결과 중 일부만 가져오고 싶을 때 사용해요. 특히 대량의 데이터를 다룰 때 유용해요.


-- 기본 형태
SELECT 컬럼1, 컬럼2, ... FROM 테이블명 LIMIT 개수;

-- 최근 가입한 사용자 10명만 조회
SELECT * FROM users ORDER BY join_date DESC LIMIT 10;

-- 11번째부터 20번째까지의 사용자 조회 (페이지네이션)
SELECT * FROM users ORDER BY join_date DESC LIMIT 10 OFFSET 10;

회사 유저 테이블은 100만 건이 넘는다고 생각해보세요. LIMIT 없이 전체 데이터 조회하면 DBeaver가 멈춰버리겠죠... 그래서 항상 LIMIT 100 정도는 붙여놓고 쿼리를 실행할거에요. 결과를 확인한 후에 LIMIT을 늘리거나 필요에 따라 제거할 수도 있을거구요!

참고: LIMIT 구문은 데이터베이스마다 조금씩 다를 수 있어요.

  • MySQL, PostgreSQL: LIMIT 10 OFFSET 10
  • Oracle: OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY
  • SQL Server: OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY

저는 MySQL을 쓰고 있어서 LIMIT 문법을 주로 사용해요!

5. GROUP BY & 집계 함수: 이걸 알면 진짜 분석이 시작돼요!

데이터를 그룹화하고 요약할 때 사용해요. 집계 함수와 함께 쓰면 강력한 분석이 가능해요.


-- 지역별 사용자 수 집계
SELECT
    location,
    COUNT(*) AS 사용자수
FROM users
GROUP BY location
ORDER BY 사용자수 DESC;

-- 연령대별, 성별 평균 구매금액
SELECT
    CASE
        WHEN age < 20 THEN '10대'
        WHEN age BETWEEN 20 AND 29 THEN '20대'
        WHEN age BETWEEN 30 AND 39 THEN '30대'
        ELSE '40대 이상'
    END AS 연령대,
    gender AS 성별,
    ROUND(AVG(amount), 0) AS 평균구매금액
FROM users u
JOIN orders o ON u.user_id = o.user_id
GROUP BY 연령대, 성별
ORDER BY 연령대, 성별;

주요 집계 함수:

  • COUNT(*): 행 개수 세기 (사용자 수, 주문 수 등)
  • SUM(): 합계 구하기 (총 매출, 총 방문 수 등)
  • AVG(): 평균 구하기 (평균 구매액, 평균 연령 등)
  • MAX(), MIN(): 최대/최소값 (최고 금액, 가장 오래된 가입일 등)

6. JOIN: 테이블 연결하기 (이걸 알면 SQL 중급자!)

여러 테이블을 연결해서 데이터를 함께 보고 싶을 때 사용해요. 관계형 DB의 꽃이라고 할 수 있어요!

기획자가 이것까지 직접 사용할 필요는 없어요! 그냥 이런게 있구나~ 정도만 알고 충분해요!

-- 기본 형태
SELECT a.컬럼1, b.컬럼2
FROM 테이블A a
JOIN 테이블B b ON a.공통컬럼 = b.공통컬럼;

-- 사용자와 그들의 주문 정보 함께 보기
SELECT
    u.name AS 이름,
    u.email AS 이메일,
    o.order_id AS 주문번호,
    o.amount AS 주문금액,
    o.order_date AS 주문일자
FROM
    users u
JOIN
    orders o ON u.user_id = o.user_id
WHERE
    o.order_date >= '2023-01-01'
ORDER BY
    o.order_date DESC;

JOIN 종류:

  • INNER JOIN (또는 그냥 JOIN): 양쪽 테이블에 모두 있는 데이터만 보여줌
  • LEFT JOIN: 왼쪽 테이블의 모든 데이터 + 오른쪽 테이블에서 매칭되는 데이터
  • RIGHT JOIN: 오른쪽 테이블의 모든 데이터 + 왼쪽 테이블에서 매칭되는 데이터
  • FULL JOIN: 양쪽 테이블의 모든 데이터 (MySQL에서는 지원 안 함)

참고: JOIN은 처음에는 이해하기 어려울 수 있어요. 그림으로 생각하면 더 쉬워요:

  • INNER JOIN: ⚪️ 두 원의 교집합
  • LEFT JOIN: ⚪️➡️ 왼쪽 원 전체 + 교집합
  • RIGHT JOIN: ⬅️⚪️ 오른쪽 원 전체 + 교집합
  • FULL JOIN: ⚪️⬅️➡️⚪️ 두 원의 합집합

실용적 팁: 많은 회사에서 LEFT JOIN을 많이 써요. 예를 들어 "모든 유저와 그들의 주문 정보"를 보고 싶을 때, 주문이 없는 유저도 포함해서 봐야 할 때가 많거든요. 이렇게 하면 주문하지 않은 고객을 찾아서 마케팅할 수 있어요!

7. HAVING: GROUP BY 결과 필터링하기

GROUP BY로 그룹화한 후에 조건을 적용하고 싶을 때 사용해요.

-- 10명 이상의 사용자가 있는 지역만 조회
SELECT
    location,
    COUNT(*) AS 사용자수
FROM
    users
GROUP BY
    location
HAVING
    COUNT(*) >= 10
ORDER BY
    사용자수 DESC;

WHERE vs HAVING 차이점:

  • WHERE: 그룹화하기 전에 행 필터링
  • HAVING: 그룹화한 후에 그룹 필터링

데이터 분석에 SQL을 쓴다면 어떤식으로 쓸까?

만약 데이터 분석에 SQL이 쓰인다면 어떻게 쓰이게 될까요?

(여기부터는 모든 SQL을 이해하지 못해도 괜찮아요! 그냥 사례 소개 정도로만 생각해주세요!)

1. 일별/주별/월별 추이 분석하기

-- 일별 신규 가입자 수
SELECT
    DATE(join_date) AS 날짜,
    COUNT(*) AS 신규가입자수
FROM users
WHERE join_date >= DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY)
GROUP BY 날짜
ORDER BY 날짜;

-- 주별 매출 추이
SELECT
    YEARWEEK(order_date) AS 연주차,
    CONCAT(
        YEAR(order_date), '년 ',
        WEEK(order_date), '주차'
    ) AS 주차표시,
    COUNT(*) AS 주문건수,
    SUM(amount) AS 총매출,
    ROUND(AVG(amount), 0) AS 평균주문금액
FROM orders
WHERE order_date >= DATE_SUB(CURRENT_DATE, INTERVAL 12 WEEK)
GROUP BY 연주차, 주차표시
ORDER BY 연주차;

2. 사용자 코호트 분석하기 (리텐션)


-- 월별 코호트 리텐션: 2023년 각 월별 가입자의 리텐션을 월별로 계산
SELECT
    DATE_FORMAT(u.join_date, '%Y-%m') AS 가입월,
    COUNT(DISTINCT u.user_id) AS 가입자수,
    SUM(CASE WHEN DATEDIFF(a.activity_date, u.join_date) BETWEEN 0 AND 30 THEN 1 ELSE 0 END) / COUNT(DISTINCT u.user_id) * 100 AS '1개월_리텐션(%)',
    SUM(CASE WHEN DATEDIFF(a.activity_date, u.join_date) BETWEEN 31 AND 60 THEN 1 ELSE 0 END) / COUNT(DISTINCT u.user_id) * 100 AS '2개월_리텐션(%)',
    SUM(CASE WHEN DATEDIFF(a.activity_date, u.join_date) BETWEEN 61 AND 90 THEN 1 ELSE 0 END) / COUNT(DISTINCT u.user_id) * 100 AS '3개월_리텐션(%)'
FROM
    users u
LEFT JOIN
    user_activities a ON u.user_id = a.user_id
WHERE
    u.join_date >= '2023-01-01' AND u.join_date < '2023-06-01'
GROUP BY
    가입월
ORDER BY
    가입월;

3. 퍼널 분석 (전환율)


sql
-- 회원가입부터 첫 구매까지의 퍼널
SELECT
    '회원가입' AS 단계,
    COUNT(DISTINCT user_id) AS 사용자수,
    100 AS 전환율
FROM
    users
WHERE
    join_date >= '2023-01-01'

UNION ALL

SELECT
    '장바구니추가' AS 단계,
    COUNT(DISTINCT user_id) AS 사용자수,
    ROUND(COUNT(DISTINCT user_id) * 100.0 / (
        SELECT COUNT(DISTINCT user_id) FROM users WHERE join_date >= '2023-01-01'
    ), 1) AS 전환율
FROM
    carts
WHERE
    created_at >= '2023-01-01'

UNION ALL

SELECT
    '구매완료' AS 단계,
    COUNT(DISTINCT user_id) AS 사용자수,
    ROUND(COUNT(DISTINCT user_id) * 100.0 / (
        SELECT COUNT(DISTINCT user_id) FROM users WHERE join_date >= '2023-01-01'
    ), 1) AS 전환율
FROM
    orders
WHERE
    order_date >= '2023-01-01';

활용 사례: 많은 서비스에서 무료 사용자를 유료로 전환하는 것이 주요 KPI입니다. 퍼널 분석을 통해 "무료→체험판→정기구독" 각 단계별 전환율을 파악하고, 가장 이탈이 많은 단계를 집중적으로 개선할 수 있습니다. 이런 데이터 기반 접근으로 전환율을 크게 높일 수 있어요! 💪

4. 세그먼트 분석 (사용자 그룹별 행동 분석)


sql
-- 연령대별 평균 주문 금액과 횟수
SELECT
    CASE
        WHEN age < 20 THEN '10대'
        WHEN age BETWEEN 20 AND 29 THEN '20대'
        WHEN age BETWEEN 30 AND 39 THEN '30대'
        WHEN age BETWEEN 40 AND 49 THEN '40대'
        ELSE '50대 이상'
    END AS 연령대,
    COUNT(DISTINCT u.user_id) AS 사용자수,
    COUNT(o.order_id) AS 총주문수,
    ROUND(COUNT(o.order_id) * 1.0 / COUNT(DISTINCT u.user_id), 1) AS 인당주문수,
    ROUND(AVG(o.amount), 0) AS 평균주문금액,
    ROUND(SUM(o.amount) * 1.0 / COUNT(DISTINCT u.user_id), 0) AS 인당평균결제금액
FROM
    users u
LEFT JOIN
    orders o ON u.user_id = o.user_id
GROUP BY
    연령대
ORDER BY
    MIN(age);

활용 인사이트: 세그먼트 분석을 통해 서비스의 주요 고객층과 그들의 행동 패턴을 발견할 수 있습니다. 예를 들어, 주 고객층이 30대 여성이지만 객단가는 40대가 더 높다는 인사이트를 얻을 수 있습니다. 이런 데이터를 바탕으로 연령대별 맞춤 마케팅 전략을 수립할 수 있어요.

SQL 학습을 위한 실용적인 팁

SQL을 효과적으로 배우기 위한 유용한 팁:

1. "복잡한 쿼리 = 작은 쿼리의 조합"이라고 접근하세요

처음부터 복잡한 쿼리를 작성하려고 하면 어렵게 느껴질 수 있어요. 다음과 같이 단계적으로 접근해보세요:

  1. 가장 기본이 되는 데이터를 조회하는 쿼리 먼저 작성
  2. WHERE 조건을 추가해서 필요한 데이터만 필터링
  3. GROUP BY로 집계하거나 JOIN으로 다른 테이블과 연결
  4. ORDER BY, LIMIT 등으로 결과 다듬기

이렇게 단계별로 접근하면 복잡한 분석도 체계적으로 수행할 수 있습니다!

2. 에러를 두려워하지 마세요 (특히 SELECT 쿼리는 안전해요!!)

SELECT 쿼리는 데이터를 조회만 하므로 서비스에 영향을 주지 않아요. 마음껏 실험해보세요!

자주 발생하는 에러들:

  • Column not found: 컬럼명 오타 체크!
  • Syntax error: 괄호나 따옴표 짝이 맞는지 확인
  • Unknown table: 테이블명 오타 또는 테이블 존재 여부 확인

3. 온라인 커뮤니티 활용하기

Stack Overflow, 데이터 분석 커뮤니티 등에서 다양한 예제와 해결책을 찾아볼 수 있습니다. SQL 관련 문제가 생기면 검색해보세요. 대부분의 문제는 이미 누군가 해결했을 거에요.

네이버 카페나 오픈채팅방도 좋아요!

SQL 사용 시 주의사항 및 모범 사례

1. 성능 고려하기

대용량 데이터를 다룰 때는 쿼리 성능이 중요합니다. 기본 원칙을 지켜주세요:

  • SELECT * 대신 필요한 컬럼만 명시하기
  • 불필요한 JOIN 피하기 (테이블 연결이 많을수록 쿼리가 느려집니다)
  • 인덱스가 걸린 컬럼으로 필터링하기 (WHERE절에서 활용)

대규모 데이터셋에 쿼리를 실행하기 전에 항상 LIMIT 절을 사용하여 소량의 데이터로 먼저 테스트해보세요. 이렇게 하면 쿼리 실행 시간이 너무 길어져 시스템이 응답하지 않는 상황을 방지할 수 있어요!

2. 민감한 정보 다룰 때 주의하기

개인정보가 담긴 데이터를 조회할 때는 특히 주의해야 합니다:

  • 필요한 경우에만 민감 정보 조회하기
  • 쿼리 결과를 안전하게 관리하기 (노션이나 구글 시트 같은 공유 문서에 민감한 데이터를 저장하지 않기)
  • 읽기 전용 권한으로만 접근하기

3. 데이터 신뢰성 검증하기

중요한 의사결정에 사용되는 데이터는 여러 방법으로 검증하는 것이 중요합니다. 이상한 결과가 나오면 쿼리 로직과 가정을 다시 검토하기!

중요 사례: 데이터 분석 시 항상 결과를 의심하는 자세가 필요합니다. 예상과 크게 다른 결과(예: 전월 대비 매출이 50% 이상 증가)가 나왔다면, 날짜 필터 조건이나 JOIN 로직을 다시 확인해보세요. 종종 쿼리 오류로 인해 데이터가 중복 계산되거나 일부 데이터가 누락되는 경우가 있습니다.

마무리하며

SQL은 기획자가 갖추면 정말 강력한 도구가 되는 스킬인데요. 처음에는 "SELECT"와 "FROM" 같은 기본 명령어만 알더라도, 꾸준히 학습하면 복잡한 분석 쿼리도 작성할 수 있게 되고, 기본 문법만 익혀도 도움이 될 수 있어요!

다음 편에서는 다른 주제로 찾아뵐게요! 오늘도 좋은 하루 되세요! 😊