
AI에게 완전 자동화로 서비스를 만들게 하면 보안은 어떻게 될까? — Claude Code에 구축한 「다층 방어 스택」
요약
AI가 자동 생성한 코드의 보안 불안을 해소하기 위해 Claude Code를 활용한 '다층 방어 스택' 구축 방법을 소개합니다. LLM 리뷰와 기계적 정적 분석을 결합하여 보안 취약점을 다각도로 검증하는 전략을 다룹니다.
핵심 포인트
- LLM 리뷰와 기계적 체크를 결합한 다층 방어(Defense in Depth) 전략
- Claude Code 전용 security-guidance 플러그인을 통한 실시간 패턴 탐지
- 작성 주체와 별도의 LLM을 활용한 독립적인 보안 리뷰 프로세스
- 정적 분석과 데이터 흐름 추적을 통한 취약점 보완
이전 기사(え!? 일주일 만에 Web 서비스를!? 할 수 있다고!! 완전 자동 개발 권장)는 3,300 view를 넘었습니다. 감사합니다.
……하지만, 실제로 계정 등록을 해준 사람은 친구뿐이었습니다.
원인을 생각해 보면,
- Qiita라는 장소의 특성상 「만드는 법」에는 관심이 있어도, 서비스 자체에는 관심이 없었다
모르는 개인이 (게다가 AI가 완전 자동화로) 만든 서비스에 이메일 주소를 등록하는 것은 리스크라고 느꼈다
이 두 가지가 있는 것 같습니다. 특히 두 번째는, 제가 독자라도 똑같이 생각할 것입니다. 「AI가 전부 작성한 코드」라는 말을 듣는 순간, 「어, 보안은 괜찮은 거야?」라고 생각하는 것은 자연스러운 반응입니다.
그래서 이 기사에서는 그 불안에 정면으로 답하기 위해 도입한, **Claude Code로 서비스를 개발할 때의 보안 다층 방어 스택 (Security Defense in Depth Stack)**을 소개합니다. 「AI가 쓰니까 위험하다」가 아니라 「AI가 쓰기 때문에, 기계적인 체크를 여러 층으로 끼워 넣을 수 있다」는 것이 결론입니다.
단일 대책에 의존하지 않고, 성질이 다른 체크를 겹치는 「다층 방어 (Defense in Depth)」로 구성했습니다.
| 층 | 대책 | 종류 | 작동 타이밍 |
|---|---|---|---|
| 1 | security-guidance 플러그인 | 패턴 탐지 + LLM 리뷰 | 코드 편집 시 · 턴 종료 시 · 커밋 시 |
| ... | |||
| 포인트는, LLM에 의한 리뷰(1, 4)와 LLM이 아닌 기계적 체크(2, 3, 5)를 섞어 놓은 것입니다. LLM은 문맥을 가로지르는 취약점(인가 누락 등)에 강하고, 정적 분석은 기지 패턴의 놓침 제로에 강합니다. 서로 보완하게 합니다. 5층째는 당초에 없었으나, 이 기사를 쓰는 도중에 빈틈을 발견하여 추가한 것입니다 (솔직한 경위는 후술). |
/plugin install security-guidance@claude-plugins-official
Claude Code 공식 마켓플레이스에 있는, Anthropic 제의 보안 리뷰 플러그인입니다. Claude가 생성한 코드를 Claude 자신과는 다른 레이어에서 검사하는 것이 핵심이며, 내부적으로는 3단계 구조로 되어 있습니다.
Edit / Write를 할 때마다 훅 (Hook)이 실행되어, 기지의 위험 패턴 약 25종을 정규 표현식으로 즉시 탐지하여 Claude에게 경고를 주입합니다. 탐지 예:
yaml.load()(임의 코드 실행으로 이어질 수 있음) →yaml.safe_load()를 권장pickle.load/torch.load(weights_only=False)등의 안전하지 않은 역직렬화 (Deserialization)- 생(Raw)
innerHTML대입 (XSS) - 하드코딩된 시크릿 (Secret)
- GitHub Actions 워크플로에 대한 입력 인젝션 (issue 제목 등을
run:에 직접 매립하는 것)
재미있는 점은, 이것이 「차단」이 아니라 「리마인드」라는 것입니다. 정당한 용도라면 Claude는 코멘트로 이유를 명시한 후 계속 진행합니다. 오탐으로 인해 개발이 멈추지 않는 설계입니다.
Claude가 작업을 마칠 때 (Stop 훅이 발화할 때)마다, 해당 턴의 차분(Diff)을 다른 LLM 호출 (기본값은 Opus 4.7)로 보내 보안 리뷰를 수행하며, 중요도가 높은 지적이 있으면 Claude에게 피드백하여 사용자가 결과를 보기 전에 수정하게 합니다.
「작성한 본인이 자기 신고로 리뷰한다」가 아니라, 차분만을 보는 별도의 관점을 가진 리뷰어를 끼워 넣는 이미지입니다.
git commit을 하면, SDK 구동 리뷰 에이전트가 기동하여 차분뿐만 아니라 관련 파일을 Read/Grep으로 읽으러 가서 데이터 흐름 (Data Flow)을 추적합니다. 이를 통해 패턴 매칭으로는 절대 찾을 수 없는
여러 파일에 걸친 취약점 —— IDOR (타인의 리소스를 ID를 바꿔서 액세스할 수 있는 문제), 인가 우회 (Authorization Bypass), 파일 횡단 SSRF 등 —— 을 검출합니다.
검출 대상 클래스는 인젝션, XSS, SSRF, 하드코딩 시크릿, IDOR, 인가 우회, 안전하지 않은 역직렬화, 패스 트래버설 (Path Traversal) 등입니다.
- 훅은 하네스(Harness) 측에서 작동하기 때문에, 상시 컨텍스트 (토큰) 비용은 거의 제로 -
~/.claude/claude-security-guidance.md또는<project>/.claude/claude-security-guidance.md
프로젝트 고유의 보안 정책을 작성하면 LLM 리뷰 프롬프트에 합성됩니다(예: "사용자 고유 데이터를 공유 캐시에 올리지 마라"와 같은 프로젝트 자체 규칙을 기계가 감시하도록 할 수 있음) - 전제: Python 3.8+ 필요
Semgrep은 업계 표준인 OSS 정적 분석(SAST) 도구입니다. 언어별로 풍부한 보안 규칙을 보유하고 있으며, **LLM과 달리 결정론적(Deterministic)**입니다. 즉, 동일한 코드에 대해 반드시 동일한 지적을 반환합니다. SaaS 버전(유료 AppSec Platform)도 있지만, CLI 본체와 커뮤니티 규칙은 오픈 소스로 무료이며 계정이 필요하지 않습니다. 스캔은 로컬에서 완결되며, 코드가 외부로 전송되지도 않습니다(--metrics=off 옵션으로 이용 통계 전송도 끌 수 있습니다).
Layer 1의 LLM 리뷰가 "문맥을 이해하여 수상한 점을 지적"하는 반면, 이 도구는 "기존의 취약 패턴을 포괄적이고 확실하게 잡아내는" 역할을 합니다. 이 두 가지 성질의 차이가 다층 방어의 핵심입니다.
사실 처음에는 공식 마켓플레이스의 semgrep (Semgrep Guardian) 플러그인을 설치했습니다. 하지만 이것은 Semgrep 계정으로의 OAuth 로그인을 전제로 하며, 세션 시작 시 갑자기 브라우저에서 로그인 페이지가 열릴 뿐만 아니라, 로그인하지 않은 상태라면 코드 편집 자체를 차단하는 동작을 보였습니다({"decision":"block","reason":"Not logged into Semgrep Guardian..."}).
"무료·로컬 완결·계정 불필요"로 운영하고 싶었기에 플러그인은 삭제하고, 무료 CLI를 호출하는 30줄짜리 훅(Hook)을 직접 제작했습니다. ~/.claude/hooks/semgrep-scan.sh:
#!/bin/bash
# PostToolUse (Write|Edit): 편집된 파일을 semgrep으로 스캔하고, 탐지 결과를 Claude에게 피드백
set -u
...
~/.claude/settings.json에 등록:
{
"hooks": {
"PostToolUse": [{
...
이렇게 하면 Claude가 파일을 작성한 직후 매번 Semgrep이 실행되며, 탐지 사항이 있으면 그 즉시 Claude에게 다시 돌려보내지게 됩니다(파일당 약 2초). 동작 확인을 위해 eval(params[:code])를 포함하는 Ruby 파일을 작성하게 했더니, 쓰기와 동시에 ruby.lang.security.no-eval 지적이 Claude에게 반환되어 수정을 유도하는 것을 확인했습니다. 하드 블록(Hard block)이 아니라 "수정하거나, 오탐(False positive)이라면 이유를 명시하라"는 설계로 만든 이유는, Layer 1의 패턴 경고와 마찬가지로 오탐 때문에 개발이 중단되지 않도록 하기 위해서입니다.
코드 리뷰 계열의 대책과는 별개로 중요한 것이, 애초에 AI에게 시크릿(Secret)을 읽게 하지 않는 것입니다. ~/.claude/settings.json에 deny 규칙을 추가했습니다.
{
"permissions": {
"deny": [
...
이렇게 하면 .env, SSH 비밀키, Rails의 master.key, 클라우드 인증 정보 등을 Claude가 읽을 수 없게 됩니다. deny 규칙은 허용 모드와 관계없이 항상 강제되므로, 자동 허용 모드로 실행 중이더라도 효과가 있습니다.
왜 필요할까요? LLM 에이전트에는 "프롬프트 인젝션 (Prompt Injection)"(읽어들인 웹 페이지나 파일에 심어진 지시를 따라버리는 현상)이라는 리스크 클래스가 존재합니다. 만일 AI가 속더라도, 시크릿에 손이 닿지 않는다면 유출될 일도 없습니다. 이 또한 "탐지"가 아닌 "차단"이므로 결정론적입니다.
deny 규칙과 짝을 이루는, 더욱 근본적인 대책은 이것입니다. 운영 환경의 시크릿은 애초에 로컬에도, 리포지토리에도 두지 않습니다. 저장 위치는 Vercel, Render, AWS 등 배포 서비스 측의 환경 변수 설정(대시보드)입니다.
- 운영 환경의 API 키, DB 비밀번호, Stripe 키는 제가 직접 대시보드에 입력합니다. AI에게는 값을 전달하지 않습니다(채팅에 붙여넣지 않습니다). AI에게는 "이 ENV 이름으로 참조하는 코드를 작성해줘"라고만 전달합니다. 이렇게 하면 AI의 작업 환경(=로컬 머신)에는 운영 시크릿(Production Secret)이 처음부터 존재하지 않습니다. 만약 deny 규칙이 실수로 뚫리더라도, 그곳에 있는 것은 개발용 더미(Dummy) 값뿐입니다. 부수적인 효과로, 리포지토리에도 남지 않기 때문에 git 히스토리를 통한 유출도 구조적으로 발생하지 않습니다. 실제로 이번에 프론트엔드의
.env[IMG:1] 파일이 첫 커밋부터 git 추적되고 있는 것을 발견했지만(앞서 언급), 이 운영 방식 덕분에 내용은 개발용 포트 설정뿐이라 무해했습니다. 코드는 "ENV 이름으로 참조할 뿐"이므로, 외부 서비스 교체도 대시보드의 ENV 교체만으로 끝납니다(저는 메일을 SES에서 Resend로 이전했지만, 코드 변경은 없었습니다).
요약하자면, 시크릿 관리는 "AI에게 읽히지 않는다(deny)"와 "AI가 있는 곳에 두지 않는다(배포 서비스 측 ENV)"라는 이중 구조입니다. 탐지 계층이 전부 뚫리더라도, 도난당할 물건이 그곳에 없는 상태를 만들어 두는 것——다층 방어(Defense in Depth)의 마지막 보루는 이것이라고 생각합니다.
운영 규칙으로서도 "시크릿은 채팅에 붙여넣지 않는다(붙여넣었다면 즉시 무효화 및 재발급) · .env [IMG:2] 파일은 인간이 관리한다"를 철저히 하고 있습니다.
Claude Code에 표준 탑재된 스킬로, 브랜치 변경 전체를 대상으로 보안 리뷰(Security Review)를 실행합니다. Layer 1이 "턴 단위 · 커밋 단위"인 것에 반해, 이것은 PR(Pull Request)로서 정리된 최종 형태를 보는 마지막 관문입니다. 머지(Merge) 전의 품질 게이트(모든 테스트 Green, Rebase 후 재실행)에 이것을 포함하고 있습니다.
"AI가 전자동으로 만들었다"라고 하면 무방비하게 들릴 수 있지만, 개발 규칙으로서 보안 설계를 명문화하여 Claude에게 전달하고 있기 때문에, 앱 자체에도 처음부터 다음과 같은 사항이 포함되어 있습니다.
- 레이트 리밋 (Rate Limit): rack-attack을 사용하여 IP/이메일 단위의 슬로틀링(Throttling, 브루트 포스 방지) 수행
- 인증 관련: Devise + 계정 잠금(lockable) + 이메일 확인(confirmable) + TOTP 방식의 2단계 인증
- ID 은닉: 순번 ID는 외부에 노출하지 않고 UUID만 공개. 비공개 리소스는 403이 아닌 404를 반환하여 존재 자체를 은닉
- 캐시 설계: 즐겨찾기, 좋아요 등의 사용자 고유 데이터는 공유 캐시에 절대 올리지 않음 (타 사용자에게 유출되는 것을 방지). 인가(Authorization) 판정은 캐시 호출 직전에 매번 실행
- 에러 모니터링: Sentry 도입 완료. 전송 전에 PII(개인정보)를 스크러빙(Scrubbing)
이 스택을 구축한 직후, 신기능(등록이 필요 없는 데모 모드) 구현에 실제로 적용해 보았습니다. 결과:
- Semgrep (Layer 2): 변경된 45개 파일을 스캔하여 지적 사항 1건 발생. 다만 내용은 "
PASSWORD_RESET_PATH = '/api/users/password'라는 URL 경로 상수를 시크릿으로 오탐(False Positive)한 것이어서 실질적인 해는 없었습니다. 인젝션(Injection), XSS 등의 기지 패턴은 제로였습니다. - 머지 전 LLM 보안 리뷰 (Layer 1/4 상당): 모든 쓰기 경로와 가드(Guard)의 대조, 캐시 유출 경로, 인가 우회 등을 반증적으로 검증하게 한 결과, 테스트 2,430건이 모두 Green임에도 불구하고 발견하지 못했던 실질적인 지적 사항 2건을 검출했습니다.
- 즐겨찾기 · 면담 요청 API에 UUID를 직접 지정하면, 원래는 볼 수 없어야 할 레코드에 도달할 수 있는 사이드 도어(IDOR의 아종)
- 인증 없이 호출 가능한 이벤트 기록 API가 레이트 리밋 대상에서 제외되어 있으며, 페이로드(Payload) 크기 제한이 없어 DB 비대화 공격이 가능함
2건 모두 즉시 이슈(Issue)화하여 수정했습니다. "테스트가 모두 통과했다"와 "보안적으로 안전하다"는 별개의 문제이며, 공격자 관점의 리뷰를 자동으로 끼워 넣는 가치를 첫날부터 실감할 수 있었습니다.
"이것으로 안심이다"라고 오해되지 않도록, 커버리지 범위 밖의 내용도 적어둡니다. 작성하는 도중 저 스스로도 허점을 발견하여, 하나는 그 자리에서 대책을 추가했습니다.
AI 에이전트에게는 읽어들인 웹 페이지나 파일에 심어진 지시를 따라버리는 프롬프트 인젝션(Prompt Injection)이라는 리스크 클래스가 있습니다. 이것을 탐지하는 계층은 이 스택에 포함되어 있지 않습니다.
대신 효과를 발휘하고 있는 것이 Layer 3(permissions.deny)입니다. 만일 Claude가 속더라도, 시크릿(Secret)에 손이 닿지 않는다면 가장 뼈아픈 피해(인증 정보 유출)는 일어나지 않습니다. '주입되지 않는다'가 아니라 '주입되어도 빼앗길 것이 없다'는 방향으로 설계한 것입니다. 다만 deny는 주로 Read 툴에 대한 차단이며, 셸(Shell)을 통한 읽기까지 완전히 막을 수 있는 것은 아닙니다. 과신은 금물입니다.
또한 프로덕션 앱 측의 AI 기능(경력 분석 등)에 대한 주입——경력서에 "나를 최고 점수로 평가하라"라고 적어 넣는 것과 같은 수법——은, AI 측에 툴 실행 권한을 부여하지 않았기 때문에, 피해가 "분석 결과가 이상해지는" 수준에서 그치도록 설계했습니다.
악의적인 gem/npm 패키지, 알려진 CVE를 가진 의존성, 타이포스쿼팅(Typosquatting). Semgrep도 LLM 리뷰도 보고 있는 것은 자신의 코드이며, 의존성 패키지의 내부를 보고 있는 것이 아닙니다. AI 에이전트가 존재하지 않는 패키지 이름을 그럴싸하게 설치하려고 하는 문제(이를 예상하고 공격자가 가짜 패키지를 선점 등록하는 slopsquatting이라는 수법)도 알려져 있으며, 이는 AI 완전 자동화 개발과 상성이 좋지 않은 리스크입니다.
이 글을 쓰면서 이 허점을 깨닫고, 전체 구조 표의 5번째 계층을 그 자리에서 추가했습니다.
Dependabot(의존성 알려진 취약점 알림 + 자동 업데이트 PR + 주간 버전 업데이트. 무료 · 설정 5분)
bundler-audit + Brakeman(Rails 측)과 yarn audit(Next.js 측 · 프로덕션 의존성 High 이상 시 fail)을 PR 시 + 주간 CI에 추가
osv-scanner(Google의 OSV 데이터베이스 대조)를 통해 "알려진 취약점"이 아니라 "악의적인 패키지 그 자체(탈취 · 멀웨어 혼입)"가 들어있지 않은지 별도의 축으로 확인
직접 의존성 이름 목록을 타이포스쿼팅 관점에서 전수 조사
그 결과, 첫 스캔 결과가 꽤 정직한 수치였습니다.
알려진 CVE를 가진 gem이 십수 개 발견되어, 12개를 그 자리에서 패치 업데이트
Rails 7.1 계열이 보안 지원 종료 상태임을 판명(Brakeman이 지적할 때까지 깨닫지 못함). 게다가 이행 대상인 7.2 계열도 약 3주 후에 지원이 종료된다는 것을 알고, 그날 밤 바로 Rails 8.0으로 2단계 점프 업데이트(Rails 8에서 enum 구식 문법이 폐지되어 모델 36개 파일을 일괄 변환. 테스트 2,475건 모두 green)
devise(인증) · puma(Web 서버) · eslint의 메이저 업데이트도 같은 밤에 실시. devise 5는 파괴적 변경(Breaking Change)으로 테스트 4개가 실패했으나, 호환성 수정 1줄을 넣어 해결——"자동 업데이트 PR을 맹목적으로 머지하지 않고, 모든 테스트를 통과시킨 후 반영한다"는 운영 방식이 그대로 효과를 발휘한 형태
결과적으로, 알려진 어드바이저리(Advisory) 억제 리스트는 비어 있음(=미뤄둔 것 제로) 상태에 도달
악의적인 패키지(OSV의 MAL 엔트리 해당)는 제로. 타이포스쿼팅도 없음
Brakeman의 SQL 인젝션 지적 3건은 모두 오탐(False Positive, 모델 상수 보간). 오탐 판정과 이유를 포함한 억제 리스트화까지 완료하여 운영에 반영
덤으로, 프론트엔드의 .env가 첫 커밋부터 git 추적되고 있었던 것을 발견하여 관리 대상에서 제외(내용은 개발용 포트 설정뿐이라 실질적 피해는 없음. 그럼에도 운영 규칙상 리포지토리에 두지 않음)
"다층 방어를 구축했다"라고 글에 쓴 본인이, 의존성 허점은 깨닫지 못하고 있었던 것입니다. 보안 대책에는 "이것으로 완성"이란 없다는 점을 포함하여 솔직하게 남겨둡니다. 참고로 이 일련의 탐지 → 업데이트 → 검증 → 머지 과정도, 예외 없이 AI가 자동으로 수행하고 있습니다.
"AI가 작성한 코드는 불안하다"에 대한 답은, 성질이 다른 체크를 여러 계층으로 자동 삽입하는 것
security-guidance(패턴 + LLM 차이점 + 커밋 시 데이터 흐름 추적)와 Semgrep(결정론적 SAST)으로 탐지를 이중화
시크릿은 이중 구조: permissions.deny로 AI가 읽지 못하게 + 프로덕션 ENV는 Vercel/Render의 대시보드 관리로 AI가 있는 곳에 두지 않음
의존성 패키지는 Dependabot + audit 계열 CI로 공급망(Supply Chain)도 감시(이 글을 작성하는 중에 추가)
머지 전에 /security-review로 최종 리뷰
인간(나)은, 이것들이 모두 green이 된 것만 머지한다
이번 학습을 통해 얻은 결론은, 완전 자동화 개발이란 '리뷰를 생략하는 것'이 아니라 '리뷰를 자동화 및 다중화하는 것'을 통해 성립된다는 점입니다.
그리고 한 가지 더. "그래도 이메일 주소를 등록하는 건 좀..."이라고 생각하시는 분들을 위해, 등록 없이 모든 페이지를 열람할 수 있는 데모 모드를 만들었습니다. 다음 장에서 소개하겠습니다.
보안을 강화하더라도 "모르는 개인의 서비스에 이메일 주소를 넘겨주는" 허들은 남습니다. 그래서 이메일 주소 등록 없이 서비스의 내용을 전부 볼 수 있는 데모 모드를 준비했습니다.
메인 페이지 또는 로그인 화면의 **「등록 없이 데모 보기」**를 통해, 클릭 한 번으로 데모 계정에 로그인할 수 있습니다. 관점은 세 가지입니다:
프리랜서 관점: 프로젝트를 찾는 쪽의 화면 (대시보드, 프로젝트 목록, 경력서, 채팅 등)
발주자 관점: 사람을 찾는 쪽의 화면 (프리랜서 목록, 모집 관리 등)
Pro 회원 관점: 유료 플랜(월 980엔) 화면. 경력서 AI 임포트(Import), AI 경력 분석, AI 자기 분석, AI 프로젝트 매칭 분석 등의 AI 기능 결과가 어떻게 보이는지 확인할 수 있습니다
프로젝트 30건, 프리랜서 20명, 경력서, 리뷰, 채팅 이력, AI 분석 결과 등의 데모 데이터가 포함되어 있습니다. "사용자가 늘어나면 이렇게 보인다"는 상태를 체험할 수 있습니다.
데모 데이터는 실제 데이터와 완전히 분리되어 있으며, 실제 사용자의 화면에는 데모 데이터가 일절 표시되지 않습니다 (반대의 경우도 마찬가지로, 데모에서 실제 사용자의 비공개 정보는 볼 수 없습니다).
데모는 열람 전용입니다. 등록, 갱신, 삭제 등의 쓰기 작업은 모두 차단됩니다 (이 또한 이번 다층 방어의 일부로, 서버 측에서 강제하고 있습니다).
데모 중에는 Pro 한정 기능(AI 계열)에 「Pro 기능」 배지가 붙으므로, 무료 플랜과 유료 플랜의 경계도 한눈에 알 수 있습니다.
데모 열람자에게는 익명 식별자를 발행하여, 어느 페이지가 얼마나 조회되었는지, 어디서 이탈했는지를 측정하고 있습니다 (이메일 주소 등의 개인정보는 일절 수집하지 않습니다). 서비스 개선을 위한 목적이므로 양해 부탁드립니다. 오히려 "AI에게 완전 자동화로 만들게 한 서비스의 관리 화면은 이런 행동 분석까지 만들 수 있다"는 실례로서, 이 측정 기반의 내부 내용도 기회가 된다면 별도의 글로 소개하겠습니다.
이 글을 읽고 "실제로 어느 정도 수준으로 만들어졌지?"라고 생각하신 분은, 꼭 데모 모드에서 확인해 보시기 바랍니다. 그리고 마음에 드신다면 꼭 등록해 주세요. 보안은 이 글에 쓴 대로 다층적으로 보호하고 있습니다.
다음 회차(제3탄)는 개발 이야기가 아니라, 그 이후의 현실적인 이야기입니다. 기사는 읽혔는데 아무도 등록하지 않는 "만들었는데, 아무도 오지 않는다"는 문제에 대해, 개발비 0원 플랜이라는 영업 전략으로 어떻게 도전할 것인가. 개인 개발의 콜드 스타트(Cold Start) 문제에 관심이 있는 분들은 그쪽도 확인해 주세요.
진행 상황은 X(@e8GU641fyp8wtVS)에서 발신하고 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기