
AI가 작성한 SQL, 그대로 운영 환경에서 실행해도 괜찮을까요? — 「동작함」을 졸업하여, EXPLAIN으로 측정하고 영향 범위를 파악한 뒤
요약
AI가 생성한 SQL의 구문적 정확성과 운영 환경에서의 안전성 사이의 간극을 다룹니다. AI는 데이터베이스의 인덱스나 제약 조건을 알지 못하므로, 실행 계획(EXPLAIN)을 통해 성능과 영향 범위를 반드시 검증해야 함을 강조합니다.
핵심 포인트
- AI 생성 SQL은 구문이 맞아도 운영 환경에서 위험할 수 있음
- Text-to-SQL 벤치마크 성능이 실제 운영 스키마의 정확도를 보장하지 않음
- 실행 계획(EXPLAIN)을 통해 인덱스 사용 여부와 성능을 반드시 확인해야 함
- 동작함, 빠름, 안전함의 3가지 축을 기준으로 SQL 검증 프로세스 필요
AI에게 SQL을 작성하게 하는 것, 정말 편리하죠.
"사용자별 이번 달 매출을 뽑아줘"라고 부탁하면, 몇 초 만에 JOIN도 GROUP BY도 포함된, 그럴싸한 SQL이 돌아옵니다. 실제로 로컬에서 실행해 보니 숫자도 제대로 나옵니다. "오, 되는데?"라고 생각하며 그대로 운영(Production) 환경에 던집니다.
여기서 잠시 멈춰 주셨으면 합니다.
그 SQL, 운영 데이터베이스에서 어떤 일이 일어날지 설명할 수 있나요?
어떤 테이블을, 어떤 순서로, 얼마나 읽을 것인가. 인덱스(Index)를 사용하는가, 아니면 전체 행을 위에서 아래로 훑는가(Full Scan). 실행 중 다른 사람의 처리를 몇 초 동안 멈추게 하는가. 만약 UPDATE라면 몇 행에 영향을 주는가.
솔직히 말하면, 저도 처음에는 이 부분이 모호했습니다. "동작하니까 OK"라며 배포했었죠. 하지만 AI가 작성하는 SQL은 구문(Syntax)이 올바른 것과, 운영 환경에서 안전하게 동작하는 것이 완전히 별개의 문제입니다.
실제로 2025년 7월에는, AI 코딩 에이전트가 코드 프리즈(Code Freeze) 기간 중에 파괴적인 명령을 실행하여 운영 데이터베이스를 통째로 망가뜨린 사례가 보고되었습니다 (심지어 그 후 "하지 않았다"며 둘러대려 했다는 덤까지 붙어서 말이죠). 극단적인 예로 보일 수도 있겠지만, 이는 현실과 맞닿아 있는 이야기입니다. "동작하는 SQL을 쓸 줄 아는 것"과 "운영 환경에 배포해도 되는 SQL인지 판단할 수 있는 것" 사이에는 생각보다 깊은 골이 있습니다.
이 기사에서는 그 골을 메우고자 합니다. AI에게 SQL을 맡길 때, 인간이 무엇을 설계하고, 무엇을 판단하며, 무엇을 AI에게 맡길 것인가. 이를 「동작함」, 「빠름」, 「안전함」의 3가지 축으로 나누어, 내일부터 업무에서 바로 사용할 수 있는 수준까지 구체화해 나가겠습니다.
전문 용어도 나올 때마다 풀어서 설명할 것이므로, "인덱스나 실행 계획(Execution Plan) 같은 건 대충밖에 모른다"는 분들도 뒤처지지 않을 것입니다. 천천히 가봅시다.
대책을 세우기 전에, 왜 위험한지를 충분히 이해해 두고 싶습니다. 이유를 알면 체크포인트가 자연스럽게 보이기 때문입니다.
Text-to-SQL(자연어로부터 SQL을 생성하는 것)의 정밀도는 최근 몇 년 사이 급격히 향상되었습니다. 하지만 숫자를 냉정하게 살펴보면 과신은 금물이라는 것을 알 수 있습니다.
BIRD라는 실데이터에 가까운 벤치마크(Benchmark)에서, 2026년 시점의 최상급 파이프라인이라 해도 실행 정밀도는 80%대 초반(인간 전문가는 약 93%)입니다.
- 또한 실무에 더 가까운 Spider 2.0의 에이전트 평가로 넘어가면 **약 21%**까지 떨어집니다.
여기서 중요한 것은 "대단하다/못한다"의 이야기가 아닙니다. 벤치마크의 숫자가 당신의 운영 스키마(Schema)에서의 정확성을 보장해 주지는 않는다는 사실입니다. 연구를 통해 밝혀진 것은, Text-to-SQL을 망가뜨리는 것은 "쿼리 구조의 복잡성"보다 실데이터, 운영 스키마, 모호한 요구사항이라는 사실입니다.
예를 들어 "활성 사용자"라고 말했을 때, 그것이 "최근 30일 이내에 로그인한 사람"인지 "결제 중인 사람"인지 AI는 당신 회사의 그 정의를 모릅니다. 그래서 그럴싸하지만 미묘하게 틀린 SQL을 당당하게 내놓는 것입니다.
더 본질적인 이유는 이것입니다.
AI는 당신의 운영 데이터베이스의 테이블 크기, 인덱스, 제약 조건(Constraint), 통계 정보를 모릅니다. 똑같은 SQL 한 줄이라도,
- 인덱스가 작동하면 2밀리초(ms)
- 인덱스가 작동하지 않으면 40초
정도로 가볍게 차이가 납니다. AI는 "구문적으로 올바른 SQL"은 쓸 수 있어도, "그것이 동작하고 있는 시스템에 무엇을 하는가"——어떤 락(Lock)을 잡고, 그것을 얼마나 오래 유지하며, 디스크 상에서 테이블을 새로 쓰는지——까지는 원리적으로 판단할 수 없습니다.
여기서 앞으로 몇 번이고 등장할 용어들을 미리 풀어서 설명해 두겠습니다.
- 인덱스 (Index): 책의 맨 뒤에 있는 색인과 같습니다. 색인이 있으면 "이 단어는 243페이지"라고 단번에 찾아갈 수 있습니다. 없다면 1페이지부터 끝까지 전부 넘겨가며 찾아야 합니다.
- 시퀀셜 스캔 (Seq Scan / Full Table Scan): 바로 그 "전부 넘기는" 상태입니다. 테이블의 모든 행을 위에서부터 순서대로 읽는 것을 말합니다. 데이터가 100만 행 있으면 100만 행을 모두 읽습니다. 작은 테이블이라면 문제가 없지만, 큰 테이블에서는 치명적입니다.
- 실행 계획 (EXPLAIN): 데이터베이스가 "이 SQL을 이런 작전으로 처리하겠습니다"라고 알려주는 작전 메모입니다. 인덱스를 사용하는지, 전부 읽는지, 어떻게 조인(Join)하는지 등이 적혀 있습니다. 읽는 법은 나중에 다루겠습니다.
- 락 (Lock): 같은 데이터를 동시에 건드려서 망가지는 것을 방지하기 위해 데이터베이스가 붙이는 "대기표"입니다. 이것이 길어지면 다른 사람의 처리가 모두 대기 상태가 되어, 시스템이 멈춘 것처럼 보일 수 있습니다.
이 네 가지만 알면 이미 절반은 이긴 것이나 다름없습니다. 그럼, 세 가지 축으로 들어가 보겠습니다.
첫 번째 축은 정확성입니다. 의도한 데이터를 제대로, 정확하게 가져올 수 있는가 하는 점입니다.
여기서 가장 효과적인 것은 기술이나 대단한 프롬프트가 아니라, 문맥 (Context)을 전달하는 것입니다. AI가 그럴싸하게 틀리는 원인의 대부분은 "당신의 데이터베이스 사정을 모르는 채로 작성하고 있기" 때문이므로, 알려주기만 하면 됩니다. 역설적으로 말하면, 여기가 Context Engineering이 활약할 차례입니다.
전달해야 할 문맥은 크게 다음 세 가지입니다.
- 스키마 (Schema): 테이블 정의 (컬럼명, 타입, 기본 키 (Primary Key), 외래 키 (Foreign Key), 인덱스)
- 용어의 정의: "활성(Active)", "매출", "탈퇴"와 같이 회사 특유의 용어가 무엇을 가리키는지
- 요구사항 및 제약사항: 무엇을 출력하고 싶은지, 기간, 정렬 순서, NULL 처리, 예상 행 수
당신은 PostgreSQL에 정통한 시니어 엔지니어입니다.
다음 스키마와 정의를 전제로, 요구사항을 충족하는 SQL을 하나 작성해 주세요.
# 스키마
...
포인트는 마지막의 **"모호하다면 마음대로 결정하지 말고 질문할 것"**이라는 문구입니다. 이 문구 하나만 넣어도 AI가 멋대로 판단하여 질주하는 것을 상당히 방지할 수 있습니다. "이번 달이란 게 달력 기준인가요? 아니면 최근 30일인가요?"와 같이 되묻게 됩니다. 모호함이야말로 text-to-SQL의 최대 적이기에, 이 부분을 인간과 AI가 함께 해결하는 것입니다.
그리고 나온 SQL을 리뷰할 때의 관점은 단순합니다.
- JOIN의 결합 키가 올바른가 (
user_id끼리 연결했는지, 이상한 곱하기 연산이 일어나고 있지는 않은지) - WHERE 조건이 의도대로인가 (기간, 상태, NULL)
- 집계의 단위(Granularity)가 맞는가 (
GROUP BY단위, 중복 카운트를 하고 있지는 않은지) - 용어의 정의에 충실한가 ("활성"의 정의를 제대로 반영하고 있는지)
여기까지가 "동작함·정확함"에 대한 이야기입니다. 하지만 정확한 SQL이라고 해서 반드시 빠른 것은 아닙니다. 다음 축입니다.
정확한 SQL이 만들어졌습니다. 하지만 그것이 운영 환경의 800만 행 테이블에서 2밀리초 만에 끝날지, 40초가 걸릴지는 겉모습만 봐서는 알 수 없습니다. 그래서 측정합니다. 도구가 바로 EXPLAIN입니다.
EXPLAIN은 방금 말한 "데이터베이스의 작전 메모"를 보여달라고 요청하는 명령어입니다. SQL 앞에 붙이기만 하면 됩니다.
EXPLAIN ANALYZE
SELECT u.id, u.name, SUM(o.amount) AS sales
FROM users u
...
EXPLAIN은 계획만 표시합니다. EXPLAIN ANALYZE를 붙이면 실제로 실행하여 실제로 걸린 시간까지 보여줍니다.
주의:
ANALYZE는 실제로 쿼리를 실행합니다. SELECT라면 기본적으로 안전하지만, UPDATE나 DELETE에 EXPLAIN ANALYZE를 붙이면 실제로 데이터가 업데이트되어 버립니다. 데이터 변경 계열을 계획만 보고 싶을 때는, 나중에 나올 트랜잭션(Transaction) + 롤백(Rollback) 안에서 수행하는 것이 안전합니다.
EXPLAIN의 출력 결과는 처음 보면 주문처럼 보여서 솔직히 "윽..." 하고 막막해질 수 있습니다. 하지만 처음 봐야 할 곳은 딱 한 군데뿐입니다. "Seq Scan"인가 "Index Scan"인가. 이것만 보면 됩니다.
-- 위험한 패턴 (전부 읽고 있음)
Seq Scan on orders o (cost=0.00..180000.00 rows=8000000 ...)
-- 좋은 패턴 (인덱스로 걸러내고 있음)
...
- Seq Scan (순차 스캔): 해당 테이블의 모든 행을 읽고 있습니다. 작은 테이블(수백~수천 행)이라면 신경 쓰지 않아도 됩니다. 하지만 수백만 행이 있는 테이블에서 이것이 나타난다면 경고 신호입니다.
- Index Scan (인덱스 스캔): 인덱스를 사용하여 필요한 행만 읽고 있습니다. 이것이 보이는 상태가 우리가 원하는 상태입니다.
여기에 더해, 다음 두 가지를 더 볼 수 있게 되면 매우 강력해집니다.
- rows 추정치와 실측치의 괴리:
EXPLAIN ANALYZE를 사용하면 '예측된 행 수'와 '실제 행 수'가 모두 나옵니다. 이 둘의 차이가 자릿수 단위로 크게 벌어져 있다면, 데이터베이스의 통계 정보가 오래되었을 가능성이 매우 높습니다 (ANALYZE 테이블명;으로 통계를 업데이트할 수 있습니다). - Nested Loop (중첩 루프)에 큰 입력: 조인(Join) 방식 중 하나로, 한쪽 데이터가 크면 행마다 반복해서 읽어야 하므로 느려지기 쉽습니다. 큰 입력 데이터가 나타난다면 주의해야 합니다.
EXPLAIN을 스스로 전부 읽지 못해도 괜찮습니다. 실행 계획을 붙여넣고, AI에게 통역과 대책을 세우게 하는 것이 현실적입니다. 이때 AI는 '설계자'가 아니라 '유능한 분석가'로 활용합니다.
다음은 PostgreSQL의 EXPLAIN ANALYZE 결과입니다.
이 SQL이 느린 원인을 초보자도 이해할 수 있는 용어로 설명해 주세요.
그다음, 개선안을 "효과가 큰 순서대로" 최대 3개까지, 각각
...
"효과가 큰 순서대로", "부작용도 작성할 것"이라고 제약을 거는 것이 요령입니다. AI는 인덱스를 무조건 추천하는 경향이 있지만, 인덱스는 공짜가 아닙니다. 읽기 속도는 빨라지는 대신, 쓰기(INSERT/UPDATE)는 조금 느려지고 디스크 공간도 차지합니다. 이러한 부작용까지 말하게 함으로써, 인간이 최종 판단을 내릴 수 있는 재료를 모을 수 있습니다.
"갑자기 운영 환경에서 EXPLAIN ANALYZE를 실행하는 것이 두렵다"——그 감각은 옳습니다. 그래서 먼저 작게 테스트하는 것입니다. 이것이 철칙과도 같은 안전책입니다.
-- 갑자기 전체를 반환하지 않고, 우선 10행만 확인한다
SELECT u.id, u.name, SUM(o.amount) AS sales
FROM users u
...
LIMIT 10을 붙여 먼저 실행하는 것만으로도, JOIN의 곱셈 실수(카테시안 곱, Cartesian Product)나 예상치 못한 거대한 결과 세트를 피해가 발생하기 전에 감지할 수 있습니다. "어라, 10행만 반환하는 건데 왜 이렇게 느리지?"라고 깨달을 수 있다면, 운영 환경에서 전체 데이터를 호출하기 전에 되돌아올 수 있습니다. 사소해 보이지만 효과적입니다.
세 번째는 가장 중요한 안전의 축입니다.
SELECT(읽기 전용)라면 최악의 경우에도 "느리다"로 끝납니다. 하지만 UPDATE, DELETE, DROP과 같이 데이터를 변경하거나 삭제하는 계열은 실패 시 돌이킬 수 없는 사고로 이어집니다. 이 영역은 AI에게 통째로 맡겨서는 안 됩니다.
키워드는 **blast radius (폭발 영향 범위)**입니다. 이 SQL이 어디까지, 몇 행에 영향을 미칠 것인가. 그것을 실행하기 전에 인간이 예측하고 가두는 것입니다.
가장 해서는 안 될 행동은 AI 에이전트에게 운영 DB 접속 권한을 주고 자유롭게 실행하게 하는 것입니다. 앞서 언급한 2025년 7월의 사고도 이것이 배경에 있었습니다.
추천하는 방법은 접속 권한 자체를 넘기지 않고, 스키마 정보만 파일로 전달하는 방식입니다. 스키마를 JSON 등으로 추출하여 리포지토리에 두면, AI는 운영 환경에 직접 닿지 않고도 "문맥"만 전달받을 수 있습니다. 접속에 따른 보안 리스크를 통째로 제거할 수 있습니다.
{
"table": "orders",
"columns": [
...
이것을 프롬프트에 첨부하는 것만으로도, AI는 운영 환경에 접속하지 않고도 행 수와 인덱스를 고려한 현실적인 SQL을 작성할 수 있습니다. 인간은 AI가 내놓은 SQL을 리뷰하고 자신의 손으로 직접 실행합니다. 실행의 주도권은 인간이 계속 쥐고 있어야 합니다.
DELETE나 UPDATE를 실행하기 전에, 완전히 동일한 조건으로 SELECT COUNT(*)를 실행해 보는 것은 습관으로 만들 가치가 있습니다.
-- ❌ 갑자기 이것을 실행하지 마세요
DELETE FROM orders WHERE status = 'pending' AND created_at < '2025-01-01';
-- ✅ 먼저, 몇 행에 해당하는지 센다 (영향 범위 확인)
SELECT COUNT(*) FROM orders WHERE status = 'pending' AND created_at < '2025-01-01';
...
"3행인 줄 알았는데 280만 행이었다"라는 사고는 대개 WHERE 조건의 착각에서 발생합니다. 삭제하기 전에 세어보세요. 단지 이것만으로도 blast radius를 눈으로 확인할 수 있게 됩니다.
그럼에도 불안할 때는, 트랜잭션(Transaction) 안에서 실행하여 정말 의도한 대로인지 확인한 뒤, 의도적으로 롤백(Rollback, 취소)하는 것이다. 말하자면 리허설이다.
BEGIN;
UPDATE orders
SET status = 'cancelled'
...
ROLLBACK을 실행하면, UPDATE는 없었던 일이 된다. "영향을 받는 행의 수(Affected rows)만 확인하고, 변경은 확정시키지 않는다." 이렇게 하면 리허설을 할 수 있다. 납득이 되었다면, 다시 BEGIN → UPDATE → 확인 → COMMIT 순서로 진행하면 된다.
인간의 주의력에만 의존하는 데에는 한계가 있다. 시스템으로 보호하자.
-- AI나 자동화에 사용하게 할 때는 읽기 전용 역할(Role)
CREATE ROLE ai_readonly LOGIN PASSWORD 'set_a_strong_password';
GRANT CONNECT ON DATABASE mydb TO ai_readonly;
...
읽기 전용 역할 (Read-only Role): 애초에 SELECT만 할 수 있는 권한으로 AI를 구동하면, AI가 아무리 폭주하더라도 데이터는 파괴되지 않는다. "권한을 주지 않는 것"이 가장 확실한 안전펜스다.
statement_timeout (쿼리 타임아웃): 쿼리 하나가 30초를 초과하면 자동으로 중단시키는 설정. WHERE 조건 누락이나 카테시안 곱(Cartesian Product)으로 폭주한 쿼리가 데이터베이스의 리소스를 모두 잡아먹기 전에 멈출 수 있다.
그리고 또 하나. AI에게 전적으로 맡기면 놓치기 쉬운 것이 바로 스키마 변경(DDL)의 이면 동작이다. 예를 들어 큰 테이블에 SET NOT NULL과 같은 변경을 가하면, ACCESS EXCLUSIVE라는 강력한 락(Lock)을 획득하여 그동안 해당 테이블에 대한 모든 읽기/쓰기가 중단될 수 있다. 400만 행 규모의 테이블에서 피크 타임에 이를 수행하면 서비스가 멈춘다. 일부 DDL은 겉보기에는 순식간인 것 같아도, 내부적으로는 디스크 상의 테이블 전체를 통째로 다시 쓸 수도 있다. AI는 이러한 "이면 동작"을 모른 채 태연하게 제안하곤 한다. 그렇기에 DDL이야말로 인간이 영향 범위를 읽고 나서 내놓아야 할 영역이다.
지금까지의 내용을 역할 분담 표로 정리한다. 이것이 이 글에서 가장 하고 싶은 말이다.
| 공정 | 주로 인간이 하는 일 (What / Why) | 주로 AI에게 맡기는 일 (How) |
|---|---|---|
| 요구사항 정의 | "무엇을", "왜" 도출하고 싶은지, 용어의 정의를 결정 | 요구사항의 모호한 점을 질문을 통해 파악 |
| ... | (이 부분은 AI에게 넘기지 않는다) |
한마디로 요약하자면, AI는 최고의 SQL 초안 작성자(Drafter)이고, 인간은 영향 범위(Blast radius)의 문지기다. 이것이 내가 생각하는 타협점이다.
"무엇을·왜(What / Why)"는 인간이 결정하고, "어떻게(How)"는 AI에게 맡긴다. SQL이든 애플리케이션 코드든, 이 경계선은 변하지 않는다고 생각한다.
마지막으로, 안전한 쪽으로 작동하는 프롬프트 하나를 소개한다. UPDATE나 DELETE를 AI에게 작성하게 할 때는, SQL 본문보다 먼저 영향 범위의 추정치와 확인 절차를 출력하게 하는 것이 안전하다.
지금부터 운영 데이터베이스에서 status를 업데이트하는 작업을 수행할 것입니다.
곧바로 UPDATE 문을 작성하지 말고, 다음 순서대로 출력해 주세요.
1. 먼저, 영향 범위를 확인하기 위한 SELECT COUNT(*)를 작성할 것
...
"곧바로 UPDATE를 쓰지 마라, 먼저 숫자를 세라, 리허설을 해라"라는 절차 그 자체를 프롬프트에 각인시켜 두는 것이다. 이렇게 해두면 AI가 절차의 파수꾼이 되어준다.
어렵게 생각할 필요 없다. 내일부터 이 4가지만 의식해 보자.
문맥을 전달하기: 스키마, 용어 정의, 예상 행 수를 AI에게 전달한 뒤 SQL을 요청한다. "모호하면 질문해 줘"라는 문장을 덧붙인다.
작게 시도하기: 운영 환경에서 전체 데이터를 대상으로 실행하기 전에, LIMIT 10으로 상태를 살핀다.
EXPLAIN으로 측정하기: Seq Scan이 발생하고 있지는 않은지 한 줄만 확인한다. 읽기 어렵다면 실행 계획(Execution Plan)을 AI에게 붙여넣어 통역시킨다.
영향 범위를 가두기: 변경 계열 작업은 COUNT(*)로 숫자를 센 다음에 진행한다. BEGIN ~ ROLLBACK으로 리허설을 한다. 실행 버튼은 인간이 누른다.
전부 한꺼번에 할 필요는 없다. 우선 4번인 "삭제하기 전에 숫자를 세는 것"만이라도 실천한다면 사고는 눈에 띄게 줄어들 것이다. 65점이어도 괜찮다.
AI에게 SQL을 작성하게 하는 것은 이제 당연한 시대가 되었습니다. 이는 정말 감사한 일이며, 우리는 "SQL을 1부터 직접 입력하는 작업"으로부터 상당히 해방되고 있습니다.
하지만 편리해지면 편리해질수록, 인간이 쥐고 있어야 할 것이 더욱 명확해진다는 느낌이 듭니다. 그것이 바로 이 글에서 내내 강조해 온 "영향 범위를 확인하는" 업무입니다. AI는 "동작하는 SQL"을 순식간에 만들어 줍니다. 하지만 "이것을 운영 환경(Production)에 배포해도 되는가"에 대한 최종 판단은 여전히 인간의 손에 달려 있습니다. 그리고 아마 앞으로도 이 영역은 인간의 업무로 남을 것입니다.
"동작함"은 하나의 통과점일 뿐입니다. 거기서부터 EXPLAIN으로 "속도"를 측정하고, 영향 범위로 "안전"을 확보해야 비로소 운영 환경에 배포할 수 있습니다. 이 한 단계를 번거로운 일로 여길 것인지, 아니면 미래의 자신에게 주는 선물로 여길 것인지의 차이입니다.
저는 최근 무언가를 실행하는 버튼을 누르기 전에, 항상 스스로에게 한 가지 질문을 던지곤 합니다.
"이 선택, 내일의 내가 '고마워요'라고 말해줄 만한 쪽인가?"
잠결에 운영 환경을 망가뜨려 다음 날 아침 얼굴이 창백해진 자신에게는 아마 "고마워요"라는 말을 듣지 못할 것입니다. 하지만 COUNT(*)로 숫자를 세고, 롤백(Rollback)으로 리허설을 하며, 제대로 납득한 뒤에 COMMIT을 한 자신에게 내일의 자신은 분명 "꼼꼼하게 해줘서 고마워요"라고 말해줄 것입니다.
완벽하지 않아도 괜찮습니다. 오늘보다 딱 한 단계만 더 정성스럽게. 그것만으로도 내일의 자신과 팀이 조금은 더 수월해질 것입니다.
여러분의 다음 SQL, 운영 환경에 배포하기 전에 딱 한 번만 멈춰 서 보는 건 어떨까요? 그 짧은 완충 작용이 미래의 여러분을 지켜줄 것입니다.
끝까지 읽어주셔서 감사합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기