v1.2.0 — 한 줄로 설치하고, 한 줄로 최신으로
v1.1.0은 입구를 ./guide 하나로 모았다. 그런데 그 입구에 닿으려면 저장소를 먼저 손에 넣어야 했고, 그 방법이 문서 어디에도 없었다.
$ rg "git clone|다운로드|releases/" README.md docs/*.md
(0건)
README.md는 ## 한 번에 시작하기에서 곧장 ./guide로 넘어간다 — 이미 클론했다는 전제가 암묵적으로 깔려 있었다. 이번 릴리스는 그 앞의 한 칸을 채운다.
curl -fsSL https://raw.githubusercontent.com/Ahngbeom/dba-guide/main/install.sh | bash새로 생긴 것 — install.sh
한 줄이면 저장소가 ~/.local/share/dba-guide에 놓이고 guide·exam·shoot 세 명령이 ~/.local/bin에 걸린다. 같은 명령을 다시 실행하면 업데이트다(멱등). 제거는 … | bash -s -- --uninstall.
- 설치 지점은 언제나 최신 정식 릴리스 태그다 —
mainHEAD가 아니다. 이 저장소에는 CI가 없어 테스트 실행도,./shoot doctor도, 벤더 브랜치 재생성도 전부 릴리스 전 사람 손 점검이고, 그 점검을 통과한 지점에만 태그가 붙는다.mainHEAD는 아무도 검증하지 않은 지점이라 학습자의 기본값이 될 수 없다. 프리릴리스(-rc)는 건너뛴다. - 설치를 강제하지 않는다.
git clone후./guide도 그대로 동작하며, README는 두 길을 나란히 적는다. 런처가 자기 경로를 스스로 풀기 때문에 클론만으로 전부 돌아간다. - 필요한 것은
git과python3(3.9 이상)뿐이다. Docker가 없으면 경고만 하고 진행한다 — 챕터 읽기와 학습 점검은 Docker 없이 완전히 동작하고, 장애 대응만 랩이 필요하다.
자기가 만들지 않은 것은 건드리지 않는다
남의 머신에서 curl | bash로 도는 스크립트다. 다음은 전부 한국어 설명과 함께 중단한다 — 덮거나 지우지 않는다.
| 상황 | 왜 위험한가 |
|---|---|
| 런처 이름에 남의 파일·심볼릭 링크가 있다 | 세 이름을 모두 확인한 뒤 한 번에 보고한다. 하나씩 죽으면 같은 실패를 세 번 겪는다 |
| 설치 경로에 git 저장소가 아닌 것이 있다 | 지우지도, 그 위에 클론하지도 않는다 |
| 설치 경로가 남의 저장소 안에 들어앉아 있다 | 홈을 git으로 관리하는 사람의 경우다. 그대로 두면 fetch·checkout이 바깥 저장소를 대상으로 돈다 |
| 설치 경로에 다른 저장소가 있다 | scripts/guide.py 유무로 신원을 확인한다. 벤더 브랜치를 그 자리에 클론해 둔 사람이 실제로 겪을 수 있다 |
| 설치본의 추적 파일이 수정돼 있다 | git status --short를 보여주고 멈춘다 |
저장소 안에서 실행하면 그 자리를 링크할 뿐 HEAD를 옮기지 않는다. 기여자가 자기 작업 클론에서 돌렸는데 브랜치가 릴리스 태그로 detached 되면 작업이 끊긴다.
제거는 학습 기록을 지우지 않는다
--uninstall은 링크만 지운다. 저장소 디렉터리는 남는다.
.exam-results/와 .shooting-progress/notes/는 .gitignore 대상이라 어디에도 백업이 없는 유일본이다. 특히 정리 노트는 엔진이 관찰한 사실만 채우고 근본 원인·5 Whys·재발 방지를 빈칸으로 남기는 — 그걸 채우는 게 학습인 — 산출물이다. 지우려면 --purge를 명시해야 하고, 그때도 시험 결과 몇 건·정리 노트 몇 건이 사라지는지 먼저 보여준 뒤 확인을 받는다. tty가 없으면 확인할 수 없으므로 지우지 않고 멈춘다.
학습서
본문은 이번 릴리스에서 바뀌지 않았다(31챕터 그대로). README.md에 ## 설치 절이 들어갔고, docs/release-policy.md에 인스톨러와 태그의 순서 의존성이 기록됐다.
./guide · ./exam · ./shoot
바뀌지 않았다. 제거되거나 의미가 바뀐 인자는 없고, 문제은행(23개 216문항)과 스테이지(14개)도 그대로다. 설치본에서는 ./ 접두사만 떼고 guide·exam·shoot으로 부르면 된다 — 그래서 기존 문서의 ./exam·./shoot 표기 67곳이 그대로 유효하다.
벤더 브랜치
postgresql/mysql/oracle 세 브랜치를 이 릴리스 시점의 main에서 재생성해 push했다. install.sh는 이 브랜치들을 설치 대상으로 삼지 않는다 — 편의가 아니라 구조 때문이다. v1.1.0의 읽기 모드가 filter_dbms.filter_lines(단일 벤더 브랜치를 자르는 것과 같은 함수)로 벤더별 본문을 보여주므로 브랜치를 클론할 이유가 사라졌고, 이 브랜치들은 매번 --force-with-lease로 재생성되므로 설치 대상으로 삼으면 업데이트가 fast-forward가 아니라 reset --hard가 되어 사용자 수정을 말없이 지우는 경로가 생긴다.
검증에 대해 — 통과하는 테스트 수는 커버리지가 아니다
이번 개발에서 실측된 것 하나를 남긴다. 리뷰 도중 install.sh의 링크 소유권 판별 검사 한 줄을 지웠는데 578개 테스트가 전부 그대로 통과했다. 그 불변식은 테스트가 아니라 코드 리뷰로만 지켜지고 있었다는 뜻이다.
지금은 그 두 검사가 각각 전용 테스트로 고정돼 있고, 해당 줄을 지우면 지정된 테스트가 실패하는 것까지 확인했다. --purge의 확인 프롬프트는 pty.openpty()로 진짜 tty를 만들어 y(삭제)·n(취소)·Ctrl-D(취소) 세 경로를 모두 실행한다 — 이 저장소에서 가장 파괴적인 한 줄이 그전까지 한 번도 실행되지 않고 있었다.
알려진 한계
발견되지 않은 버그가 아니라 알고 감수하는 경계다.
인스톨러 (신규)
curl | bash의 신뢰 모델. 스크립트를 읽지 않고 실행하게 한다. README에 내려받아 확인한 뒤 실행하는 2단계 방법을 함께 적었고, 스크립트는 짧고 읽을 수 있게 유지했다.--purge는 파이프로 실행할 수 없다. 확인에 tty가 필요하다. 내려받은 사본에서bash install.sh --uninstall --purge로 실행해야 한다.- PATH 등록은 자동으로 하지 않는다.
~/.local/bin이$PATH에 없으면 더할 한 줄을 출력만 한다. 남의 셸 설정을 말없이 고치지 않는다. - PATH 점검은
~/.local/bin이 끝에 슬래시가 붙거나~로 미전개된 형태면 못 알아본다. - 태그가 붙은 트리에 세 런처가 다 있는지는 검사하지 않는다(
v1.1.0이후로는 항상 참). - 이름 충돌:
guide/exam/shoot은 일반적인 이름이다. 사용자 스코프 설치와 설치 전 충돌 감지로 막지만, 나중에 같은 이름이 설치되면 우리 링크가 가려질 수 있다. - Windows 네이티브 미지원. WSL 안에서 쓴다. Homebrew·PyPI·컨테이너 이미지도 지원하지 않는다.
판정 회피 (MySQL)
- 플레이어(
dba)에게는 튜닝 스테이지를 위해SYSTEM_VARIABLES_ADMIN이 있고, 그 권한이면 엔진과 같은 방법(SET SESSION sql_log_off = 1)으로 자기 명령을 로그에서 뺄 수 있다. - 명령 로그를 읽고 비우는 사이에 수 ms의 유실 창이 있다. 로그 테이블에는
DELETE가 막혀 있어(ERROR 1556) "읽은 지점까지만 지우기"가 불가능하므로 고칠 수 없다. 판정 대부분이 누적 목록이 아니라 최종 상태에 기대므로 실해는 거의 없지만, 타임라인에서 한 줄이 빠질 수 있다.
PostgreSQL 판정의 두 구멍 (MySQL에는 없다)
- 파싱 오류는 감시에 남지 않는다. 실측 결과 정확히 파싱 오류만 빠진다 — 없는 테이블 조회나 권한 오류는 잡히고,
KILL 999999(PG 문법이 아님)는 놓친다. - pid를 적지 않는 쓸기가 보이지 않는다.
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE ...형태는 문장에 숫자가 없어kill_precision이 잡지 못한다. 감점 대상으로 삼으려면 스테이지에서forbidden_command로 직접 막아야 한다.
커버리지 공백
- 스테이지 14개 중 MySQL 13 / PostgreSQL 1. Oracle 스테이지는 없다.
- PostgreSQL 스테이지를 하려면
psql클라이언트가 필요하다(./shoot doctor가 알려 준다). - 단답 채점의 허용 답안이 하나뿐인 문항이 남아 있어, 뜻이 같은 다른 표기를 오답 처리할 수 있다.
- 문항 벤더 표기가 전부
neutral인 은행이 2개 있다(01-beginner/01,03-advanced/06) —--dbms로 걸러도 이 은행은 항상 전부 나온다.
운영
- CI가 없다. 테스트 실행도, 벤더 브랜치 재생성도, 릴리스 발행도 전부 사람이 손으로 한다. 실행 코드가 외부 의존성 없는 Python 표준 라이브러리와 Bash뿐이라 유지할 파이프라인 자체가 얇다는 판단이다. 인스톨러가 늘어나면서 릴리스 전 점검 항목도 하나 늘었다.
- 인스톨러는 태그를 기다린다.
install.sh자체는raw.githubusercontent.com/.../main/install.sh에서 받으므로 스크립트 버그 수정은 즉시 반영되지만, 설치되는 내용은 최신 태그다. 그래서 이 릴리스를 발행한 직후 실제로 한 번 돌려 확인해야 한다.
요약
| v1.1.0 | v1.2.0 | |
|---|---|---|
| 챕터 | 31 | 31 |
| 문제은행 / 문항 | 23 / 216 | 23 / 216 |
| 스테이지 | 14 | 14 |
| 실행 진입점 | ./guide ./exam ./shoot |
동일 + install.sh |
| 설치 수단 | 없음(수동 clone) | 한 줄 설치·업데이트·제거 |
| 테스트 | 557 | 590 |
커밋 18개. 전체 변경 이력: https://github.com/Ahngbeom/dba-guide/commits/v1.2.0
호환성: 더해지기만 했다. 제거되거나 의미가 바뀐 CLI 인자, 스키마 변경, 진행·결과 기록 형식 변경, 챕터 경로 변경 모두 없다.