반응형
Web Development · PHP HTML 동적 생성
PHP로 SELECT 옵션 만들기 —
배열 → HTML 동적 생성
.= 누적 연산자 · 백슬래시 이스케이프 · 변수 치환의 종합 패턴
시작 오늘 분석할 코드
앞 예제(prefecture1.php)가 단순 출력이라면, 이번엔 같은 배열로 HTML <select> 드롭다운을 만든다. 변수에 HTML을 차곡차곡 누적해서 마지막에 한 번에 출력하는 패턴이다.
<?php $PrefectureList = array("서울특별시","부산광역시", ... ,"황해도"); $html = "<SELECT name=\"prefecture\" >\n"; for($i = 0; $i <= count($PrefectureList) - 1; $i ++){ $html .= "<OPTION value=\"$i\">$PrefectureList[$i]</OPTION>\n"; } $html .= "</SELECT>\n"; print $html; ?>
실제 출력 미리보기
→ 사용자에게는 "서울특별시"가 보이고, 폼이 서버로 전송되면 value="0"이 전송된다.
용어 용어 정리
.=문자열 누적 연산자 — $a .= $b는 $a = $a . $b
\"큰따옴표 안에서 큰따옴표를 쓰기 위한 이스케이프
\n줄바꿈 — 화면이 아닌 HTML 소스에서
변수 치환큰따옴표 안의 $변수가 값으로 자동 치환
SELECT드롭다운 폼 컨테이너
OPTION드롭다운의 한 항목
value서버로 전송될 실제 값
name폼 데이터의 키 이름
1
.= 누적 연산자.이 문자열 연결 연산자라면, .=는 "오른쪽 값을 왼쪽 변수 끝에 붙이고 결과를 다시 왼쪽에 저장"하는 단축형이다. 자바스크립트의 +=와 비슷한 역할이다.
$html = "A"; // $html = "A" $html .= "B"; // $html = "AB" $html .= "C"; // $html = "ABC" // 위와 동일한 의미 $html = "A"; $html = $html . "B"; // = "AB" $html = $html . "C"; // = "ABC"
왜 누적해서 한 번에 출력? → ① 디버깅 쉬움 (중간 결과 확인 가능) ② 출력 순서 제어 ③ 함수에서 반환 가능 ④ 캐싱·재사용 가능
2 백슬래시 이스케이프 —
\"큰따옴표 문자열 안에 큰따옴표를 쓰려면 PHP가 헷갈린다. 어디까지가 문자열인지 모르기 때문이다. 백슬래시를 앞에 붙이면 "이건 닫는 따옴표가 아니라 글자야"라고 알려준다.
// 잘못된 예 $html = "<SELECT name="prefecture">"; ^ ^ 문자열 여기서 끝났다고 PHP가 착각 → Parse error // 올바른 예 $html = "<SELECT name=\"prefecture\">"; ↑ ↑ "이 따옴표는 글자입니다"라고 알려줌
| 이스케이프 | 의미 | 큰따옴표 / 작은따옴표 |
|---|---|---|
\" |
큰따옴표 글자 | 큰따옴표에서만 필요 |
\\ |
백슬래시 글자 | 둘 다 가능 |
\n |
줄바꿈 | 큰따옴표에서만 동작 |
\t |
탭 | 큰따옴표에서만 동작 |
\$ |
$ 글자 (변수 치환 막음) | 큰따옴표에서만 필요 |
3 큰따옴표 vs 작은따옴표
PHP의 두 따옴표는 동작이 다르다. 큰따옴표는 변수를 자동 치환하고, 작은따옴표는 글자 그대로 다룬다. 본 코드는 $i·$PrefectureList[$i]를 치환해야 하므로 큰따옴표를 쓴다.
큰따옴표 "..."
- 변수 자동 치환 (
$i→ 실제 값) \n,\t등 이스케이프 동작- 약간 느림 (PHP가 내용을 파싱)
작은따옴표 '...'
- 변수 치환 안 함 (
$i가 글자 그대로) \n은 글자 \n 그대로- 약간 빠름
$i = 5; print "값: $i\n"; // "값: 5\n" (개행됨) print '값: $i\n'; // "값: $i\n" (글자 그대로)
반응형
4
$PrefectureList[$i] — 큰따옴표 안 배열 접근PHP 큰따옴표 안에서 배열 요소를 쓰는 두 가지 형태가 있다.
// 1) 단순 형태 (따옴표 없이 인덱스만) "$PrefectureList[$i]" // ✓ 동작함. 단, 키에 따옴표 못 씀 // 2) 중괄호 형태 (가장 안전) "{$PrefectureList[$i]}" // ✓ 모든 경우 동작. 명확함 // 3) 작동 안 하는 형태 "$PrefectureList[\"key\"]" // ✗ Parse error
실무에서는 헷갈리지 않게 {$arr[$key]} 중괄호 형태를 권장한다. 키가 문자열이든 숫자든 모두 안전.
5 SELECT 동적 생성의 흐름
[ 시작 ] $html = "<SELECT name=\"prefecture\">\n" ↓ ┌─── for 반복 (i = 0 ~ 21) ───┐ │ │ │ $html .= "<OPTION ...>...</OPTION>\n" │ │ │ └──────────────────────────────┘ ↓ $html .= "</SELECT>\n" ↓ print $html; ← 완성된 HTML을 한 번에 출력
최종적으로 $html에는 다음과 같은 문자열이 만들어진다.
<SELECT name="prefecture" > <OPTION value="0">서울특별시</OPTION> <OPTION value="1">부산광역시</OPTION> ... (총 22줄) <OPTION value="21">황해도</OPTION> </SELECT>
6 화면 표시 vs 실제 전송 값
이 패턴의 핵심은 "보이는 것과 저장되는 것이 다르다"는 점이다.
| 속성 | 역할 | 본 코드 예 |
|---|---|---|
| OPTION 태그 안 텍스트 | 사용자에게 보이는 글자 | "서울특별시" |
value 속성 |
서버로 전송되는 실제 값 | "0" |
name 속성 |
폼 데이터의 키 (서버 측 변수명) | $_POST["prefecture"] |
예: 사용자가 "부산광역시"를 선택 → 폼 제출 → 서버는
$_POST["prefecture"] = "1"을 받음. 인덱스 번호로 받아 처리하는 패턴.7 자주 하는 실수와 보안
| 실수 | 증상 | 해결 |
|---|---|---|
| 큰따옴표 안 큰따옴표 미 이스케이프 | Parse error | 반드시 \" |
| 작은따옴표 안에 변수 사용 | 변수가 글자로 출력 | 큰따옴표로 바꾸거나 . 연결 |
| 한 번씩 print로 출력 | 흐름 디버깅 어려움 | 변수에 누적 후 한 번 print |
| 사용자 입력 데이터를 그대로 HTML에 삽입 | XSS 취약점 | htmlspecialchars()로 이스케이프 |
닫는 태그 누락 (</SELECT>) |
레이아웃 깨짐 | 여는·닫는 태그 짝 맞추기 |
※ XSS 방어: 본 코드는 배열이 하드코딩이라 안전하지만, 만약 DB나 사용자 입력에서 받은 값이라면 반드시 이스케이프해야 한다.
$html .= "<OPTION value=\"$i\">" . htmlspecialchars($PrefectureList[$i]) . "</OPTION>";8 같은 결과를 더 깔끔하게 — foreach + heredoc
// 개선판 $html = "<select name=\"prefecture\">\n"; foreach($PrefectureList as $i => $name){ $safe = htmlspecialchars($name); $html .= " <option value=\"$i\">$safe</option>\n"; } $html .= "</select>\n"; echo $html;
※ 개선 포인트
foreach로 인덱스($i)와 값($name)을 한 번에 받음count()호출 없음htmlspecialchars()로 XSS 방어- HTML 태그는 소문자 권장 (HTML5 표준)
핵심 한 줄 요약
.=문자열 끝에 누적 (= $a . $b를 $a에 저장)
\"큰따옴표 안 큰따옴표 이스케이프
\n소스코드 줄바꿈 (큰따옴표에서만)
큰따옴표$변수 자동 치환됨
value vs 텍스트전송되는 값 / 사용자에게 보이는 값
{$arr[$i]}배열 접근의 가장 안전한 표기
XSS 방어사용자 데이터에는 htmlspecialchars() 필수
반응형
'php' 카테고리의 다른 글
| PHP while 반복문 — 조건이 참인 동안 반복하는 선검사 루프 (0) | 2026.06.12 |
|---|---|
| PHP switch 조건문 — case/break/default 완전 정리 (1) | 2026.06.12 |
| PHP for + count() — 배열 길이만큼 반복하는 패턴 완전 정리 (0) | 2026.06.12 |
| PHP 중첩 if-else — type 분기로 배우는 다중 분기 완전 정리 (0) | 2026.06.12 |
| PHP if-else — 로그인 성공/실패 분기 처리 완전 정리 (0) | 2026.06.12 |
왕진 블로그

댓글