
AI가 작성한 코드에 인간의 리뷰가 필요할까 —— API 키를 코드에 직접 작성한 것을 보고 생각한 점
요약
AI 코딩 툴의 뛰어난 성능에도 불구하고 인간의 코드 리뷰가 반드시 필요한 이유를 보안 관점에서 다룹니다. AI가 작성한 코드에 API 키가 하드코딩되는 등의 보안 취약점이 발생할 수 있음을 경고합니다.
핵심 포인트
- AI는 기능 구현과 예외 처리 등에서 매우 뛰어난 성능을 보임
- AI가 작성한 코드에 API 키가 하드코딩되는 보안 사고 위험 존재
- Private 리포지토리 환경이라도 보안 관행을 준수하는 것이 필수적임
- AI 코딩 툴 활용 시 인간의 검토는 단순 절차가 아닌 보안 방어 기제임
저는 엔지니어로 3년 차가 되었습니다.
업무에서는 업무용 Web 애플리케이션 (Java / Spring Boot) 프로젝트를 담당하면서, 개인 개발로는 iOS 앱도 만들고 있습니다.
AI 코딩 툴은 일상적으로 사용하고 있습니다. Claude에 유료 결제를 하여, 업무에서도 개인 개발에서도 평범하게 파트너로서 활용하고 있는 느낌입니다.
그러던 중, 최근 이런 생각을 자주 하게 됩니다.
"AI가 작성한 코드에, 인간의 리뷰가 정말로 필요할까?"
이 질문에 대한 답은 "당연히 필요하지"로 끝날 것처럼 보입니다.
하지만 저는 한때 진지하게 "필요 없을지도 모른다"라고 생각했습니다. 그리고 그 생각을 바꾸게 된 계기가 된 사건이 있었습니다.
이 기사는 그 일련의 생각들을 정리한 것입니다.
마찬가지로 AI를 사용하여 개발하고 계신 분들에게 무언가 울림을 줄 수 있다면 좋겠습니다.
우선 솔직한 이야기부터 시작하겠습니다.
AI 코딩 툴을 사용하기 시작했을 무렵, 저는 꽤 얕보고 있었습니다. "어차피 조잡한 코드가 나오겠지"라고 말이죠.
하지만 실제로 사용해 보니 상상 이상이었습니다.
- 요청한 기능이 한 번에 동작함
- 내가 쓰는 것보다 더 깔끔한 방식으로 작성함
- 예외 처리(Exception Handling)나 null 체크까지 세심하게 넣어줌
- "왜 이렇게 작성했는지" 물어보면 제대로 설명해 줌
제가 3년에 걸쳐 익혀온 것들을 단 몇 초 만에 해냅니다.
이것을 목격하면, "리뷰라는 게 그저 의식화된 절차(Ritual)가 아닌가?"라는 마음이 생겨납니다.
게다가 리뷰는 시간이 걸리죠.
리뷰어의 시간을 뺏기도 하고, 지적 사항을 주고받는 과정에서 1~2일이 허비되기도 합니다. 그만큼의 비용을 지불할 가치가 AI의 코드에 정말로 있는가.
"AI가 나보다 더 잘한다면, 내가 리뷰할 의미가 없지 않을까?"
이 의문은 꽤 진심으로 가지고 있었습니다.
그 생각이 바뀐 것은 개인 개발에서의 어떤 사건이 계기가 되었습니다.
저는 "MyEat"이라는 음식점 기록 앱을 개인 개발하고 있습니다.
구성 방식은 SwiftUI + Spring Boot + AWS Lightsail이며, 음식점 데이터 취득을 위해 Google Places API를 사용하고 있습니다. 소스 코드는 Azure Repos (Azure DevOps)의 private 리포지토리에서 관리하고 있습니다.
이 백엔드 부분을 만들 때, AI에게 프레임워크적인 부분(개요)을 의뢰하고, 디테일은 직접 다듬는 방식으로 개발을 진행하고 있었습니다.
그리고 나온 코드는 제대로 동작했습니다. API를 호출하고, 응답(Response)을 파싱하여 앱에 반환합니다. 예상대로의 동작이었습니다.
하지만 나중에 다시 살펴보니, API 키가 소스 코드에 직접 작성(Hard-coded)되어 있었습니다.
// 이미지 (실제 코드와는 다릅니다)
private static final String API_KEY = "AIzaSy...";
환경 변수도 아니고, .env도 아니고,
설정 파일도 아닌, 소스 코드 안에 그대로 적혀 있었습니다.
서버 측 애플리케이션이므로 클라이언트 측에 노출되는 것은 아닙니다.
Azure Repos의 private 리포지토리이므로, 그 순간 전 세계에 공개된 것도 아닙니다.
그럼에도 불구하고, 이것은 위험하다고 생각했습니다.
솔직히 말하면, 이번에 도움을 받은 것은 우연히 private 리포지토리였기 때문입니다.
제 판단이 옳았기 때문이 아니라, 운영의 초기 설정 덕분에 구제받은 것뿐입니다. 이 부분을 착각하면 다음에 똑같은 일을 했을 때 끝장납니다.
왜 위험한지 이유를 들어보겠습니다.
① 공개 범위는 영원히 변하지 않는다는 보장이 없다
private였던 리포지토리를 나중에 OSS(Open Source Software)로 전환하고 싶어질지도 모릅니다. 누군가에게 코드를 보여줄 기회가 생길지도 모릅니다. CI/CD 설정 실수로 로그에 키가 출력될지도 모릅니다.
"지금은 private니까 안전해"라는 생각은, 미래의 나의 선택지를 제한하거나, 혹은 미래의 내가 사고를 일으키게 만드는 것 중 하나입니다.
② Git의 히스토리는 사라지지 않는다
이것이 가장 까다롭습니다.
"위험하다"고 깨닫고 나중에 커밋(Commit)으로 지운다 해도, 히스토리를 거슬러 올라가면 보입니다. 완전히 지우려면 리포지토리의 히스토리를 다시 써야 하는데, 이것 또한 매우 번거롭습니다.
즉, "나중에 고치면 돼"가 통하지 않는 유형의 실수입니다.
③ 과금 API이므로, 유출되면 금전적 피해로 직결된다
Google Places API는 종량제 과금 방식입니다.
키가 유출되어 악용된다면, 전혀 예상치 못한 청구서가 날아오게 됩니다. 개인 개발자가 이런 실수를 저질렀다가는 감당하기 어려운 금액이 될 수도 있습니다.
이번 건에서 가장 "위험하다"고 느낀 점은 금액 문제도, 공개 범위 문제도 아니었습니다.
(금액도 당연히 무섭습니다)
코드가 완벽하게 작동하고 있었다는 점입니다.
에러도 발생하지 않습니다. 테스트도 통ผ่าน합니다. 앱에서도 문제없이 사용할 수 있습니다.
"동작 확인"이라는 관점에서는 100점 만점인 코드였습니다.
만약 여기서 제가 코드를 읽지 않았다면, 그대로 인지하지 못한 채 릴리스(Release)했을 것입니다.
이전에 취약점 진단에 관한 글에서도 썼지만, "동작하는 것"과 "안전한 것"은 완전히 별개의 문제입니다.
그리고 AI는 "동작하는 코드"를 쓰는 데는 엄청나게 능숙하지만, "안전한 코드"를 쓰고 있는지 여부는 또 다른 문제라는 것을 뼈저리게 느꼈습니다.
여기서 중요한 포인트가 있습니다.
AI는 틀린 코드를 작성한 것이 아닙니다.
"API 키를 사용해서 Google Places API를 호출하는 코드를 작성해줘"라는 요청에 대해, 부족함도 과함도 없이 응답한 것입니다.
단지 제가 "키를 직접 작성하지 말고 .env에서 읽어오도록 해줘"라고 말하지 않았을 뿐입니다.
여기서 당연히 이런 반론이 나올 수 있습니다.
"요청할 때 'API 키는 직접 작성하지 말고 환경 변수로 분리해줘'라고 한마디 덧붙이면 끝날 일 아닌가?"
맞는 말입니다. 실제로 그렇게 지시하면 단번에 해결됩니다.
지금의 저도 기밀 정보를 다루는 구현을 부탁할 때는 "환경 변수는 나중에 내가 작성할 테니 빈 정의만 해둬"라고 요청합니다.
하지만, 이 모든 것을 일일이 하는 것은 매우 고된 일입니다.
왜냐하면 이 방법에는 전제가 있기 때문입니다.
**"발생할 수 있는 문제를 요청하기 전에 우리가 전부 알고 있다"**는 전제입니다.
- API 키는 환경 변수로 분리할 것
- 사용자 입력은 준비된 문구 (Prepared Statement)로 처리할 것
- 출력 시에는 이스케이프 (Escape) 처리할 것
- 예외를 무시(Swallow)하지 말 것
- 로그에 개인 정보를 남기지 말 것
- 외부 URL로의 요청은 화이트리스트 (Whitelist)로 제한할 것
- 경로(Path)에 사용자 입력을 직접 사용하지 말 것
- ……
요청할 때마다 이 모든 것을 전제로 까는 것은 솔직히 힘든 일입니다.
게다가, 이 전제 리스트는 내가 알고 있는 것만 쓸 수 있습니다.
이번 API 키 건도 "알고 있었지만 말하는 것을 잊었다"라면 그나마 다행입니다.
무서운 점은, 내가 모르는 관점은 애초에 전제 리스트에 들어가지 않는다는 것입니다.
그래서 결국 이런 구도가 됩니다.
AI 코드의 허점은 "AI의 실수"가 아니라 "요청한 쪽의 시야의 허점"으로 나타난다.
AI는 물어본 것에 대해서는 완벽하게 답합니다. 하지만 물어보지 않은 것은 알려주지 않습니다.
인간 선배라면 "이거 키를 직접 작성했는데 괜찮아?"라고 한마디 해줄 것입니다. AI는 우리가 문제의식을 가지고 묻지 않는 한 그대로 전달합니다. 악의가 있는 것도, 능력이 낮은 것도 아니라, 단순히 "그 부분은 요청받지 않았기 때문"입니다.
사전 지시는 예방은 될 수 있지만, 발견은 되지 않습니다.
자신의 시야 밖에 있는 문제를 찾으려면, 결국 "나온 코드를 읽는" 프로세스가 필요합니다.
이 경험을 거쳐, "그렇다면 인간의 리뷰는 무엇을 보아야 하는가"를 정리해 보았습니다.
저 나름의 결론은, AI가 잘하는 것과 인간이 보아야 할 것은 애초에 영역이 다르다는 것입니다.
- 구문의 정확성
- 일반적인 코딩 스타일
- 흔한 버그 패턴 (Null 체크 누락, 경계값 등)
- 정형적인 구현 (CRUD, 유효성 검사 (Validation), 변환 처리)
이런 부분은 솔직히 AI가 더 안정적입니다.
"세미콜론이 빠졌다", "들여쓰기가 어긋났다" 같은 지적에 인간의 시간을 쓰는 것은 이제 낭비라고 생각합니다.
① 업무적으로 올바른가
코드로서 올바르더라도, 업무 요구사항과 맞는지 여부는 별개의 문제입니다.
AI는 프로젝트의 배경도, 클라이언트와의 합의 사항도, 과거의 경위도 모릅니다. "상태(Status)가 2일 때만 이 처리를 스킵한다"와 같은 업무 규칙은 코드 외부에 존재합니다.
② 기존 시스템과 정합성을 이루는가
우리 프로젝트에는 독자적인 공통 클래스나 명명 규칙 (Naming Convention), 레이어 구성 규칙이 있습니다.
AI는 "일반적으로는 이렇게 작성한다"를 내놓지만, "이 프로젝트에서는 이렇게 작성한다"는 모릅니다. 기존 코드와 따로 노는 구현은 추후 유지보수 시 확실히 영향을 미칩니다.
③ 보안상 문제가 없는가
이번 저의 케이스가 바로 이것입니다.
기밀 정보의 취급, 입력값의 유효성 검사 (Validation), 인가 (Authorization) 체크. 동작 확인만으로는 절대로 검출되지 않는 영역이기에, 의식적으로 살펴보는 수밖에 없습니다.
④ 그 코드가 정말로 필요한가
AI는 "써줘"라고 하면 써줍니다.
하지만, 애초에 그 구현이 필요한 것인지, 더 심플한 방법은 없는지, 기존의 공통 처리로 해결할 수 있는 것은 아닌지——라는 판단은 인간의 몫입니다. AI는 "필요 없어요"라고 말해주지 않습니다.
지금까지의 이야기를 정리하면, 저의 결론은 이렇습니다.
인간의 리뷰는 필요하다. 단, 역할이 바뀐다.
지금까지의 리뷰는 어느 쪽인가 하면 "실수를 찾는 작업"이었습니다.
작성 방식에 대한 지적, 버그 발견, 규약 위반 체크. 모든 행을 눈으로 훑으며 허점을 찾는 느낌이었죠.
하지만 AI가 코드를 작성하는 시대의 리뷰는, **"AI가 판단할 수 없는 영역을 인간이 채우는 작업"**이 될 것이라고 생각합니다.
| 관점 | 지금까지 | 앞으로 |
|---|---|---|
| 구문·스타일 | 인간이 체크 | AI에게 맡김 |
| ... |
봐야 할 포인트가 줄어드는 것이 아니라, 봐야 할 포인트의 밀도가 높아지는 이미지입니다.
오히려 리뷰는 더 어려워질지도 모릅니다.
마지막으로, 이것은 기술이라기보다 태도에 관한 이야기입니다.
업무에서 AI를 사용하는 것 자체는 현재 현장에서 보통 허용되고 있습니다. 쓰지 말라는 이야기가 아닙니다.
다만, 자신이 이해하지 못한 코드를 그대로 리뷰어에게 넘기는 것은 역시 실례라고 생각합니다.
리뷰어는 자신의 작업 시간을 깎아가며 리뷰를 해주고 있습니다.
그 사람에게 "AI가 작성해서 내용은 잘 모르겠습니다"라는 코드를 건네는 것은, 자신이 원래 해야 할 일을 상대에게 통째로 떠넘기는 것과 같습니다.
게다가 까다로운 점은, 리뷰어는 "이 사람은 이해한 상태에서 제출했다"라는 전제로 코드를 본다는 것입니다.
그 전제가 무너지면 리뷰의 정밀도 자체가 떨어집니다.
그래서 저는 최소한 이 라인을 지키려고 노력하고 있습니다.
- AI가 작성한 코드는, 자신의 언어로 설명할 수 있는 상태로 만든 뒤 제출한다. - "왜 이런 구현이 되었는가"에 답할 수 없는 부분은 이해하거나 다시 작성한다.
- 이해하지 못한 부분이 있다면, 그 사실을 솔직하게 덧붙여서 리뷰를 올린다.
마지막 항목이 은근히 중요한데, "이 부분은 AI가 제안한 구현인데, 왜 이렇게 되어 있는지 저도 확신이 서지 않습니다"라고 한마디 덧붙이는 것만으로도 리뷰어는 그 부분을 중점적으로 봐줍니다.
모르는 것을 모른다고 말하는 것은 떠넘기는 것과는 다릅니다.
"AI가 작성한 코드에 인간의 리뷰가 필요할까"——저의 대답은 **"필요하다. 단, 역할은 바뀐다"**입니다.
이유를 세 가지로 요약하면 다음과 같습니다.
① AI는 "동작하는 코드"는 쓸 수 있지만, "안전한 코드"인지는 보장하지 않는다
저의 API 키 직기재 건이 바로 그것이었습니다. 완벽하게 동작하는 코드가, 완벽하게 위험했습니다.
② 사전 지시는 예방은 될 수 있지만, 발견은 되지 않는다
"미리 조건을 전달하면 된다"는 옳은 말이지만, 그것은 자신이 알고 있는 문제에만 효과가 있습니다. 모든 우려 사항을 매번 전제로 깔기에는 현실적이지 않고, 자신의 시야 밖에 있는 문제는 리스트에조차 올라오지 않습니다. 그렇기에 나온 코드를 읽는 프로세스가 필요합니다.
③ 리뷰에서 봐야 할 포인트는 줄어들지 않고, 밀도가 높아진다
구문 체크는 AI에게 맡길 수 있는 만큼, 업무 정합성·기존 시스템과의 정합성·보안·설계의 타당성 같은 "인간만이 볼 수 있는 영역"에 집중하게 됩니다.
AI는 엄청나게 강력한 파트너입니다. 유료로 결제해서라도 쓸 가치가 있다고 생각하며, 쓰지 않을 이유가 없다고 생각합니다.
하지만, AI에게 맡길 수 있는 것은 "쓰는 것"이지 "책임을 지는 것"이 아니다라는 것이 지금 저의 실감입니다.
제출한 코드의 책임은 최종적으로 제출한 인간이 집니다.
이것은 AI가 아무리 똑똑해져도 아마 변하지 않을 것입니다.
실제로는 API 키를 그대로 적은 상태로 Azure repo에 push하지 않았습니다. 사전에 알아차렸습니다. 다만 push했을 가능성도 있기 때문에, 강조의 의미를 담아 본 기사에서는 push한 것처럼 작성했습니다.
이 기사는 실무 3년 차인 한 엔지니어의 경험을 바탕으로 작성되었습니다.
"우리 현장에서는 이렇게 한다", "나는 이렇게 생각한다" 등 댓글을 남겨주시면 기쁩니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Qiita AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기