시작 오늘 분석할 코드
매 PHP 파일마다 PDO 접속 코드를 반복하는 대신, db_connect() 함수를 MYDB.php에 한 번만 작성하고 필요한 파일에서 require_once로 불러온다. 접속 정보가 바뀌어도 MYDB.php 한 파일만 수정하면 된다.
// MYDB.php — DB 접속 전용 파일 <?php function db_connect() { $db_user = "root"; $db_pass = ""; $db_host = "localhost"; $db_name = "sampledb"; $db_type = "mysql"; $dsn = "$db_type:host=$db_host;dbname=$db_name;charset=utf8"; try { $pdo = new PDO($dsn, $db_user, $db_pass); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); } catch (PDOException $e) { die('오류: ' . $e->getMessage()); } return $pdo; // PDO 객체를 반환 } ?>
사용하는 쪽 — require_once로 불러와 함수 호출
// view.php, list.php 등 어느 파일에서나 동일하게 require_once("MYDB.php"); // 파일 포함 (중복 포함 방지) $pdo = db_connect(); // 함수 호출 → PDO 객체 반환 // 이후 $pdo로 prepare/execute 등 동일하게 사용 $stmh = $pdo->prepare($sql);
실제 구조 미리보기
MYDB.php
function db_connect()
PDO 접속 정보
setAttribute 설정
return $pdo
←
// view.php
require_once("MYDB.php");
$pdo = db_connect();
// list.php
require_once("MYDB.php");
$pdo = db_connect();
// update.php
require_once("MYDB.php");
$pdo = db_connect();
접속 정보가 바뀌면 MYDB.php 한 파일만 수정 — 나머지는 자동으로 반영됨
용어 핵심 용어 정리
require_once지정 파일을 포함. 같은 파일을 두 번 포함해도 한 번만 실행되도록 보장
함수 분리반복되는 코드를 함수로 감싸 별도 파일에 두는 패턴 — 재사용성·유지보수성 향상
return $pdo함수 내부에서 생성된 PDO 객체를 호출부로 반환. 반환값을 변수에 받아 사용
캡슐화접속 상세 정보(DSN, 사용자명, 비번)를 함수 내부에 숨겨 외부에서 보이지 않게 함
include파일을 포함하되 없어도 경고만 출력하고 계속 실행. require는 없으면 치명적 에러로 중단
PDO 객체new PDO()로 생성된 DB 연결 객체. prepare/execute/beginTransaction 등의 메서드를 가짐
단일 책임각 파일이 한 가지 역할만 담당 — MYDB.php는 접속만, view.php는 표시만
DRY 원칙Don't Repeat Yourself. 같은 코드를 반복하지 않는다 — 함수 분리의 근본 동기
1 왜 접속 코드를 함수로 감싸는가
이전 코드에서는 view.php, list.php, update.php 각각에 PDO 접속 코드 10여 줄이 복사되어 있었다. DB 비밀번호가 바뀌면 모든 파일을 수정해야 한다. 함수로 감싸면 db_connect() 호출 한 줄로 PDO 객체를 얻을 수 있고, 접속 정보는 MYDB.php 한 곳에만 존재한다.
분리 전 — 각 파일에 반복
// view.php, list.php, update.php 각각에...
$db_user = "root";
$db_pass = "";
$db_host = "localhost";
$db_name = "sampledb";
$dsn = "$db_type:host=...";
$pdo = new PDO($dsn, ...);
$pdo->setAttribute(...);
× 3곳에 동일 코드
분리 후 — MYDB.php 한 곳에
// MYDB.php
function db_connect() { ... }
// 나머지 파일들
require_once("MYDB.php");
$pdo = db_connect();
○ 접속 정보 1곳에만 존재
2 function db_connect() — 왜 return $pdo인가
함수 안에서 생성된 $pdo는 함수 스코프에 갇혀 있다. 함수가 끝나면 사라진다. return $pdo를 해야만 호출한 쪽에서 PDO 객체를 받아 사용할 수 있다. 이것이 "함수가 값을 돌려준다"는 return의 역할이다.
function db_connect() { $pdo = new PDO(...); // 함수 스코프 안에서 생성 ... return $pdo; // 호출한 쪽으로 PDO 객체 반환 } // 호출하는 쪽 $pdo = db_connect(); // 반환된 PDO 객체를 $pdo에 저장
⚠ return 없이 함수를 끝내면 호출부의 $pdo는 null이 된다. 이후 $pdo->prepare()를 호출하면 "Call to a member function prepare() on null" 에러가 발생한다.
3 require_once vs include — 4가지 차이
| 구분 |
파일 없을 때 |
중복 포함 |
적합한 상황 |
require |
Fatal Error — 스크립트 중단 |
매번 포함 |
없으면 안 되는 핵심 파일 |
require_once |
Fatal Error — 스크립트 중단 |
한 번만 포함 |
DB 접속, 설정 파일 — 가장 안전 |
include |
Warning — 계속 실행 |
매번 포함 |
없어도 되는 선택적 파일 |
include_once |
Warning — 계속 실행 |
한 번만 포함 |
선택적이지만 중복 방지 필요 시 |
※ MYDB.php처럼 함수 정의가 들어있는 파일에 require_once를 쓰는 이유: 같은 함수를 두 번 정의하면 PHP가 에러를 발생시키기 때문이다. _once가 중복 포함을 막아준다.
4 함수 안에서 die() — 왜 접속 실패 시 바로 중단하는가
DB 접속에 실패하면 이후 모든 쿼리가 의미없다. die()는 지정된 메시지를 출력하고 PHP 실행을 즉시 중단시킨다. catch 블록에서 die()를 쓰면 접속 실패 원인을 바로 화면에 표시하고 다음 코드로 넘어가지 않는다.
catch (PDOException $e) { die('오류: ' . $e->getMessage()); // getMessage()는 "SQLSTATE[HY000] [1045] Access denied..." 등 상세 에러 반환 // die() 이후 코드는 실행되지 않음 }
⚠ 실제 서비스에서는 에러 메시지를 화면에 그대로 출력하면 DB 구조가 노출된다. 로그 파일에 기록하고 사용자에게는 "잠시 후 다시 시도해주세요" 같은 메시지를 보여주는 것이 바람직하다.
5 DSN 문자열 내 변수 보간 — 왜 큰따옴표를 쓰는가
PHP에서 큰따옴표 문자열 안에 변수를 쓰면 변수 값으로 자동 치환된다. "$db_type:host=$db_host;dbname=$db_name"은 변수들이 실제 값으로 교체된 DSN 문자열이 된다. 작은따옴표를 쓰면 변수가 그대로 텍스트로 출력되어 DSN이 깨진다.
$db_type = "mysql"; $db_host = "localhost"; $db_name = "sampledb"; // 큰따옴표 — 변수 보간 발생 $dsn = "$db_type:host=$db_host;dbname=$db_name;charset=utf8"; // 결과: "mysql:host=localhost;dbname=sampledb;charset=utf8" ✓ // 작은따옴표 — 변수가 그대로 $dsn = '$db_type:host=$db_host;dbname=$db_name;charset=utf8'; // 결과: "$db_type:host=$db_host;dbname=$db_name;charset=utf8" ✗
6 함수 스코프 — 왜 함수 안에서 선언한 변수는 밖에서 쓸 수 없는가
db_connect() 안의 $db_user, $pdo 등은 함수 실행이 끝나면 사라진다. PHP 함수는 기본적으로 자체 스코프를 가진다. return $pdo가 없다면 함수 바깥에서 $pdo에 접근할 방법이 없다. 이것은 버그가 아니라 의도된 설계 — 함수 내부 구현을 외부로부터 격리한다.
함수 분리 패턴이 주는 3가지 이점
- 단일 수정 포인트: DB 비밀번호·호스트가 바뀌어도 MYDB.php 한 줄만 수정
- 중복 제거: 10줄짜리 접속 코드가 모든 파일에서 1줄(db_connect())로 줄어듦
- 테스트 용이: 접속 함수만 따로 테스트하거나 Mock으로 교체하기 쉬움
7 자주 하는 실수
| 실수 |
증상 |
해결 |
| return $pdo 누락 |
$pdo = db_connect() 결과가 null — prepare() 호출 시 Fatal Error |
함수 마지막 줄에 반드시 return $pdo 추가 |
| require 대신 include 사용 |
MYDB.php 경로가 틀려도 경고만 출력하고 계속 실행 — null PDO로 에러 연쇄 |
접속 파일은 require_once 사용 — 없으면 즉시 중단이 안전 |
| _once 없이 require 반복 |
같은 함수가 두 번 정의되어 "Cannot redeclare db_connect()" Fatal Error |
require_once로 중복 포함 방지 |
| DSN에 작은따옴표 사용 |
변수가 보간되지 않아 "$db_type:host=..." 그대로 DSN 전달 — 접속 실패 |
DSN 문자열은 큰따옴표로 작성 |
| MYDB.php 경로 오류 |
require_once 실패 — Fatal Error: Failed opening required |
상대경로(같은 폴더는 "MYDB.php") 또는 절대경로(__DIR__."/MYDB.php") 사용 |
핵심 한 줄 요약
함수 분리 이유접속 코드 반복 제거 — 정보가 바뀌어도 MYDB.php 한 곳만 수정
return $pdo함수 안 변수는 밖에서 못 씀 — return으로 PDO 객체를 호출부로 전달
require_once없으면 Fatal Error로 즉시 중단 + 중복 포함 방지 — 접속 파일에 가장 적합
die()접속 실패 시 즉시 중단 — 이후 코드가 null PDO로 연쇄 에러 나는 것을 방지
큰따옴표 DSN변수 보간으로 실제 값 치환 — 작은따옴표 쓰면 변수 그대로 전달돼 접속 실패
Tags
#PDO #PHP #MySQL #함수분리 #require_once #db_connect #재사용 #캡슐화 #MYDB #접속함수 #DRY원칙 #PHP학습 #웹개발 #티스토리
▼ 티스토리 태그 입력란 복사용
PDO, PHP, MySQL, 함수분리, require_once, db_connect, 재사용, 캡슐화, MYDB, 접속함수
댓글