문을 하나만 열어 두기 — PHP 라우터 사이트 보안 팁 정리

2026.10.31 10:11

이번엔 말하는 법이 아니라 막는 법

지금까지 만든 툴은 전부 "AI에게 정확히 말하기"였다. 화면은 UI 용어 75, 에러는 에러 디버깅 프롬프트 변환기, 저장·로그인·배포는 백엔드·배포 용어 60.

이번 건 결이 조금 다르다. 나는 PHP로 작업하고, 라우터 방식을 고집한다. 모든 요청을 index.php 하나로 받고, 거기서 주소를 보고 할 일을 나눈다. AI에게 기능을 시키면 기능은 잘 만들어 준다. 그런데 "이 파일을 주소로 직접 열 수 있나?", "업로드 폴더에서 PHP가 실행되나?" 같은 건 내가 먼저 말하지 않으면 빠지기 쉽다.

그래서 이 방식으로 사이트를 만들 때 챙기는 것들을 한 화면에 정리했다.


문이 하나면, 검사도 한 곳에서

라우터 방식의 보안은 한 문장으로 요약된다. 밖에서 들어오는 문은 index.php 하나뿐이고, 나머지 PHP 파일은 주소로 직접 열리지 않아야 한다.

문이 하나면 로그인 검사, 권한 검사, CSRF 검사를 그 문 뒤에 한 번만 세우면 된다. 반대로 /app/admin/delete.php처럼 내부 파일이 주소로 열리면, 라우터에 아무리 꼼꼼하게 검사를 넣어 놔도 그 파일은 검사를 건너뛴다. 직접 URL 접속 차단이 중요한 이유가 이거다.


그래서 정리한 것: PHP 라우터 사이트 보안 팁

PHP 라우터 사이트 보안 팁 — mifplus.com/tools/php-router-security

원칙 하나, 팁 7가지, 배포 전 체크 15개로 묶었다. 설정과 코드는 전부 복사 버튼이 붙어 있어서 그대로 가져다 쓸 수 있다.


요청을 직접 보내 보는 흐름도

툴 맨 앞에는 이 흐름도를 넣었다. 글로 "웹서버에서 막고, 라우터에서 막고, 미들웨어에서 막는다"고 쓰면 금방 잊는다. 그래서 요청을 골라 보내면 어디서 멈추는지 눈으로 보게 했다.

보내 본 요청어디서결과
GET /assets/site.css웹서버200, PHP 실행 없이 파일 그대로
GET /.env웹서버404
GET /app/admin/delete.php웹서버404
GET /uploads/shell.php웹서버404
GET /backup-2024라우터404 (허용 목록에 없음)
GET /admin/post/5/delete (관리자)라우터405 (POST만 허용)
GET /admin/dashboard (로그아웃)미들웨어404
POST /admin/post/5/delete (토큰 없음)미들웨어419 (CSRF 토큰 불일치)
POST /admin/post/5/delete (관리자·토큰)통과200

막은 주소에 403이 아니라 404를 돌려주는 것도 일부러다. 403은 "거기 뭔가 있다"는 대답이라서, 없는 주소와 똑같이 보이게 하는 편이 낫다.


7가지 팁

  1. 웹 루트는 public 폴더만 — 설정보다 위치가 확실하다. app/, config/, .env가 웹 루트 밖에 있으면 주소 자체가 없다.
  2. 직접 URL 접속 차단 — 숨김 파일, 백업 확장자, 폴더 목록, 업로드 폴더의 PHP 실행을 웹서버에서 막는다. 내 웹서버에서 Apache와 Nginx를 고르면 그 설정만 보여 준다.
  3. 라우터 코드 — 허용 목록으로만 라우팅하고, 주소로 파일을 고르는 include $_GET['page'] 같은 코드는 쓰지 않는다. /admin은 라우트 묶음 단위로 한 번에 검사한다.
  4. 입력은 의심하고, 출력은 감싸기 — SQL은 PDO 자리표시자, 출력은 htmlspecialchars, POST는 CSRF 토큰, 업로드는 내용 검사와 새 이름.
  5. 로그인과 세션 — password_hash, 로그인 직후 session_regenerate_id(true), 쿠키 옵션, 시도 횟수 제한.
  6. 서버 설정과 보안 헤더 — 운영 서버는 display_errors = Off, 버전 정보 숨기기, 기본 보안 헤더.
  7. 배포와 비밀 정보 — 서버에 .git, .bak, .sql, phpinfo.php를 남기지 않는다.

7번에는 주석 이야기도 넣었다. 배포할 때 주석을 지워야 하나 싶었는데, PHP 주석은 서버 밖으로 나가지 않으니 지울 필요가 없다. 대신 뷰 파일의 HTML 주석 <!-- -->은 그대로 브라우저로 간다. "TODO: 테스트 계정 test/1234" 같은 메모를 HTML 주석에 남기면 페이지 소스 보기로 누구나 본다.


배포 전 체크리스트

체크리스트는 대부분 주소창에 직접 넣어 보면 확인되는 것으로 골랐다. 진짜 도메인에서 하나씩 열어 보고 404가 나오면 통과다. 맨 위에 내 사이트 주소를 넣으면 항목마다 바로 열어 보는 링크가 생기고, 체크한 건 브라우저에 남아서 다음에 열어도 이어서 볼 수 있다.


AI에게 점검 맡기기

마지막에는 이 팁을 그대로 점검 기준으로 넘기는 요청문을 붙였다. "보안 점검해 줘"만 쓰면 일반론이 돌아오니까, 구조(PHP + 라우터, 웹서버 종류)와 점검 항목 10개를 같이 준다. 그리고 두 가지를 꼭 부탁한다.

  • 고치기 전에 항목별로 통과 / 문제 / 확인 불가를 표로 먼저 보여 달라
  • 문제는 한 번에 하나씩 고쳐 달라

보안 수정을 한꺼번에 맡기면 라우터나 로그인처럼 사이트 전체에 걸린 부분이 한 번에 바뀌어서, 뭐가 뭘 깨뜨렸는지 찾기 어렵다.


정리하며

앞의 세 툴이 "AI에게 정확히 말하기"였다면, 이번 건 "정확히 막기"다. 문을 하나만 열어 두고, 그 문 뒤에 검사를 세우고, 배포할 때마다 주소창으로 한 번씩 두드려 본다. 거창한 보안 도구보다 이 습관이 먼저라고 생각한다.

PHP로 라우터 방식 사이트를 만들고 있다면, 배포 버튼을 누르기 전에 체크리스트만이라도 한 번 훑어보면 좋겠다.

PHP 라우터 사이트 보안 팁: https://mifplus.com/tools/php-router-security
바이브 코딩 백엔드·배포 용어 60: https://mifplus.com/tools/backend-terms
에러 디버깅 프롬프트 변환기: https://mifplus.com/tools/debug-prompt
바이브 코딩 UI 필수 용어 75: https://mifplus.com/tools/vibe-ui
지난 글: "저장되게 해줘"로는 부족하다 — 바이브 코딩 백엔드·배포 용어 60개 정리

댓글 0

32HMU ↻
아직 댓글이 없습니다.