9 프로그래밍과 자동화
SQL 쿼리만으로는 해결할 수 없는 한계가 있다. 지금까지 우리는 “무엇을(What)” 분석할지에 집중했지만, 실제 업무에서는 “언제(When)”, “어떻게(How)”, “그 다음에는(Then)” 무엇을 할지가 더 중요하다. 752번 측정값에서 41.6이라는 이상치를 발견했을 때, 이것이 단순한 숫자가 아니라 즉시 조치가 필요한 경고 신호임을 누군가는 판단하고 대응해야 한다.
SQL은 데이터를 ’조회’하는 도구다. 하지만 조회한 결과로 무엇을 할 것인지는 사람이 결정해야 한다. 만약 매시간 수백 건의 새로운 측정값이 들어오고, 그중에서 이상치를 실시간으로 찾아 관련자에게 즉시 알려야 한다면? SQL 쿼리를 수동으로 실행하는 것으로는 한계가 있다. 이때 프로그래밍과 자동화가 필요하다.
752 미스터리를 해결한 후, 새로운 임무가 주어졌다고 상상해보자. 남극 탐사대가 실시간으로 측정값을 전송하고, 우리는 로리히의 41.6 같은 중요한 발견을 더 이상 우연에 맡기지 않는 자동화 시스템을 구축해야 한다.
9.1 SQL 한계와 프로그래밍 필요성
지금까지 우리는 SQL로 752번 측정값의 미스터리를 해결했다. 하지만 SQL만으로는 해결할 수 없는 상황들이 있다:
-- 이것은 할 수 있다: 현재 이상치 찾기
SELECT * FROM Survey WHERE reading > 40.0;
-- 하지만 이것들은 할 수 없다:
-- • 새로운 데이터가 추가될 때마다 자동으로 확인
-- • 이상치 발견 시 관련자에게 이메일 발송
-- • 사용자 입력에 따라 동적으로 쿼리 변경
-- • 여러 데이터베이스를 연결하여 통합 분석
SQL은 선언적 언어다. “무엇을” 원하는지 말하면 데이터베이스가 “어떻게” 가져올지 결정한다. 하지만 비즈니스 로직, 사용자 상호작용, 자동화된 의사결정은 절차적 프로그래밍 언어가 필요하다.
컴퓨터 과학에서 이 두 패러다임이 발전한 배경에는 서로 다른 문제 해결 접근법이 있다. 선언적 언어는 “무엇을 원하는가”에 집중하여 복잡한 구현 세부사항을 시스템에 맡김으로써 개발자의 인지적 부담을 줄이고자 했다. 반면 절차적 언어는 “어떻게 해결할 것인가”를 명시적으로 제어함으로써 복잡한 로직과 상호작용이 필요한 문제들을 해결하고자 했다. 752 미스터리 같은 데이터 분석에서도 이 두 접근법이 각각 다른 역할을 수행한다.
선언적 언어(SQL) - “무엇을(What)” 원하는가?
- 원하는 결과를 선언하면, 시스템이 최적의 방법을 찾아 실행
- 데이터베이스 엔진이 쿼리 최적화와 실행 계획을 자동으로 결정
- 예시:
SELECT * FROM Survey WHERE reading > 40.0
- “40 이상인 측정값을 보여줘” - 결과만 명시
- 장점: 간결하고 직관적, 성능 최적화는 시스템이 담당
- 한계: 과정 제어 불가, 시간적 흐름 관리 불가, 외부 시스템 연동 제한
절차적 언어(Python, R) - “어떻게(How)” 할 것인가?
- 목표를 달성하기 위한 단계별 절차를 명시적으로 기술
- 프로그래머가 실행 순서, 조건문, 반복문을 직접 제어
- 예시:
while True: check_data() → if anomaly: send_alert() → sleep(3600)
- “매시간 확인하고, 40 이상이면 이메일 보내고, 로그 남기고, 분석 시작해라” - 전체 과정 제어
- 장점: 완전한 제어, 복잡한 로직 구현, 시간 관리, 외부 시스템 연동
- 특징: 조건문, 반복문, 예외 처리, 상태 관리 가능
752 미스터리로 비교하면:
- SQL 방식: “염도가 40 이상인 데이터를 찾아라” (결과만 요구)
- 프로그래밍 방식: “매시간 염도를 확인하고, 40 이상이면 연구팀에 알리고, 과거 유사 사례를 찾고, 추가 센서 배치를 준비하라” (전체 워크플로우 제어)
이 두 패러다임의 결합이 바로 현대 데이터 자동화 시스템의 핵심이다. SQL의 강력한 데이터 처리 능력과 프로그래밍의 유연한 제어 능력이 만날 때, 752 같은 발견을 우연이 아닌 체계적 모니터링으로 바꿀 수 있다.
9.1.1 프로그래밍과 SQL 결합
여기서 진정한 변화가 시작된다. SQL만으로는 752 미스터리 같은 일회성 분석은 가능하지만, 매일 수백 건의 새로운 데이터가 들어오고 이를 체계적으로 모니터링해야 하는 현실적인 업무에는 한계가 있다. 프로그래밍 언어와 SQL을 결합하면 데이터베이스의 강력한 쿼리 능력과 프로그래밍 언어의 유연한 로직 처리 능력을 동시에 활용할 수 있다. 이는 단순히 두 기술을 섞어 쓰는 것이 아니라, 각각의 장점을 극대화하면서 상호 보완하는 시너지 효과를 만들어낸다.
프로그래밍 언어는 SQL이 할 수 없는 영역들을 담당한다. 조건부 로직, 반복 처리, 외부 시스템과의 연동, 사용자 인터페이스, 무엇보다 의사결정이 그것이다. 752번 측정값에서 41.6이라는 수치를 발견했을 때, “이것이 중요한 이상값인가?”를 판단하고 “그렇다면 누구에게 알려야 하는가?”를 결정하는 것은 프로그래밍 로직의 영역이다. SQL은 데이터를 찾아주지만, 그 데이터로 무엇을 할지는 작성한 코드가 결정한다.
Python과 SQLite의 연결은 놀랍도록 간단하면서도 강력하다. 몇 줄의 코드만으로 데이터베이스와 연결하고, SQL의 모든 기능을 사용할 수 있다:
import sqlite3
# 데이터베이스 연결 설정
= sqlite3.connect("data/survey.db")
connection = connection.cursor()
cursor
# SQL 쿼리 실행
= "SELECT * FROM Survey WHERE reading > ?"
query 40.0,))
cursor.execute(query, (= cursor.fetchall()
results
# 연결 정리
cursor.close() connection.close()
752 미스터리를 해결하는 과정에서 중요한 데이터를 다루고 있기 때문에, 보안에 특별한 주의를 기울여야 한다. SQL 주입 공격은 웹 애플리케이션에서 가장 흔하고 위험한 보안 취약점 중 하나로, 악의적인 사용자가 데이터베이스의 내용을 조작하거나 삭제할 수 있게 만든다. 실제로 수많은 기업들이 SQL 주입 공격으로 인해 고객 데이터가 유출되거나 시스템이 마비되는 피해를 겪었다.
# 위험한 방법 - 절대 하지 말 것!
def get_readings_unsafe(person_id):
= f"SELECT * FROM Survey WHERE person = '{person_id}'"
query
cursor.execute(query)
# 만약 person_id가 "dyer'; DROP TABLE Survey; --"라면?
# 실행되는 쿼리: SELECT * FROM Survey WHERE person = 'dyer'; DROP TABLE Survey; --'
위의 코드는 사용자 입력을 직접 SQL 문자열에 삽입하기 때문에 매우 위험하다. 악의적인 입력이 들어올 경우 우리의 소중한 752번 조사 데이터가 모두 삭제될 수 있다. 다행히 해결책은 간단하다 - 준비된 문장(Prepared Statement)을 사용하는 것이다:
# 안전한 방법 - 준비된 문장(Prepared Statement) 사용
def get_readings_safe(person_id):
= "SELECT * FROM Survey WHERE person = ?"
query
cursor.execute(query, (person_id,))return cursor.fetchall()
물음표(?
)를 사용하여 매개변수를 표시하고, execute()
함수의 두 번째 인수로 실제 값을 전달한다. 이렇게 하면 데이터베이스 엔진이 SQL 코드와 데이터를 명확히 구분하여 처리하므로, 악의적인 SQL 코드가 실행될 가능성을 원천 차단한다.
9.1.2 반복 작업 자동화
SQL의 근본적인 한계가 여기서 분명해진다. 아무리 복잡하고 정교한 쿼리를 작성해도, SQL은 수동으로 실행해야만 결과를 얻을 수 있다. 752번 측정값의 이상치를 찾는 완벽한 쿼리를 만들었다고 해도, 매시간 누군가가 그 쿼리를 실행해야 한다. 하지만 프로그래밍 언어는 다르다. 한 번 작성한 코드가 스스로 계속 실행되면서, 시간을 관리하고, 조건을 판단하고, 상황에 따라 다른 행동을 취할 수 있다.
프로그래밍 언어의 제어 구조가 바로 이런 차이를 만든다. while True:
루프는 프로그램이 영원히 반복되게 하고, time.sleep(3600)
은 정확히 1시간씩 기다리게 하며, if
조건문은 상황에 따라 다른 로직을 실행하게 한다. SQL에는 이런 시간적 제어나 조건부 실행 개념이 없다. SQL은 “지금 이 순간” 데이터를 조회하는 도구이지, “언제, 어떤 조건에서, 무엇을 할 것인가”를 제어하는 도구가 아니다.
더 중요한 것은 프로그래밍이 가능하게 하는 외부 시스템 연동이다. SQL 쿼리 결과로 이상치를 발견했다고 해서 자동으로 이메일이 발송되지는 않는다. 하지만 Python이나 R 코드는 쿼리 결과를 받아서 즉시 이메일을 보내고, Slack에 알림을 전송하고, 다른 데이터베이스에 기록을 남기고, 심지어 다른 분석 프로그램을 자동으로 시작시킬 수도 있다. 이것이 단순한 데이터 조회와 완전한 업무 자동화의 차이다.
time.sleep(3600)
코드 한줄로 매시간 새로운 데이터를 확인하고 이상치를 탐지하는 모니터링 시스템이 구현된다.
import time
import smtplib
from datetime import datetime
def monitor_antarctic_data():
"""752 미스터리 기반 실시간 모니터링"""
while True:
# 1. 새로운 측정값 확인
= """
query SELECT * FROM Survey
WHERE reading > 40.0
AND timestamp > datetime('now', '-1 hour')
"""
cursor.execute(query)= cursor.fetchall()
anomalies
# 2. 이상치 발견 시 알림
for anomaly in anomalies:
if anomaly[3] > 41.0: # 로리히 수준
f"Critical anomaly detected: {anomaly}")
send_alert(
# 3. 1시간 대기
3600)
time.sleep(
def send_alert(message):
"""이메일 알림 발송"""
print(f"ALERT: {message}")
# 실제로는 이메일이나 Slack 등으로 알림
9.1.3 완전 자동화 시스템
이제 단순한 반복 실행을 넘어 지능형 통합 시스템의 영역에 들어선다. 앞서 살펴본 모니터링 시스템이 “이상치를 발견하면 알림을 보낸다”는 단순한 반응이었다면, 완전 자동화 시스템은 다단계 연쇄 반응을 수행한다. 하나의 이벤트가 발생하면 즉시 여러 가지 관련 작업들이 자동으로 시작되고, 각각의 결과가 다시 다른 작업들을 트리거한다. 마치 도미노처럼, 첫 번째 이상치 발견이 전체 연구 생태계를 움직이게 하는 것이다.
완전 자동화 시스템의 핵심은 예측적 지능이다. 단순히 “41.6이 발견되었다”고 알리는 것이 아니라, “41.6과 유사한 과거 3건의 사례에서는 모두 지질학적 변화가 뒤따랐으니, 즉시 지질 전문가팀에 알리고 추가 센서 배치를 준비하며, 위성 이미지 분석을 자동으로 시작한다”는 식으로 작동한다. 이는 752 미스터리에서 얻은 교훈을 단순히 기억하는 것을 넘어서, 그 교훈을 바탕으로 능동적으로 다음 단계를 예측하고 준비하는 것이다.
def intelligent_research_system(new_data):
"""752 교훈을 바탕으로 한 예측적 자동 대응 시스템"""
# 1. 즉시 저장과 동시에 패턴 분석 시작
save_to_database(new_data)= analyze_realtime_patterns(new_data)
patterns
# 2. 다단계 지능형 대응
if is_significant_anomaly(new_data):
# 즉시 실행
alert_response_team(new_data, patterns)
# 자동 연구 네트워크 가동
= find_historical_parallels(new_data)
similar_cases = assemble_expert_team(new_data, similar_cases)
expert_team
# 예측적 준비 작업
prepare_additional_sensors(new_data.location)
schedule_satellite_analysis(new_data.timestamp)
initiate_predictive_modeling(patterns)
# 3. 시스템 전체의 지속적 학습
update_detection_algorithms(new_data, patterns)
# 단일 이벤트가 연구 생태계 전체를 자동 가동
이런 시스템이 만들어내는 변화는 과학 연구의 본질적 전환이다. 과거에는 중요한 발견이 있어도 그것이 더 큰 연구로 이어지기까지 수개월이 걸렸다. 논문 발표, 동료 검토, 후속 연구 계획 수립, 예산 확보 등의 긴 과정을 거쳐야 했다. 하지만 완전 자동화 시스템은 발견과 동시에 관련된 모든 후속 작업을 즉시 시작한다. 752번 지점에서 새로운 이상치가 발견되는 순간, 전 세계 관련 연구자들이 알림을 받고, 유사 사례가 자동으로 정리되며, 추가 분석에 필요한 자원들이 예약되고, 예측 모델이 돌아가기 시작한다. 발견에서 후속 연구까지의 시간이 수개월에서 수시간으로 단축되는 것이다.
Python과 마찬가지로 R도 SQL과 프로그래밍 로직을 효과적으로 결합할 수 있다. R의 데이터 분석 생태계는 특히 통계적 분석과 시각화에 강점을 가지고 있어, 데이터베이스에서 추출한 데이터를 즉시 분석하고 그래프로 표현하는 워크플로우가 자연스럽다. 752 미스터리 같은 이상치 탐지와 분석에서 R의 통계 함수들과 시각화 라이브러리들이 특히 유용하다.
library(RSQLite)
library(DBI)
# 안전한 데이터베이스 연결과 쿼리
<- function(person_id) {
safe_query <- dbConnect(SQLite(), "data/survey.db")
conn
# 준비된 문장으로 SQL 주입 방지
<- "SELECT personal || ' ' || family as name FROM Person WHERE id = ?"
query <- dbGetPreparedQuery(conn, query, data.frame(person_id))
result
dbDisconnect(conn)
return(result)
}
# 함수 사용
<- safe_query("dyer")
name print(paste("연구자 이름:", name$name))
# [1] "연구자 이름: William Dyer"
R의 데이터베이스 인터페이스는 데이터 과학자들이 자주 수행하는 작업들을 단순화하는 도우미 함수들을 풍부하게 제공한다. 전체 테이블을 데이터프레임으로 읽어오거나, R에서 처리한 결과를 다시 데이터베이스에 저장하는 작업이 몇 줄의 코드로 가능하다. 이는 탐색적 데이터 분석(EDA)에서 매우 유용하며, 752번 측정값 같은 이상치를 발견했을 때 즉시 관련된 모든 데이터를 불러와 상세 분석을 수행할 수 있게 해준다.
<- dbConnect(SQLite(), "data/survey.db")
conn
# 데이터베이스 구조 탐색
<- dbListTables(conn)
all_tables <- dbListFields(conn, "Survey")
survey_columns
# 전체 데이터를 R 환경으로 가져와서 분석
<- dbReadTable(conn, "Survey")
survey_df <- survey_df[survey_df$reading > 40.0, ]
anomalies
# 분석 결과를 새로운 테이블로 저장
dbWriteTable(conn, "anomaly_analysis", anomalies, row.names = FALSE)
dbDisconnect(conn)
9.2 SQL 자동화 프로그래밍 인프라
SQL 쿼리는 강력하지만 스스로 실행되지 않는다. 752번 측정값에서 이상치를 찾는 완벽한 쿼리를 작성했다 해도, 누군가 혹은 무언가가 그 쿼리를 실행해야 한다. 더 중요한 것은 쿼리 실행 중 데이터베이스 연결이 끊어지거나, 결과를 다른 시스템과 공유해야 할 때 SQL만으로는 대응할 수 없다는 점이다.
여기서 프로그래밍 인프라가 SQL의 든든한 지원군이 된다. 정해진 시간에 SQL 쿼리를 자동 실행하고, 데이터베이스 연결 문제를 자동으로 해결하며, SQL 쿼리 결과를 전 세계와 실시간으로 공유하는 시스템. 이것이 바로 752 미스터리를 우연한 발견에서 체계적 모니터링으로 전환시키는 핵심 인프라다.
9.2.1 SQL 쿼리 실행 스케줄링
SQL의 가장 큰 아이러니는 강력한 쿼리 언어이면서도 스스로는 아무것도 할 수 없다는 점이다. 아무리 정교한 SELECT * FROM Survey WHERE reading > 40.0
쿼리를 작성해도, 누군가 “실행” 버튼을 눌러야만 작동한다. 1930년대 로리히가 41.6이라는 중요한 값을 우연히 발견할 수 있었던 것은 그가 그날 데이터를 확인했기 때문이다. 하지만 만약 그가 그날 아팠거나, 다른 업무에 바빠서 데이터를 보지 않았다면? 과학사에서 가장 중요한 발견 중 하나를 놓쳤을지도 모른다.
시간 기반 패턴은 과학 데이터에서 극히 중요하다. 752번 지점의 이상치가 특정 시간대에 집중되거나, 계절적 변화를 보이거나, 다른 지역의 패턴과 연관될 수 있다. 하지만 이런 시간적 패턴을 발견하려면 일정한 간격으로 지속적으로 데이터를 확인해야 한다. 매시간, 매일, 매주 같은 규칙적인 모니터링 없이는 중요한 시간적 연관성을 놓칠 수밖에 없다.
프로그래밍 스케줄링이 SQL에 부여하는 것은 시간 의식이다. SQL 쿼리에게 “언제 실행될지”를 알려주고, 그 약속을 지키게 하는 것이다. 이는 752 미스터리 같은 우연한 발견을 체계적이고 예측 가능한 모니터링으로 전환하는 첫 번째 단계다:
import schedule
import sqlite3
def daily_pattern_analysis():
"""매일 시간별 패턴 분석"""
= sqlite3.connect("data/survey.db")
conn = conn.cursor()
cursor
"""
cursor.execute( SELECT COUNT(*) as readings, AVG(reading) as avg_reading
FROM Survey
WHERE date(timestamp) = date('now', '-1 day')
""")
= cursor.fetchone()
result print(f"📊 어제: {result[0]}건, 평균 {result[1]:.2f}")
conn.close()
# SQL이 시간을 인식하게 만드는 스케줄링 - 하루도 빼먹지 않는 꾸준함
"09:00").do(daily_pattern_analysis)
schedule.every().day.at(
while True:
schedule.run_pending()60) time.sleep(
9.2.2 SQL 연결 오류와 자동 복구
데이터베이스는 우리가 생각하는 것보다 훨씬 자주 연결이 끊어진다. 네트워크 지연, 서버 재시작, 동시 접속 한도 초과, 심지어는 단순한 타임아웃까지 - 수많은 이유로 SQL 쿼리가 실패할 수 있다. 752번 측정값의 중요한 이상치를 확인하던 중 “데이터베이스에 연결할 수 없습니다”라는 오류가 뜬다면? 그 순간 놓친 데이터는 되돌릴 수 없다.
과학 데이터의 특성상 연속성이 극히 중요하다. 752번 지점의 염도 변화가 시간에 따라 어떻게 변하는지, 다른 측정값과 어떤 상관관계가 있는지 파악하려면 중간에 빠진 데이터 포인트가 없어야 한다. 한 번의 연결 실패로 중요한 패턴을 놓칠 수 있고, 이는 잘못된 과학적 결론으로 이어질 수 있다.
강건한 SQL 시스템의 핵심은 끈질김이다. 한 번 실패했다고 포기하지 않고, 여러 번 재시도하고, 주 데이터베이스가 실패하면 백업으로 전환하고, 그래도 안 되면 다른 대안을 찾는다. 이는 752 미스터리 같은 중요한 발견을 절대 놓치지 않겠다는 과학자의 끈질김을 코드로 구현한 것이다:
import time
from sqlite3 import OperationalError
def safe_sql_query(query, max_retries=3):
"""SQL 쿼리 실패 시 자동 재시도"""
for attempt in range(max_retries):
try:
= sqlite3.connect("data/survey.db", timeout=30)
conn = conn.cursor()
cursor
cursor.execute(query)= cursor.fetchall()
results
conn.close()return results
except OperationalError as e:
print(f"SQL 연결 실패 (시도 {attempt + 1}/{max_retries})")
if attempt < max_retries - 1:
5 * (attempt + 1)) # 점진적 대기
time.sleep(else:
# 백업 데이터베이스로 전환
return query_backup_database(query)
def query_backup_database(query):
"""주 데이터베이스 실패 시 백업 사용"""
try:
= sqlite3.connect("backup/survey_backup.db")
backup_conn = backup_conn.cursor()
cursor
cursor.execute(query)= cursor.fetchall()
results
backup_conn.close()print("📂 백업 데이터베이스 사용")
return results
except Exception:
print("⚠️ 모든 데이터베이스 연결 실패")
return []
# 끈질긴 752 모니터링
def resilient_monitoring():
= "SELECT * FROM Survey WHERE reading > 40.0"
query = safe_sql_query(query)
results
if results:
print(f"✅ 발견: {len(results)}건의 이상치")
else:
print("📊 이상치 없음 (또는 연결 실패)")
9.2.3 SQL 쿼리 결과 글로벌 공유
과학의 역사를 돌아보면, 가장 중요한 발견들은 고립된 환경에서 이루어진 것이 아니라 전 세계 연구자들의 협업을 통해 확인되고 발전되었다. 1930년대 로리히의 41.6 발견이 중요한 이유도, 그것이 단순히 하나의 측정값이 아니라 다른 지역, 다른 시점의 데이터와 비교될 때 진정한 의미가 드러났기 때문이다. 하지만 당시에는 이런 비교가 수개월, 심지어 수년이 걸렸다.
현대 과학에서 SQL 쿼리 결과를 혼자만 보관하는 것은 마치 중요한 발견을 서랍에 넣어두는 것과 같다. 752번 지점에서 발견한 이상치가 실제로 지구 전체의 기후 변화를 나타내는 신호인지, 아니면 단순히 지역적 변화인지는 전 세계 데이터와 비교해야만 알 수 있다. API를 통한 실시간 데이터 공유는 이런 글로벌 협업을 즉시 가능하게 한다.
네트워크 효과가 과학 발견에 미치는 영향은 기하급수적이다. 하나의 연구소에서 발견한 SQL 패턴이 전 세계 10개, 100개의 다른 데이터베이스와 즉시 비교될 때, 우리는 개별 연구로는 절대 발견할 수 없는 거대한 패턴을 볼 수 있다. 이는 752 미스터리 같은 우연한 발견을 체계적인 글로벌 과학으로 승화시키는 마지막 단계다:
import requests
import sqlite3
def share_sql_findings():
"""SQL 결과를 글로벌 연구 네트워크에 공유"""
= sqlite3.connect("data/survey.db")
conn = conn.cursor()
cursor
"SELECT * FROM Survey WHERE reading > 40.0")
cursor.execute(= cursor.fetchall()
anomalies
conn.close()
# 전 세계 연구 네트워크에 즉시 공유
for anomaly in anomalies:
= {"site": anomaly[0], "reading": anomaly[2]}
data "https://global-research.org/api/share", json=data)
requests.post(print(f"📡 {anomaly[0]} 이상치를 전 세계와 공유")
이 세 가지 인프라가 결합되면, SQL은 단순한 쿼리 도구를 넘어 글로벌 연구 네트워크의 핵심이 된다. 매시간 자동으로 실행되고, 오류에도 멈추지 않으며, 발견 즉시 전 세계와 공유되는 시스템. 이것이 바로 SQL과 프로그래밍의 진정한 시너지이며, 752 미스터리 같은 우연한 발견을 체계적인 과학 시스템으로 전환시키는 핵심 메커니즘이다.
💭 생각해볼 점
SQL 쿼리에서 시작해서 완전 자동화 시스템까지 - 이 여정은 단순한 기술적 진화가 아니라 우리가 데이터와 상호작용하는 방식의 근본적 변화를 보여준다. 1930년대 로리히가 손으로 기록한 41.6이라는 숫자가 2024년에는 실시간 글로벌 모니터링 시스템의 트리거가 될 수 있다는 것, 그 변화의 규모를 상상해보라.
이제 우리는 SQL의 한계를 명확히 알고, 프로그래밍과의 결합이 어떻게 그 한계를 뛰어넘는지 이해했다. 다음 장에서는 한 걸음 더 나아가 자연어로 “752 지점의 염도가 왜 높은지 알려줘”라고 질문하면 AI가 자동으로 SQL을 생성하고 분석 결과를 제공하는 Text2SQL의 혁신적 세계를 탐험할 것이다.