$_GET은 URL 쿼리 문자열의 배열이므로 article.php?id=42&lang=en은 $_GET['id'] === '42'와 $_GET['lang'] === 'en'을 줍니다. $_POST는 method="post"로 보낸 폼 필드의 배열입니다. 파라미터가 없으면 키도 없으므로 둘 다 기본값과 함께 읽으세요: $_GET['id'] ?? null.
블록을 실행한 다음 링크를 클릭하세요. 클릭할 때마다 링크의 쿼리 문자열로 채워진 $_GET과 함께 스크립트가 다시 실행됩니다.
$_GET['lang']은 출력한 세 링크만이 아니라 URL에 적힌 무엇이든 될 수 있습니다. 누구나 주소창에 ?lang=<script>를 입력할 수 있으며, 그래서 이 블록은 값을 출력하는 대신 $languages에서 찾고, 요청 데이터를 출력하는 유일한 곳은 이스케이프합니다.
쿼리 문자열에서 숫자 읽기
$_GET의 모든 값은 문자열입니다. 페이지 번호라면 filter_var()로 검증과 변환을 한 번에 하고, 값이 없거나 숫자가 아니거나 범위를 벗어나면 기본값으로 돌아가세요. 페이지를 넘겨 본 다음 Page 999와 Page abc 링크를 시도해 보세요.
filter_var()는 "3"에 대해 정수 3을, 그 밖의 문자열에 대해 default 옵션을 반환하므로 $page는 항상 쓸 수 있는 int입니다. 다른 검증기는 filter_var 페이지에 나열되어 있습니다.
$_POST로 폼 데이터 읽기
method="post"인 폼은 필드를 요청 본문으로 보내고, PHP는 각 입력의 name 아래 $_POST에 넣습니다. $_SERVER['REQUEST_METHOD']는 현재 요청이 첫 방문(GET)인지 전송(POST)인지 알려 줍니다. 폼을 채우고 Send를 눌러 둘 다 확인하세요.
빈 텍스트 입력도 ""로 전송되므로, 전송 후에는 방문자가 아무것도 입력하지 않았어도 $_POST['title']이 존재합니다. 서버에서는 REQUEST_METHOD가 항상 설정되어 있고, ?? 'GET'은 명령줄에서 php로 파일을 실행할 때 스크립트를 조용히 유지할 뿐입니다. 폼을 검증하고 다시 표시하는 전체 패턴은 폼 페이지에 있습니다.
method="get"인 검색 폼
결과가 공유 가능한 URL이어야 하는 폼, 예를 들어 검색창에는 GET을 쓰세요. 브라우저가 필드를 쿼리 문자열(?q=sort&level=beginner)로 바꾸고, 스크립트는 링크와 똑같이 $_GET에서 읽습니다. array나 string을 검색해 보세요.
http_build_query로 링크 만들기
"?q=$q&page=2"를 손으로 쓰면 $q에 공백, &, #이 들어가는 순간 깨집니다. http_build_query()는 모든 값을 인코딩해 주며, HTML 안에서 &는 &여야 하므로 결과가 href에 들어갈 때는 htmlspecialchars()를 거칩니다.
두 인수를 받는 parse_str()은 PHP가 쿼리 문자열로 $_GET을 만드는 방법이므로 테스트에 편리합니다. 항상 두 번째 인수를 넘기세요. 변수를 만들던 예전의 인수 하나짜리 형태는 PHP 8에서 제거되었습니다.
$_REQUEST와 피해야 하는 이유
$_REQUEST는 $_GET과 $_POST를 한 배열로 합친 것입니다. PHP가 제공하는 php.ini 파일은 request_order = "GP"를 설정하므로 둘에 같은 키가 있으면 POST가 이깁니다. 그 설정이 없으면 쿠키도 합쳐집니다.
<?php
// POST /save.php?id=1 with a form field id=2
echo $_GET['id']; // "1"
echo $_POST['id']; // "2"
echo $_REQUEST['id']; // "2"
편리해 보이지만 값이 어디서 왔는지 숨깁니다. $_REQUEST['id']로 레코드를 지우는 핸들러는 평범한 링크로도 실행될 수 있으며, 이는 POST 전용 동작이 막으려는 바로 그것입니다. 대신 $_GET이나 $_POST를 이름으로 읽으세요.
GET과 POST: 무엇을 쓸까
| GET | POST | |
|---|---|---|
| 데이터가 이동하는 곳 | URL 안: ?q=php&page=2 | 요청 본문 안 |
| 읽는 방법 | $_GET | $_POST |
| 북마크, 공유, 뒤로 가기 | 가능 | 불가(브라우저가 재전송을 묻습니다) |
| 길이 | URL에 의해 제한(수천 자는 안전) | post_max_size에 의해 제한(기본 8M) |
| 파일 업로드 | 불가 | 가능, enctype="multipart/form-data"와 함께($_FILES를 읽음) |
| 용도 | 검색, 필터, 정렬, 페이지 나누기 | 로그인, 가입, 저장, 삭제, 결제 |
중요한 규칙: GET 요청은 아무것도 바꾸면 안 됩니다. 브라우저는 링크를 미리 불러오고, 크롤러는 링크를 따라가며, 사람들은 링크를 공유하므로 ?delete=5 링크는 결국 지울 의도가 없던 무언가에 의해 열리게 됩니다. 두 방식 모두 그 자체로 암호화되지는 않습니다. HTTPS가 둘 다 보호하며, POST는 데이터를 URL, 브라우저 기록, 서버 로그에 남기지 않을 뿐입니다.
자주 묻는 질문
PHP에서 URL의 파라미터를 가져오려면 어떻게 하나요?
기본값과 함께 $_GET에서 읽으세요. page.php?id=42라면 $id = $_GET['id'] ?? null;이 문자열 "42"를 줍니다. 모든 값은 문자열(또는 id[]=의 경우 배열)이므로, 예를 들어 filter_var($id, FILTER_VALIDATE_INT)로 변환하고 검증하세요.
$_GET과 $_POST의 차이는 무엇인가요?
$_GET은 URL의 쿼리 문자열에서 오므로 보이고, 북마크할 수 있고, 길이가 제한됩니다. 검색, 필터, 페이지에 쓰세요. $_POST는 method="post"로 보낸 폼의 요청 본문에서 옵니다. 저장, 구매, 로그인처럼 데이터를 바꾸는 모든 것에 쓰세요.
PHP에서 GET 파라미터가 있는지 확인하려면 어떻게 하나요?
isset($_GET['q'])를 쓰세요. 키가 없거나 null이면 거짓입니다. 빈 값(?q=)도 없는 것으로 치려면 trim한 값을 비교하세요: trim($_GET['q'] ?? '') !== ''.
PHP에서 $_REQUEST를 써야 하나요?
대개는 아닙니다. $_REQUEST는 $_GET과 $_POST(그리고 request_order에 따라 쿠키)를 합치므로 값이 어디서 왔는지 알 수 없고, 폼에서 기대한 값을 링크가 공급할 수 있습니다. $_GET이나 $_POST를 명시적으로 읽으세요.
PHP에서 요청이 GET인지 POST인지 확인하려면 어떻게 하나요?
$_SERVER['REQUEST_METHOD']를 비교하세요: if ($_SERVER['REQUEST_METHOD'] === 'POST') { ... }. 버튼에 name이 없거나 JavaScript나 다른 스크립트가 그 필드 없이 폼을 보낼 때 실패하는 isset($_POST['submit'])보다 더 믿을 만합니다.