콘텐츠로 이동

P7-1.1 프로젝트 질문과 입력 정의

Section ID: P7-1.1 Version: v2026.07.22

앞에서는 모델, 검색, 에이전트(agent), 운영까지 큰 구조를 보았습니다. 하지만 프로젝트 파트의 첫 출발은 더 직접적이어야 합니다. 표를 읽고, 질문을 세우고, 입력 단위를 정하는 일부터 다시 시작해야 합니다. 바로 그 첫 단계입니다. 목적은 모델을 쓰는 것이 아니라, 표에서 질문을 만들고 어떤 행을 한 건의 입력으로 볼지 정한 뒤 요약 결과를 프로젝트 기록으로 남기는 습관을 만드는 데 있습니다.

질문과 입력 단위

  • 데이터셋(dataset) 하나를 받았을 때 무엇부터 확인해야 하는가?
  • 데이터 분석 프로젝트는 어떤 질문 구조로 시작하면 좋은가?
  • 표를 요약하는 코드가 왜 프로젝트 문서의 출발점이 되는가?
  • 숫자를 계산한 뒤 무엇을 관찰과 해석으로 남겨야 하는가?

핵심은 질문 -> 표 확인 -> 요약 -> 관찰 기록으로 프로젝트 문서를 시작하는 기준을 세우는 데 있습니다. 여기서 먼저 고정해야 하는 것은 모델 선택이 아니라 무엇을 묻는가, 어떤 행을 한 건의 입력으로 볼 것인가입니다.

Part 7의 출발점에서는 모델보다 질문과 기록의 뼈대를 먼저 세웁니다. 표 확인과 요약 기록만으로도 프로젝트 문서가 시작될 수 있다는 기준을 잡습니다.

판단 기준

  • 데이터 분석 프로젝트를 질문 -> 표 확인 -> 요약 -> 관찰 기록 흐름으로 시작할 수 있습니다.
  • 데이터셋을 처음 받았을 때 바로 모델부터 만들지 않는 이유를 설명할 수 있습니다.
  • 실습 코드가 단지 계산이 아니라 프로젝트 기록의 근거라는 점을 이해할 수 있습니다.

왜 이 프로젝트부터 시작하나

종종 프로젝트를 시작할 때 바로 모델을 고르려 합니다. 하지만 실제 프로젝트에서는 그보다 먼저 다음 질문이 필요합니다.

  • 데이터는 몇 행인가?
  • 어떤 열(column)이 있는가?
  • 지금 확인하려는 질문은 무엇인가?
  • 평균(mean), 합(sum), 비율(ratio)만 봐도 드러나는 패턴이 있는가?

이 단계를 건너뛰면 뒤의 분류(classification)나 회귀(regression) 프로젝트도 흔들립니다. 그래서 Part 7의 첫 프로젝트는 일부러 모델 없는 프로젝트로 시작합니다.

프로젝트 입구에서 바로 흔들리기 쉬운 판단 기준을 먼저 표로 고정하면 다음과 같습니다.

질문 짧은 답
왜 모델부터 시작하지 않는가? 질문과 데이터 이해가 먼저이기 때문
이 프로젝트의 최소 산출물은 무엇인가? 요약값과 관찰 메모
그래서 무엇을 연습하는가? 프로젝트 문서의 시작 방식

Part 3에서 써 온 공통 기록 구조를 프로젝트 문서 형태로 처음 다시 받는 지점이기도 합니다.

여기서 바로 남길 것 Part 3에서 이어지는 공통 구조
요약값과 표 확인 결과 사실
눈에 띄는 패턴과 아직 확정하지 않을 설명 해석
다음에 더 볼 날짜, 원인, 비교 구간 다음 질문

프로젝트 질문 설정

프로젝트는 지난 7일 운영 기록에서 방문자(visitors), 가입(signups), 오류(errors)의 기본 흐름은 어떠한가?라는 질문에서 시작합니다. 입력 데이터가 많지 않아도 바로 다룰 수 있고, 평균과 비율만으로도 기본 패턴을 볼 수 있으며, 이후 어느 날이 이상한가, 전환율(conversion)이 왜 떨어졌는가 같은 다음 질문으로도 자연스럽게 이어집니다.

