설치·인증·첫 실행 - 세 도구를 같은 저장소에서 켜 보기
이 장에서 배우는 것
앞 장에서 터미널 AI 코딩 도구를 대화, 도구, 권한, 맥락의 조합으로 살펴봤다. 이제 같은 저장소를 세 도구로 열어 첫 요청을 보내는 과정을 정리한다. 첫 실행의 목표는 많은 코드를 만드는 일이 아니다. 어떤 계정으로 접속했는지, 어느 폴더를 보고 있는지, 무엇을 실행하도록 허용했는지를 설명할 수 있는 상태를 만드는 일이다.
이 책 제목의 ‘Gemini’는 Google의 Gemini 계열 도구를 뜻한다. 2026년 10월 기준 예시에서 개인 사용자는 Antigravity CLI를 중심으로 설명하고, Gemini CLI는 조직용 계정과 API 키 사용자의 경로로 구분한다. 설치와 로그인 화면은 바뀔 수 있으므로 화면의 위치를 외우기보다 확인할 항목을 익힌다.
- 세 도구의 설치 경로와 인증 선택이 서로 다른 결정임을 구분한다.
- Google 계열 도구에서 계정 종류에 맞는 실행 도구를 고른다.
- 첫 실행 전에 작업 폴더와 권한 질문을 확인한다.
- 파일을 바꾸지 않는 저장소 요약 요청으로 작업 범위를 점검한다.
- 표준 라이브러리만 사용하는 모의 프로그램으로 요약 결과를 재현하고 검증한다.
문제 상황
작은 팀이 Python으로 만든 업무 도구를 함께 관리한다. 한 사람은 Claude Code를 사용하고, 다른 사람은 Google 계열 도구를 사용한다. 검토를 맡은 사람은 Codex CLI를 켠다. 모두 같은 저장소를 열었다고 생각하지만, 첫 대화부터 설명이 어긋난다. 한 도구는 상위 폴더의 여러 프로젝트를 함께 설명하고, 다른 도구는 테스트가 없다고 답한다. 세 번째 도구에서는 로그인했는데도 예상한 이용 경로가 표시되지 않는다.
원인은 모델의 답변 능력만으로 설명되지 않는다. 첫 사람은 저장소의 상위 폴더에서 실행했고, 두 번째 사람은 파일을 읽도록 허용하지 않았다. 세 번째 사람은 구독 계정 로그인과 API 키 인증을 같은 과금 경로라고 생각했다. 실행 위치, 권한, 인증이라는 서로 다른 조건이 한꺼번에 섞인 상황이다.
팀은 첫날의 작업을 줄인다. 각자 저장소의 최상위 폴더에서 도구를 실행하고, 인증 경로를 확인한 뒤, 변경 없이 저장소를 요약하게 한다. 결과에는 확인한 파일과 확인하지 못한 범위를 적도록 요청한다. 요약이 실제 파일 목록과 맞는지 사람이 검토한 다음에야 수정 작업을 시작한다.
이 장의 완성 코드는 이 첫 질문을 흉내 낸다. 실제 AI를 호출하지 않고 임시 저장소를 만든 뒤, 정해진 규칙으로 파일을 센다. 출력은 자연어 추론 결과가 아니라 관찰 결과다. 이 구분은 실제 도구의 답을 검토할 때도 유용하다.
설치와 인증을 따로 결정한다
설치는 실행할 프로그램을 컴퓨터에 놓는 과정이다. 인증은 그 프로그램이 누구의 자격으로 서비스에 접근할지 정하는 과정이다. 프로그램 설치가 끝났다고 사용할 계정과 비용 경로까지 정해진 것은 아니다. 반대로 웹에서 계정에 로그인되어 있어도 터미널 프로그램의 인증이 끝났다고 단정할 수 없다.
2026년 10월 기준 예시에서 설치 명령과 지원 배포 경로는 각 도구의 공식 문서에서 확인한다. 이 장에서는 확인되지 않은 설치 명령을 제시하지 않는다. macOS와 Linux에서도 운영체제, 배포판, 실행 환경에 따라 안내가 달라질 수 있다. 설치 안내가 요구하는 조건을 먼저 읽고, 설치가 끝나면 아래 실행 명령을 사용할 수 있는지 확인한다.
| 도구 | 설치 방식 확인 | 인증 방식 확인 | 첫 실행 명령 |
|---|---|---|---|
| Claude Code | 공식 설치 문서에서 현재 지원하는 배포 방식과 운영체제 조건을 확인한다. | 계정 로그인과 API 키 중 사용할 수 있는 경로 및 이용 조건을 확인한다. | claude |
| Antigravity CLI | 공식 CLI 설치 안내를 따른다. 데스크톱 앱 설치와 CLI 사용 준비를 같은 것으로 가정하지 않는다. | 개인 계정의 플랜과 CLI 이용 경로를 확인한다. | agy |
| Gemini CLI | 공식 README에서 현재 설치 안내와 대상 사용자를 확인한다. | Code Assist 표준·기업용 계정 또는 API 키 경로를 확인한다. | gemini |
| Codex CLI | 공식 CLI 설치 문서에서 현재 지원하는 배포 방식을 확인한다. | 계정 로그인과 API 키 중 사용할 경로 및 이용 조건을 확인한다. | codex |
표의 Google 계열 두 행은 이 책에 비교 대상이 하나 더 늘었다는 뜻이 아니다. 같은 계열에서도 계정에 따라 출발점이 갈라진다는 뜻이다. 2026년 10월 기준 예시에서 2026년 6월 18일부터 개인 무료 사용과 Google AI Pro/Ultra 구독 사용은 Gemini CLI에서 Antigravity CLI로 옮겨 갔다. 예전 사용 기록만 따라 설치하면 자신의 계정에 맞지 않는 경로를 선택할 수 있다.
| 계정 또는 이용 목적 | 사용 도구 | 명령 | 구분할 점 |
|---|---|---|---|
| 개인 무료 사용 | Antigravity CLI | agy | 이전 Gemini CLI 개인 사용 경로와 구분한다. |
| Google AI Pro/Ultra 구독 | Antigravity CLI | agy | 개인 플랜과 CLI 이용 조건을 확인한다. |
| Code Assist 표준·기업용 | Gemini CLI | gemini | 조직에서 허용한 계정과 이용 정책을 확인한다. |
| API 키로 코딩 도구 사용 | Gemini CLI | gemini | 키가 연결된 프로젝트와 비용 경로를 확인한다. |
| 상태 없는 API 명령줄 호출 | 별도의 API 도구 | gemini-api | 저장소 작업을 수행하는 코딩 도구와 구분한다. |
구독 계정 로그인은 사용자가 로그인 절차를 거쳐 계정에 연결된 이용 자격을 프로그램에 전달하는 방식이다. API 키 인증은 프로그램이 요청에 사용할 자격 정보를 제공하는 방식이다. 둘 다 원격 서비스를 사용하지만, 사용 권한과 이용량을 귀속시키는 경로가 다를 수 있다. 구독을 보유했다는 사실만으로 API 요청 비용까지 포함된다고 판단해서는 안 된다.
API 키는 사용자 이름처럼 공개해도 되는 표식이 아니다. 요청 권한을 전달하는 비밀값이다. 저장소, 요청문, 공유한 터미널 기록에 붙여 넣지 않는다. 계정 로그인 역시 개인 계정인지 업무용 계정인지 확인한다. 팀원이 대신 로그인해 준 환경을 그대로 사용하면 사용 주체와 기록의 책임이 어긋난다.
2026년 10월 기준 예시에서 Antigravity CLI 사용량은 AI 크레딧 방식으로 안내된다. 이를 다른 도구의 구독이나 API 이용량과 같은 단위라고 간주하지 않는다. 이 장에서는 요금과 한도를 비교하지 않는다. 팀이 정할 것은 누가 어떤 자격으로 사용하며, 사용 내역을 어디서 확인할 것인가이다.
2026년 10월 기준 예시의 사실 확인 출발점은 Claude Code 공식 문서, Gemini CLI 공식 README, Antigravity 공식 사이트, Codex 공식 문서다. 설치 화면이나 인증 선택지가 이 장의 설명과 다르면 현재 공식 안내와 자신의 계정 조건을 대조한다.
첫 실행에서는 폴더와 권한부터 확인한다
설치를 마쳤다면 터미널에서 현재 위치를 확인한다. 터미널 명령 예시는 다음과 같다.
pwd
git status
첫 명령의 결과가 의도한 저장소 폴더인지 읽는다. 두 번째 명령에서는 현재 브랜치와 기존 변경을 확인한다. 아직 커밋하지 않은 변경이 있다면 그 사실을 기록한다. 이후 변경이 생겼을 때 AI가 만든 변경과 원래 있던 변경을 구분할 기준이 되기 때문이다.
이 장에서는 네 도구 행 모두 같은 저장소의 최상위 폴더에서 시작한다. 여러 도구를 처음부터 동시에 켤 필요는 없다. 하나를 열어 요약을 확인하고 종료한 뒤 다음 도구를 여는 방식이면 비교가 쉽다. 이 단계의 공통 조건은 저장소 내용과 요청문이다.
2026년 10월 기준 예시에서 실행 명령은 Claude Code의 claude, Antigravity CLI의 agy, Gemini CLI의 gemini, Codex CLI의 codex다. 실행 뒤 표시되는 작업 폴더와 인증 상태를 확인한다. 화면에 충분한 정보가 없다면 현재 공식 문서의 확인 방법을 따른다. 확인하지 않은 상태를 ‘아마 맞을 것’이라고 기록하지 않는다.
처음 만나는 권한 질문은 내용을 읽고 판단한다. 어떤 폴더에 접근하는지, 파일을 읽는 것인지 바꾸는 것인지, 터미널 명령을 실행하는 것인지 구분한다. 저장소를 신뢰할지 묻는 질문과 개별 동작을 허용할지 묻는 질문은 판단 범위가 다를 수 있다. 익숙한 저장소라는 이유만으로 뒤에 나오는 모든 실행까지 허용할 근거가 생기는 것은 아니다.
권한을 줄였다고 요약에 필요한 모든 동작이 가능해지는 것도 아니다. 파일을 읽는 데 필요한 승인을 거절했다면 도구가 저장소를 충분히 살펴보지 못할 수 있다. 이때는 ‘테스트가 없다’는 결론과 ‘테스트를 확인하지 못했다’는 설명을 구분해야 한다. 권한 모드의 세부 설계는 별도 주제이며, 여기서는 질문의 대상과 범위를 읽는 습관을 만든다.
요청문에 ‘수정하지 말라’고 쓰는 것은 작업 의도를 전달한다. 실제 접근 범위는 실행 환경과 권한 설정에도 영향을 받는다. 문장 하나만으로 보호가 끝났다고 생각하지 않는다. 첫 요청 전후에 상태를 비교하면 의도와 결과가 일치했는지 확인할 수 있다.
첫 요청은 관찰 가능한 저장소 요약으로 만든다
첫 질문으로 기능 추가를 요청하면 설치, 인증, 읽기 권한, 편집 권한, 테스트 환경의 문제가 한꺼번에 나타난다. 저장소 요약은 조건을 줄인다. 읽을 수 있는 범위와 답변의 근거를 먼저 확인하고, 코드 수정은 그다음에 다룬다.
세 도구에 사용할 첫 요청문은 다음처럼 작성할 수 있다. 아래 문장은 실제 응답이나 제품의 보장된 동작이 아니라 팀에서 사용할 요청 예시다.
현재 작업 폴더를 기준으로 저장소를 살펴봐라. 파일을 수정하거나 패키지를 설치하지 마라. 확인한 범위에서 주요 언어, 전체 파일 수, 테스트 폴더, 지침 파일의 존재 여부를 요약해라. 파일 수에서 제외한 폴더와 언어 분류 기준을 밝혀라. 테스트 폴더가 있다는 사실과 테스트를 실행해 통과했다는 사실을 구분해라. 읽지 못한 범위와 추정한 내용은 따로 적어라.
파일 수에는 하나의 자명한 정답이 있는 것이 아니다. 버전 관리 내부 파일, 가상 환경, 생성된 결과물까지 포함할지에 따라 값이 달라진다. 언어도 확장자로 셀지, 파일 내용을 분석할지에 따라 다르다. 따라서 숫자만 비교하지 않고 집계 기준을 함께 비교한다.
지침 파일은 이 장에서 존재 여부만 확인한다. 2026년 10월 기준 예시에서 Claude Code의 지침 파일은 CLAUDE.md, Gemini CLI의 지침 파일은 GEMINI.md, Codex CLI의 지침 파일은 AGENTS.md다. Antigravity CLI의 규칙 파일 이름은 여기서 확정하지 않으며 공식 문서에서 확인한다. 익숙한 이름을 다른 도구에도 그대로 적용하지 않는다.
실제 답변은 파일 목록과 대조한다. 예를 들어 테스트 폴더가 보인다는 답은 그 안의 테스트가 실행 가능하다는 뜻이 아니다. 지침 파일이 있다는 답도 해당 내용이 적용되었다는 증거는 아니다. 요약은 첫 관찰이며, 실행과 검토를 대신하지 않는다.
완성 코드
아래 프로그램을 main.py로 저장한다. Python 3.12 이상에서 외부 패키지, API 키, 네트워크 연결 없이 실행된다. 실행하면 임시 폴더에 예제 저장소를 만들고 요약한 뒤 종료한다. 현재 작업 중인 실제 저장소는 훑지 않는다. 따라서 실행 위치에 다른 파일이 있어도 출력은 바뀌지 않는다.
집계 기준도 프로그램에 고정한다. 일반 파일만 세고, 심볼릭 링크는 따라가지 않으며, 제외 목록에 있는 폴더 아래는 집계하지 않는다. 언어는 일부 확장자로만 분류한다. 테스트 폴더는 이름이 tests인 폴더를 찾고, 지침 파일은 저장소 최상위의 세 이름만 확인한다. 이 기준은 모의 프로그램의 규칙이며 실제 도구의 내부 동작을 재현한 것은 아니다.
from collections import Counter
from pathlib import Path
from tempfile import TemporaryDirectory
EXCLUDED_DIRS = {".git", ".venv", "__pycache__"}
LANGUAGES = {".py": "Python", ".js": "JavaScript", ".sh": "Shell"}
INSTRUCTION_FILES = ("CLAUDE.md", "GEMINI.md", "AGENTS.md")
SAMPLE_FILES = {
"README.md": "# 작은 팀 저장소\n",
"src/app.py": "def add(a, b):\n return a + b\n",
"src/view.js": "export const title = '작업 목록';\n",
"tests/test_app.py": "def test_add():\n assert 1 + 1 == 2\n",
"scripts/check.sh": "printf 'check\\n'\n",
"docs/setup.md": "설치 기록을 적는다.\n",
"CLAUDE.md": "변경 전에 작업 범위를 확인한다.\n",
"AGENTS.md": "변경 뒤 실행 결과를 확인한다.\n",
".git/config": "[core]\n",
".venv/lib/helper.py": "# 집계에서 제외한다.\n",
"src/__pycache__/cache.bin": "임시 데이터\n",
}
def create_sample(root: Path) -> None:
for relative, content in sorted(SAMPLE_FILES.items()):
path = root / relative
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content, encoding="utf-8")
def scan(root: Path) -> tuple[list[Path], list[str]]:
files: list[Path] = []
test_dirs: list[str] = []
def visit(folder: Path) -> None:
for path in sorted(folder.iterdir(), key=lambda item: item.name):
if path.is_symlink():
continue
if path.is_dir():
if path.name in EXCLUDED_DIRS:
continue
if path.name == "tests":
test_dirs.append(path.relative_to(root).as_posix())
visit(path)
elif path.is_file():
files.append(path.relative_to(root))
visit(root)
return files, sorted(test_dirs)
def summarize(root: Path) -> str:
files, test_dirs = scan(root)
counts = Counter(
LANGUAGES[path.suffix.lower()]
for path in files
if path.suffix.lower() in LANGUAGES
)
lines = [
"첫 질문 모의 응답",
"대상: 임시 예제 저장소",
"제외 폴더: " + ", ".join(sorted(EXCLUDED_DIRS)),
"집계 기준: 일반 파일, 심볼릭 링크 제외, 언어는 확장자 기준",
f"전체 파일 수: {len(files)}",
f"언어 분류 대상: {sum(counts.values())}",
]
for language, count in sorted(counts.items()):
lines.append(f"언어: {language} {count}개")
lines.append("테스트 폴더: " + (", ".join(test_dirs) or "없음"))
for name in INSTRUCTION_FILES:
state = "있음" if Path(name) in files else "없음"
lines.append(f"최상위 지침 파일: {name} {state}")
lines.append("테스트 실행: 하지 않음")
lines.append("파일 변경: 요약 과정에서 없음")
return "\n".join(lines)
def main() -> None:
with TemporaryDirectory(prefix="first-question-") as temporary:
root = Path(temporary)
create_sample(root)
print(summarize(root))
if __name__ == "__main__":
main()
줄별 해설
첫 세 줄은 개수 집계, 경로 처리, 임시 폴더 관리를 표준 라이브러리에서 가져온다. 프로그램은 설치된 AI 도구를 찾거나 인증 정보를 읽지 않는다. 도구 사용을 흉내 내는 부분은 파일을 관찰하고 그 결과를 문장으로 조립하는 과정이다.
EXCLUDED_DIRS는 방문하지 않을 폴더 이름을 정의한다. 경로 문자열 전체에서 특정 글자를 찾는 대신 각 폴더의 이름을 비교한다. 따라서 이름이 정확히 .venv인 폴더는 제외하지만, notes.venv.md 같은 일반 파일까지 함께 제외하지는 않는다.
LANGUAGES는 확장자와 표시할 언어의 대응표다. 이 예제는 Python, JavaScript, Shell만 센다. Markdown 파일과 확장자가 없는 파일은 전체 파일 수에는 들어갈 수 있지만 언어별 개수에는 들어가지 않는다. 전체 파일 수와 언어 분류 대상 수를 따로 출력하는 이유다.
INSTRUCTION_FILES는 최상위에서 존재 여부를 확인할 이름이다. 2026년 10월 기준 예시의 세 도구에서 확인된 이름을 사용한다. 이 목록에 Antigravity CLI의 이름을 추측해 넣지 않는다. 프로그램은 파일 내용을 지침으로 해석하거나 적용 여부를 판단하지 않는다.
SAMPLE_FILES는 임시 저장소에 쓸 상대 경로와 내용을 담는다. 집계 대상 파일 여덟 개와 제외될 파일 세 개를 준비한다. 테스트 예제는 존재 여부를 보여 주기 위한 입력 데이터다. 그 안의 assert는 이 요약 프로그램이 실행하는 검증 코드가 아니다.
create_sample은 상대 경로를 임시 폴더와 결합하고 필요한 부모 폴더를 만든다. 문자 인코딩을 UTF-8로 지정해 한글 내용을 기록한다. 이 함수가 파일을 생성하는 단계와 summarize가 읽어서 집계하는 단계를 분리했으므로, 출력의 ‘파일 변경 없음’은 요약 과정에 한정된 설명이다.
scan은 수집한 파일 경로와 테스트 폴더 경로를 반환한다. 내부의 visit 함수가 폴더를 재귀적으로 방문한다. 항목은 이름순으로 정렬한다. 운영체제가 반환하는 디렉터리 순서가 달라도 방문 순서는 일정하게 유지된다.
심볼릭 링크 확인을 폴더와 파일 판정보다 먼저 수행한다. 링크를 따라가면 예제 루트 밖의 파일까지 포함하거나 같은 위치를 반복 방문할 수 있기 때문이다. 이 코드는 링크를 집계에서 제외하는 단순한 규칙을 선택한다. 다만 이 규칙만으로 실제 AI 도구의 접근 권한을 통제하는 것은 아니다.
폴더라면 제외 목록부터 검사한다. 제외 대상은 안으로 들어가지 않으므로 그 아래의 테스트 폴더와 파일도 집계하지 않는다. 이름이 tests인 폴더는 상대 경로를 기록한 다음 계속 방문한다. 따라서 테스트 폴더 안의 파일도 전체 파일 수에 포함된다.
일반 파일 경로는 root를 기준으로 한 상대 경로로 저장한다. 임시 폴더의 실제 이름은 실행마다 달라질 수 있으므로 출력에 사용하지 않는다. 테스트 폴더를 표시할 때는 as_posix로 구분자를 일정하게 만든다.
summarize는 수집한 경로의 확장자를 소문자로 바꾸고 대응표에 있는 언어만 센다. Counter는 같은 언어에 속한 파일 수를 모은다. 이후 언어 이름을 정렬해 출력하므로 사전이나 파일 생성 순서에 기대지 않는다.
지침 파일 확인에서는 Path(name)이 수집된 상대 경로 목록에 있는지 검사한다. docs/AGENTS.md는 최상위 AGENTS.md와 다른 경로다. 이 프로그램의 ‘없음’은 최상위에서 집계한 일반 파일 중에 없다는 뜻이며, 저장소 전체 어디에도 같은 이름이 없다는 뜻은 아니다.
마지막 두 문장은 관찰의 한계를 표시한다. 테스트 폴더를 발견했지만 테스트를 실행하지 않았고, 요약 함수는 파일을 쓰지 않았다. main은 임시 폴더를 만들고 예제 데이터를 준비한 다음 요약을 한 번 출력한다. with 블록이 끝나면 임시 폴더도 정리된다.
실행 결과
macOS 또는 Linux에서 main.py를 저장한 폴더로 이동한 뒤 다음 명령을 실행한다.
python3 main.py
예상 출력은 다음과 같다. 임시 경로, 현재 시각, 네트워크 응답을 출력에 포함하지 않아 반복 실행해도 같다.
첫 질문 모의 응답
대상: 임시 예제 저장소
제외 폴더: .git, .venv, __pycache__
집계 기준: 일반 파일, 심볼릭 링크 제외, 언어는 확장자 기준
전체 파일 수: 8
언어 분류 대상: 4
언어: JavaScript 1개
언어: Python 2개
언어: Shell 1개
테스트 폴더: tests
최상위 지침 파일: CLAUDE.md 있음
최상위 지침 파일: GEMINI.md 없음
최상위 지침 파일: AGENTS.md 있음
테스트 실행: 하지 않음
파일 변경: 요약 과정에서 없음
숫자는 입력 데이터와 직접 대조할 수 있다. README.md, 소스 파일 두 개, 테스트 파일 하나, 셸 파일 하나, 문서 하나, 지침 파일 두 개를 더하면 여덟 개다. 그중 언어 대응표에 들어가는 파일은 네 개다. .git, .venv, __pycache__ 아래의 세 파일은 포함되지 않는다.
실제 저장소에서 AI 요약을 받았을 때도 같은 방식으로 표본을 대조한다. 요청 전후에는 다음 명령으로 상태와 차이를 확인한다.
git status
git diff
git diff에 내용이 없다는 사실만으로 모든 새 파일까지 없다고 단정하지 않는다. git status를 함께 읽어 추적되지 않은 파일도 확인한다. 원래 변경이 있었다면 요청 전 기록과 비교한다. 이 장에서는 실행 결과를 대조하고, 실제 수정 작업에서는 관련 테스트까지 수행하는 방식으로 검증 범위를 넓힌다.
실무에서 자주 틀리는 것
전체 파일 수와 언어별 파일 수를 같게 만든다
다음은 잘못된 집계 표현이다. 아래 두 조각은 main.py에 포함된 코드가 아니라 각각 실행해 비교할 수 있는 짧은 예제다.
files = ["app.py", "README.md"]
python_files = [name for name in files if name.endswith(".py")]
print("전체 파일 수:", len(python_files))
이 코드는 Python 파일 수를 전체 파일 수라고 표시한다. 고친 예제는 관찰 대상을 따로 출력한다.
files = ["app.py", "README.md"]
python_files = [name for name in files if name.endswith(".py")]
print("전체 파일 수:", len(files))
print("Python 파일 수:", len(python_files))
실제 첫 요청에서도 ‘파일 수’라는 말만 쓰지 않고 집계 기준을 요구한다. 두 도구가 다른 숫자를 냈다면 먼저 무엇을 포함했는지 비교한다.
테스트 폴더를 발견하고 통과했다고 기록한다
틀린 예제는 폴더 존재를 실행 결과로 바꿔 쓴다.
test_dirs = ["tests"]
status = "통과" if test_dirs else "없음"
print("테스트:", status)
고친 예제는 관찰과 실행 상태를 분리한다.
test_dirs = ["tests"]
print("테스트 폴더:", ", ".join(test_dirs) or "없음")
print("테스트 실행: 하지 않음")
테스트 파일을 읽어 본 것과 실행한 것도 다르다. 실제 도구가 ‘문제가 없어 보인다’고 답했다면 실행한 명령과 결과가 있는지 확인한다. 첫 요약 단계에서는 실행하지 않았다는 기록도 충분히 유용하다.
실행마다 달라지는 임시 경로를 답에 넣는다
틀린 예제는 임시 폴더의 실제 경로를 출력한다.
from tempfile import TemporaryDirectory
with TemporaryDirectory() as temporary:
print("대상:", temporary)
이 출력은 환경과 실행에 따라 달라진다. 예제의 목적이 경로 자체를 검사하는 것이 아니라면 고정된 설명을 사용한다.
from tempfile import TemporaryDirectory
with TemporaryDirectory():
print("대상: 임시 예제 저장소")
실무에서는 실제 작업 경로를 확인해야 한다. 교육용 재현 출력에서 경로를 생략하는 선택과, 운영 기록에서 경로를 남기는 선택은 목적이 다르다. 완성 코드는 출력의 재현성을 위해 실제 임시 경로를 숨긴다.
관찰하지 않은 인증 상태를 코드에서 확정한다
프로그램이 시작됐다는 사실만으로 원하는 구독이나 API 경로를 사용한다고 단정할 수 없다. 다음 코드는 그런 추정을 그대로 기록한 틀린 예제다.
program_started = True
auth_path = "구독 계정" if program_started else "미확인"
print("인증 경로:", auth_path)
고친 예제는 별도 확인이 필요한 상태를 그대로 남긴다.
program_started = True
auth_path = "미확인"
print("프로그램 시작:", program_started)
print("인증 경로:", auth_path)
인증 경로는 실제 로그인 안내와 계정 정보를 확인해 채워야 한다. 비밀값을 출력해 확인하는 방법은 사용하지 않는다. ‘미확인’은 실패를 감춘 표현이 아니라 아직 얻지 못한 정보를 정확히 표시한 값이다.
한눈에 보기
| 단계 | 확인할 것 | 남길 기록 | 검증 방법 |
|---|---|---|---|
| 설치 | 운영체제에 맞는 공식 설치 안내 | 사용 도구와 설치 경로 | 실행 명령으로 프로그램이 열리는지 확인한다. |
| 인증 | 계정 로그인 또는 API 키 경로 | 이용 주체와 비용 확인 위치 | 현재 계정과 이용 경로를 대조한다. |
| 작업 폴더 | 저장소 최상위와 기존 변경 | 경로, 브랜치, 변경 상태 | pwd와 git status를 읽는다. |
| 권한 질문 | 접근 대상과 허용할 동작 | 허용한 범위와 읽지 못한 범위 | 요청 목적과 실제 승인 내용을 대조한다. |
| 첫 요약 | 언어, 파일 수, 테스트, 지침 파일 | 집계 기준과 관찰 결과 | 실제 파일을 표본으로 확인한다. |
| 요청 이후 | 예상하지 않은 변경 여부 | 실행 결과와 차이 | git status와 git diff를 함께 확인한다. |
첫 요약이 맞았다고 이후의 코드까지 믿을 근거가 생기지는 않는다. 대신 어느 폴더를 어떤 자격과 권한으로 읽었는지 확인한 출발점이 생긴다. 다음에는 발견한 지침 파일의 내용과 적용 범위를 정리한다. 파일 이름의 존재를 확인하는 일과 팀의 작업 규칙을 설계하는 일은 그때 구분해 다룬다.
연습 문제
- SAMPLE_FILES에 src/report.py를 추가하면 전체 파일 수, 언어 분류 대상 수, Python 파일 수가 각각 어떻게 바뀌는지 예측하고 실행 결과와 비교하라.
- SAMPLE_FILES에 docs/GEMINI.md를 추가하라. 최상위 지침 파일 GEMINI.md가 계속 ‘없음’으로 표시되는 이유를 설명하라.
- 팀원이 테스트 폴더를 찾았다는 AI 답변을 근거로 검토 기록에 ‘테스트 통과’라고 썼다. 기록을 두 문장으로 고치고, 통과 여부를 확정하려면 무엇이 더 필요한지 적어라.
- 첫 요청 뒤 git diff에는 내용이 없지만 git status에는 새 파일이 표시된다. ‘변경 없음’이라고 결론 내릴 수 있는지 설명하고 확인 순서를 적어라.
정답과 해설
- 전체 파일 수는 9, 언어 분류 대상 수는 5, Python 파일 수는 3이 된다. .py가 언어 대응표에 있고 src는 제외 폴더가 아니므로 세 집계에 모두 반영된다. 실행 전에 예측값을 적고 출력과 비교하면 집계 규칙을 검증할 수 있다.
- 전체 파일 수는 9가 되지만 최상위 GEMINI.md는 계속 ‘없음’이다. 수집된 경로는 docs/GEMINI.md이고 검사 대상은 GEMINI.md이기 때문이다. 이 결과는 하위 폴더의 지침 적용 여부를 설명하지 않는다. 2026년 10월 기준 예시에서도 도구의 실제 지침 탐색 범위는 별도로 확인해야 한다.
- ‘tests 폴더를 확인했다. 테스트는 아직 실행하지 않았다’로 고친다. 통과 여부를 확정하려면 프로젝트가 정한 테스트를 실제로 실행하고 종료 상태와 결과를 확인해야 한다. 폴더 이름이나 파일 내용만으로 실행 결과를 대신할 수 없다.
- 바로 결론 내릴 수 없다. 먼저 요청 전 상태와 비교해 새 파일이 원래 있었는지 확인하고, 새로 생긴 파일이라면 내용과 생성 이유를 검토한다. 그다음 기존 파일의 diff와 실행 결과를 함께 확인한다. AI가 만들었다는 이유만으로 새 파일을 채택하거나 곧바로 삭제하지 않는다.