프로젝트 문서에는 이 질문을 그대로 첫 줄에 남기는 편이 좋습니다. Part 7에서는 코드보다 질문 문장이 먼저 보이는 구성이 더 중요합니다.

입력이 항상 일별 집계표일 필요는 없습니다. 어떤 프로젝트는 처음부터 여러 행으로 쌓인 원시 로그를 받기도 합니다. 그 경우에도 출발점은 크게 다르지 않습니다. 예를 들어 다음처럼 짧은 질문 한 줄로도 시작할 수 있습니다.

최근 동작 기록들이 평소 기준선과 비교해 어떤 차이를 보이는가?

이 질문을 받았을 때도 먼저 해야 할 일은 모델 선택이 아니라 입력 구조를 확인하는 것입니다.

동작 ID 경과 시간(초) 진행 비율 신호 A
A-01 0.0 0.00 0.8
A-01 1.0 0.20 1.4
A-01 2.0 0.40 1.9
B-02 0.0 0.00 0.7
B-02 1.0 0.25 1.3
B-02 2.0 0.50 1.5

이런 표에서는 한 행이 최종 결과가 아니라 동작 중 한 시점일 수 있습니다. 따라서 프로젝트 문서의 첫 단계는 무슨 모델을 쓸까보다 어떤 열이 식별자이고, 여러 행이 어떤 단위로 다시 묶여야 하는가를 적는 쪽에 더 가깝습니다.

프로젝트를 조금만 더 실제 분석 질문에 가깝게 옮기면, 다음처럼 최근 구간기준선을 비교하는 구조도 잡을 수 있습니다.

지표 최근 5개 평균 기준선 20개 평균 차이 해석
동작 단계 수 5.4 5.0 0.4 최근 구간이 더 길다
제어값 평균 0.48 0.44 0.04 최근 구간이 조금 높다
신호 A 최고값 29.6 28.2 1.4 최근 구간 최고값이 올라갔다
신호 B 평균 1.42 1.16 0.26 최근 구간 평균이 올라갔다

이 표는 프로젝트가 꼭 복잡한 모델에서 시작하지 않아도 된다는 점을 잘 보여 줍니다. 먼저 동작 단위 요약을 만들고, 그다음 최근 상태와 평소 기준선을 비교하는 표를 만들면, 사람은 무엇이 달라졌는지 훨씬 빠르게 읽을 수 있습니다. 다만 이 차이는 우선 변화 신호와 검토 우선순위를 보여 주는 것이지, 표 하나만으로 원인 설명까지 끝난 것은 아닙니다.

여기서 중요한 경계도 함께 적어 두는 편이 좋습니다.

  • 변화는 관찰되지만 원인은 아직 확정되지 않았습니다.
  • 경고는 검토 우선순위를 올리기 위한 신호입니다.
  • 적은 표본에서는 해석을 더 보수적으로 해야 합니다.

예를 들어 전체 전환율이 조금 내려간 표만 먼저 보면, 빠르게는 서비스 전체 가입 구조가 나빠졌다고 적고 싶어질 수 있습니다. 하지만 더 안전한 다음 판단은 그렇게 전체 결론부터 쓰는 것이 아니라, 한 행이 하루 전체인지 채널-일자인지, 하락이 모든 채널에 공통인지 특정 채널에 몰렸는지, 오류율 상승이 같이 붙는지를 먼저 나누는 것입니다. 그렇게 읽어야 전체 문제특정 입력 단위에서만 드러나는 문제를 섞지 않게 됩니다.

flowchart TD
  A["문제 장면<br/>전체 전환율이 조금 내려감"]
  B["빠른 판단<br/>서비스 전체가 나빠졌다"]
  C["입력 단위 확인<br/>하루 전체인가 채널-일자인가"]
  D["채널별 비교<br/>하락이 어디에 몰렸는가"]
  E["오류율 함께 확인<br/>같이 튄 신호가 있는가"]
  F["더 안전한 판단<br/>전체 문제인지 특정 채널 문제인지 구분"]

  A --> B
  A --> C --> D --> E --> F

즉 프로젝트의 첫 성공은 정답을 맞히는 모델이 아니라, 사람이 다음 질문을 세울 수 있는 비교표를 만드는 일일 수 있습니다.

프로젝트 흐름

flowchart TD
  A["질문 정리<br/>무엇을 알고 싶은가"]
  B["표 확인<br/>행과 열 구조 파악"]
  C["요약 계산<br/>평균, 최고값, 비율"]
  D["메모 정리<br/>관찰과 다음 질문"]

  A --> B --> C --> D

이 도식은 데이터 분석 프로젝트가 모델 선택으로 시작하지 않는다는 점을 보여 줍니다. 질문을 먼저 적고, 표를 확인하고, 요약값을 만든 뒤, 그 결과를 다시 관찰 메모로 남겨야 다음 분석 질문이 자연스럽게 이어집니다.

이 프로젝트의 핵심은 복잡한 계산이 아니라 질문과 요약을 연결하는 태도입니다.

프로젝트 기록으로 정리하면 순서는 다음과 같습니다.

단계 문서에 남길 것
질문 무엇을 알고 싶은가
표 확인 어떤 열과 기간을 보는가
요약 평균, 비율, 최고값
관찰 눈에 띄는 점과 다음 질문

동작 단위 원시 로그를 받는 프로젝트라면 이 흐름을 한 단계 더 세분화해 볼 수 있습니다.

단계 동작 단위 시계열 사례에서의 읽기
질문 최근 동작이 평소 기준선과 다른가
표 확인 한 행은 한 시점인가, 한 동작인가
요약 동작 1회 요약 표를 만들 수 있는가
비교 최근 구간과 기준선 차이를 표로 만들 수 있는가
관찰 경고가 필요한가, 더 봐야 할 구간은 무엇인가

이 표는 프로젝트 파트의 출발점을 더 현실적으로 바꿔 줍니다. 질문 -> 표 확인 -> 요약 -> 관찰 흐름은 그대로 유지되지만, 실제 데이터가 원시 시계열일 때는 비교 가능한 동작 단위최근 구간 비교가 중간에 추가됩니다. Part 7 입구에서도 핵심은 모델 선택이 아니라 무엇을 사실로 남겼고, 무엇은 아직 해석 단계에 두었고, 다음 질문을 어디에 붙였는가를 분리해 적는 데 있습니다. 경고가 붙더라도 그것은 사람이 다시 볼 대상을 좁히는 신호이므로, 즉시 결론보다 재검토 대상으로 먼저 남겨 두어야 합니다.

예제 데이터

최근 14일 유입 채널 운영 로그 발췌를 사용합니다. 핵심은 전체 일별 합계만 보면 약한 하락처럼 보이지만, 채널-일자(channel-day) 단위로 다시 묶으면 광고 유입만 크게 무너졌다는 점이 드러난다는 것입니다.

예제에서 한 행은 하루 전체가 아니라 특정 날짜의 특정 채널입니다. 즉, 이 절의 첫 실습 포인트는 숫자를 계산하는 일보다 먼저 한 행이 무엇을 뜻하는가를 분명히 잡는 데 있습니다.

아래는 본문에서 실제로 쓸 CSV의 일부 발췌입니다.

date channel visitors signups errors
2026-06-01 organic 520 64 1
2026-06-01 search 410 37 1
2026-06-01 ads 300 30 2
2026-06-08 organic 555 67 1
2026-06-08 search 428 38 1
2026-06-08 ads 360 25 6
2026-06-14 organic 572 69 1
2026-06-14 search 444 39 1
2026-06-14 ads 405 24 8

이 예제는 외부 로그를 그대로 복제한 것은 아니지만, 전체 합계는 크게 흔들리지 않는데 특정 유입 채널만 급격히 악화되는 운영 상황을 실제 프로젝트처럼 읽을 수 있도록 만든 자체 사례입니다.

Python 예제

예제는 14일 운영 로그를 읽고, 하루 전체채널-일자라는 두 단위 중 무엇을 프로젝트의 샘플로 잡아야 하는지 직접 확인하는 것입니다. 예제에서는 평균과 최대값만 뽑고 끝내지 않고, 기준선 7일최근 7일을 나눠 전체 요약과 채널별 비교를 함께 남기겠습니다.

이 기록 종류 지금 남기는 이유 기록이 주는 역할
전체 요약 서비스 전체가 정말 나빠졌는지 먼저 보기 위해 기준선 대비 전체 흐름을 확인하는 첫 비교 기준이 된다
채널별 비교표 어느 채널이 실제 변화의 원인인지 분해해 보기 위해 액션 우선순위를 채널별로 나눠 읽게 만든다
결과 해석 표 요약값, 관찰, 다음 질문을 본문 표로 분리해 읽기 위해 계산 결과와 해석 문장을 섞지 않게 만든다
  • 문제 상황: 최근 7일 동안 가입 전환율(conversion rate)이 떨어졌다는 제보가 들어왔다.
  • 입력: date, channel, visitors, signups, errors
  • 기대 출력:
  • 기준선 7일과 최근 7일의 전체 전환율 비교
  • 채널별 전환율 변화와 오류율 변화 비교
  • 어떤 단위에서 이상 신호가 실제로 드러나는지 설명하는 결과 해석 표
  • 확인할 개념:
  • 한 행이 무엇인가를 먼저 잡아야 비교 기준이 흔들리지 않는다
  • 전체 합계만 보면 놓치는 문제가 채널 단위 비교에서 드러날 수 있다
  • 데이터 분석 프로젝트의 첫 성공은 원인을 단정하는 것이 아니라 다음 검토 우선순위를 만드는 것이다

실습용 CSV를 코드 안에 직접 넣지 않고 p7-1-traffic-log.csv에 둡니다. Python 코드는 그 파일을 읽는 단계부터 시작합니다.

입력 파일

  • 파일 경로: p7-1-traffic-log.csv
  • 한 행의 의미: 특정 날짜의 특정 유입 채널
  • 핵심 열: date, channel, visitors, signups, errors

입력 파일의 앞부분만 짧게 다시 보면 다음과 같습니다.

date channel visitors signups errors
2026-06-01 organic 520 64 1
2026-06-01 search 410 37 1
2026-06-01 ads 300 30 2
2026-06-02 organic 540 66 1
2026-06-02 search 420 38 1
2026-06-02 ads 310 31 2

실행 기록 기준

  • CSV에서 한 행이 하루 전체인지 채널-일자인지 먼저 표시합니다.
  • 기준선 구간과 최근 구간을 나누고, 두 구간의 전체 전환율 차이를 계산합니다.
  • 채널별 비교표에서 전체 합계보다 더 크게 흔들리는 채널을 찾습니다.
  • 관찰한 값, 아직 단정하지 않을 해석, 다음 질문을 서로 다른 칸에 적습니다.
# 웹 트래픽 로그를 기준선 기간과 최근 기간으로 나눠 채널별 전환율과 오류율 변화를 비교하는 예제입니다.
import csv
from collections import defaultdict
from datetime import datetime
from pathlib import Path

data_path = Path("docs/assets/part-07/chapter-01/p7-1-traffic-log.csv")
rows = list(csv.DictReader(data_path.open(encoding="utf-8")))
for row in rows:
    row["date"] = datetime.strptime(row["date"], "%Y-%m-%d").date()
    row["visitors"] = int(row["visitors"])
    row["signups"] = int(row["signups"])
    row["errors"] = int(row["errors"])

# 조작 변수: 이 날짜를 바꾸면 기준선과 최근 구간의 경계가 달라집니다.
cutoff = datetime.strptime("2026-06-08", "%Y-%m-%d").date()
baseline_rows = [row for row in rows if row["date"] < cutoff]
recent_rows = [row for row in rows if row["date"] >= cutoff]

def summarize(group_rows):
    visitors = sum(row["visitors"] for row in group_rows)
    signups = sum(row["signups"] for row in group_rows)
    errors = sum(row["errors"] for row in group_rows)
    if visitors == 0:
        raise ValueError("비교 구간에 visitors가 없습니다. cutoff 날짜나 입력 파일을 확인하세요.")
    return {
        "visitors": visitors,
        "signups": signups,
        "conversion_rate": round(signups / visitors, 4),
        "error_rate": round(errors / visitors, 4),
    }

overall_baseline = summarize(baseline_rows)
overall_recent = summarize(recent_rows)

by_channel = defaultdict(lambda: {"baseline": [], "recent": []})
for row in rows:
    period = "recent" if row["date"] >= cutoff else "baseline"
    by_channel[row["channel"]][period].append(row)

channel_summary = []
for channel, grouped in by_channel.items():
    baseline = summarize(grouped["baseline"])
    recent = summarize(grouped["recent"])
    channel_summary.append({
        "channel": channel,
        "baseline_conversion": baseline["conversion_rate"],
        "recent_conversion": recent["conversion_rate"],
        "conversion_delta": round(recent["conversion_rate"] - baseline["conversion_rate"], 4),
        "baseline_error_rate": baseline["error_rate"],
        "recent_error_rate": recent["error_rate"],
        "error_delta": round(recent["error_rate"] - baseline["error_rate"], 4),
    })

channel_summary.sort(key=lambda row: row["conversion_delta"])

overall_delta = round(
    overall_recent["conversion_rate"] - overall_baseline["conversion_rate"], 4
)

print("전체 기준선 요약 =", overall_baseline)
print("전체 최근 요약 =", overall_recent)
print("전체 전환율 차이 =", overall_delta)
print("읽은 파일 =", str(data_path))
print("채널별 비교 =")
for row in channel_summary:
    print(row)

실행 결과 예시는 다음과 같습니다.

1
2
3
4
5
6
7
8
전체 기준선 요약 = {'visitors': 8950, 'signups': 941, 'conversion_rate': 0.1051, 'error_rate': 0.0034}
전체 최근 요약 = {'visitors': 9759, 'signups': 920, 'conversion_rate': 0.0943, 'error_rate': 0.0066}
전체 전환율 차이 = -0.0108
읽은 파일 = docs/assets/part-07/chapter-01/p7-1-traffic-log.csv
채널별 비교 =
{'channel': 'ads', 'baseline_conversion': 0.0978, 'recent_conversion': 0.0617, 'conversion_delta': -0.0361, 'baseline_error_rate': 0.0071, 'recent_error_rate': 0.0185, 'error_delta': 0.0114}
{'channel': 'organic', 'baseline_conversion': 0.1217, 'recent_conversion': 0.1207, 'conversion_delta': -0.001, 'baseline_error_rate': 0.0019, 'recent_error_rate': 0.0018, 'error_delta': -0.0001}
{'channel': 'search', 'baseline_conversion': 0.0894, 'recent_conversion': 0.0886, 'conversion_delta': -0.0008, 'baseline_error_rate': 0.0024, 'recent_error_rate': 0.0023, 'error_delta': -0.0001}

결과를 어떻게 읽는가

이 출력에서 먼저 봐야 할 것은 전체 합계채널별 비교가 서로 다른 이야기를 하고 있다는 점입니다.

비교 단위 기준선 7일 전환율 최근 7일 전환율 해석
전체 합계 10.51% 9.43% 전체로 보면 하락은 보이지만 원인은 아직 흐릿하다
ads 채널 9.78% 6.17% 하락폭이 가장 크고 오류율도 함께 올라간다
organic 채널 12.17% 12.07% 거의 유지된다
search 채널 8.94% 8.86% 거의 유지된다

이 표가 보여 주는 첫 번째 교훈은 한 행을 무엇으로 볼 것인가에 따라 프로젝트 결론이 달라진다는 점입니다.

  • 하루 전체를 샘플로 보면 전환율이 조금 내려갔다는 약한 결론만 남습니다.
  • 채널-일자를 샘플로 보면 ads 채널에서만 큰 이상이 생겼다는 훨씬 더 구체적인 결론이 나옵니다.

두 번째 교훈은 전환율 하락만 보는 것보다 오류율 변화를 같이 봐야 다음 질문이 더 선명해진다는 점입니다.

  • organic과 search는 전환율 변화가 거의 없습니다.
  • ads는 전환율이 크게 떨어졌고 오류율은 크게 올랐습니다.
  • 따라서 이 시점에서 가장 먼저 의심해야 할 것은 서비스 전체 메시지 문제보다 ads 유입 경로의 추적 스크립트, landing page, 특정 브라우저 문제 같은 더 좁은 운영 이슈입니다.

즉, 데이터 분석 프로젝트의 첫 성공은 원인을 단정했다가 아니라 다음 검토 우선순위를 더 좁혔다는 데 있습니다.

예제에서 확인해야 할 결과는 코드가 해석 문장까지 대신 쓰는가가 아닙니다. 코드 출력에서 전체 요약, 전환율 차이, 채널별 비교를 분리해 얻고, 그 위에 본문 표와 해석 문장을 사람이 다시 얹을 수 있는가가 더 중요합니다. 그래야 계산 결과와 판단 문장을 같은 프로젝트 기록 안에서 분리해 둘 수 있습니다.

결과 해석 기준

관찰 읽어야 할 뜻
전체 전환율은 10.51%에서 9.43%로 내려간다 전체 수준에서는 하락 신호가 있지만 원인은 아직 흐릿하다
ads 전환율 하락폭이 가장 크다 샘플 단위를 채널-일자로 잡아야 이상 신호가 선명해진다
ads 오류율도 함께 오른다 다음 질문은 단순 유입량보다 오류 유형과 landing page 쪽으로 좁혀진다
organic과 search는 거의 유지된다 서비스 전체 문제로 바로 단정하면 과한 해석이 된다

프로젝트 기록 예시

1
2
3
4
5
6
7
첫 질문:
한 행의 의미:
기준선 구간:
최근 구간:
가장 먼저 보인 사실:
아직 단정하지 않을 해석:
다음 질문:

직접 바꿔 보며 확인할 것

값을 조금만 바꿔도 어떤 비교 단위에서 이상 신호가 보이는가가 달라집니다. 처음 실행한 뒤에는 다음 두 가지만 직접 바꿔 보는 편이 좋습니다.

  1. cutoff 날짜를 2026-06-10이나 2026-06-12로 바꿔 봅니다. 관찰할 점: 기준선 7일과 최근 7일의 경계가 바뀌면 ads 채널 하락폭이 얼마나 달라지는가?

  2. CSV에서 ads 채널의 errors 값을 며칠만 낮춰 봅니다. 관찰할 점: 전환율 하락은 그대로인데 오류율 상승 신호가 약해지면, 다음 질문이 서비스 오류보다 유입 품질 변화 쪽으로 이동하는가?

즉, 핵심 확인 기준은 숫자를 맞게 계산했는가보다 비교 구간과 열 하나를 바꾸면 본문에서 정리할 해석과 다음 질문이 어떻게 달라지는가입니다.

실무에서의 의미

이런 비교는 실제 업무에서 매우 자주 등장합니다.

  • 서비스 운영 팀은 일별 오류와 가입 흐름을 먼저 봅니다.
  • 마케팅 팀은 유입 채널별 전환율을 먼저 봅니다.
  • 제품 팀은 특정 날짜의 변화를 보고 배포, 이벤트, 정책 변경과 연결해 봅니다.

이 수준의 분석을 빠르게 할 수 있어야 분류 모델이나 예측 모델을 붙일 때도 기준점(baseline)이 생깁니다. 무엇보다 전체가 나빠졌는가특정 세그먼트만 나빠졌는가를 구분하지 못하면, 이후 비교도 잘못된 샘플 단위 위에서 시작하게 됩니다.

즉, 이 프로젝트는 단순한 요약 실습이 아니라 샘플 단위 정의와 기준점(baseline) 문서 만들기이기도 합니다.

체크리스트

확인할 것 스스로 답할 질문
질문 이 프로젝트의 첫 질문을 한 문장으로 적었는가?
입력 단위 한 행이 무엇이고, 한 샘플을 어디까지로 볼지 구분했는가?
비교 단위 전체 합계와 채널-일자 비교가 서로 다른 결론을 만들 수 있음을 확인했는가?
기준점 요약값과 비교표를 다음 비교가 기대는 기준점(baseline)으로 남겼는가?
다음 질문 결과를 보고 추가로 확인할 열이나 구간을 최소 2개 이상 적었는가?

이 다섯 칸이 채워지면 질문과 입력 단위, 기준점, 다음 질문이 문서에 남습니다. 아직 모델을 만들지 않았더라도 프로젝트는 이미 다음 비교를 시작할 수 있는 상태입니다.

출처와 참고 자료