본문 바로가기

비개발자의 개발 일지

현장 팀장에서 수출 ERP까지 — AI와 함께 시스템을 만든 기록

시리즈 보기
php

PHP 런타임 상태 완전 정리 — 클래스가 메모리에서 실행되는 순간

by 왕진 2026. 7. 12.
반응형

 

 

Web Development · PHP OOP

PHP 런타임 상태 완전 정리

클래스가 메모리에서 실행되는 순간 — 오버라이딩이 런타임에 결정되는 이유
시작 런타임이란 무엇인가

클래스를 작성하는 것은 "설계도를 그리는 것"이다. 그 설계도가 실제로 메모리에 올라가고 객체가 생성되어 메서드가 실행되는 순간을 런타임(Runtime)이라고 부른다. 오버라이딩된 메서드가 어느 클래스 버전으로 실행될지는 코드를 쓸 때(컴파일타임)가 아니라, 실제로 객체가 만들어지는 런타임에 결정된다.

class User { private $name = null; public function print_hello() { print $this->name . " 님, 안녕하세요!"; } } class Guest extends User { private $name = "게스트"; public function print_hello() { // 오버라이딩 print $this->name . " 님, 반갑습니다!"; } } $newuser = new Guest(); // 런타임에 Guest 객체 생성 $newuser->print_hello(); // 런타임에 Guest 버전 메서드가 선택됨
실제 출력 미리보기
게스트 님, 반갑습니다!

→ new Guest()로 생성된 객체이므로, 런타임에 Guest::print_hello()가 선택되어 실행된다

용어 핵심 용어 정리
런타임프로그램이 실제로 실행되는 시점. 객체 생성·메서드 호출·값 저장이 여기서 일어난다
컴파일타임코드를 작성·해석하는 시점. PHP는 요청 처리 전에 파싱하는 단계가 이에 해당
오버라이딩자식 클래스에서 부모와 같은 이름의 메서드를 재정의. 런타임에 자식 버전이 선택됨
동적 바인딩어떤 메서드를 실행할지 런타임에 결정하는 방식. 오버라이딩의 핵심 메커니즘
다형성같은 메서드 이름이 객체 타입에 따라 다르게 동작하는 OOP 특성
메모리 할당new 키워드 실행 시 객체를 위한 메모리 공간이 실제로 확보되는 것
런타임 상태객체가 메모리에 살아있고 멤버변수에 값이 담겨 있는 실행 중의 상태
extendsPHP 수직상속 키워드. 자식이 부모의 메서드·변수를 물려받는다
instanceof런타임에 객체가 특정 클래스의 인스턴스인지 확인하는 연산자. $obj instanceof User가 true면 User 클래스 또는 그 자식 클래스의 객체
런타임 에러코드 파싱 후 실행 중에 발생하는 오류. undefined method, class not found 등. 컴파일타임에는 잡지 못한다

1 런타임 vs 컴파일타임 — 언제 무엇이 결정되나
코드를 쓰는 순간과 실행하는 순간은 다르다

$newuser->print_hello()라는 코드를 보면 어떤 클래스의 메서드가 실행될지 그 자리에서 알 수 없다. $newuser가 User 객체인지 Guest 객체인지는 new가 실행되는 런타임에야 확정된다. PHP는 요청이 들어오면 코드를 파싱하고, 실제로 라인을 실행하는 것이 런타임이다.

컴파일타임 (파싱 단계)
클래스 구조 확인, 문법 오류 감지.
어떤 객체가 만들어질지, 어떤 값이 들어올지는 모른다.
런타임 (실행 단계)
new Guest() → 메모리에 Guest 객체 생성.
print_hello() 호출 → Guest 버전 메서드 선택·실행.
※ 오버라이딩이 강력한 이유: 코드는 부모 타입을 쓰도록 짜도, 런타임에 자식 객체가 들어오면 자식 동작으로 자동 전환된다.

2 오버라이딩과 런타임 선택 원리
부모와 자식이 같은 메서드 이름을 가질 때 무엇이 실행되나

자식 클래스가 부모와 동일한 이름의 메서드를 재정의하면, 런타임에 해당 객체의 실제 타입을 기준으로 메서드를 선택한다. $newuser = new Guest()라면 $newuser->print_hello()는 부모(User)의 메서드가 아니라 자식(Guest)의 메서드를 실행한다.

class User { public function print_hello() { print "User 버전: 안녕하세요!"; } } class Guest extends User { public function print_hello() { // 오버라이딩 print "Guest 버전: 반갑습니다!"; } } $a = new User(); $a->print_hello(); // → "User 버전: 안녕하세요!" (런타임에 User 선택) $b = new Guest(); $b->print_hello(); // → "Guest 버전: 반갑습니다!" (런타임에 Guest 선택)

3 런타임 상태 — 객체가 메모리에 살아있는 동안
new 부터 스크립트 종료까지가 런타임 상태다

new Guest()가 실행되는 순간 메모리에 Guest 객체가 올라간다. 이 객체의 멤버변수에 값이 저장되고, 메서드가 호출되는 이 전체 구간이 "런타임 상태"다. 실무에서 "Guest 클래스의 객체가 런타임 상태에서 메서드 오버라이딩을 해서 Guest 클래스의 메서드를 실행한다"는 표현이 이 개념을 가리킨다.

1
파싱 (컴파일타임)PHP 엔진이 코드를 읽고 클래스 구조를 파악. 아직 객체는 없음
2
new Guest() 실행런타임 시작 — Guest 객체가 메모리에 할당됨. $name = "게스트" 초기화
3
메서드 호출$newuser->print_hello() — 런타임에 객체 타입(Guest) 확인 → Guest::print_hello() 선택
4
실행 완료"게스트 님, 반갑습니다!" 출력. 오버라이딩된 자식 메서드가 실행됨
5
스크립트 종료PHP 요청 처리 완료 — 객체가 메모리에서 해제됨 (런타임 상태 종료)
파싱
new 객체 생성
메서드 호출
런타임 선택
실행·종료

 

반응형

 

4 다형성(Polymorphism) — 런타임의 실용적 의미
같은 코드로 다른 동작을 이끌어내는 OOP의 핵심

다형성은 "같은 메서드 이름이 객체 타입에 따라 다르게 동작하는 것"이다. 함수에 User 타입을 기대하고 작성하더라도, 런타임에 Guest 객체가 들어오면 Guest 버전의 메서드가 자동으로 실행된다. 이 덕분에 새로운 자식 클래스를 추가해도 호출하는 코드를 바꿀 필요가 없다.

function greet(User $user) { // User 타입을 기대 $user->print_hello(); // 런타임에 실제 타입으로 선택됨 } greet(new User()); // → "안녕하세요!" (User 버전) greet(new Guest()); // → "반갑습니다!" (Guest 버전) // greet() 함수는 하나지만 런타임에 다른 동작이 나온다
※ 새로운 VIPGuest 클래스를 만들어도 greet()는 그대로 쓸 수 있다. 이것이 다형성의 실용적 이점이다.

다형성은 "미래에 추가될 코드에 현재의 코드가 열려 있다"는 것을 의미한다. 확장할 때마다 기존 코드를 고치지 않아도 되는 구조가 런타임 선택과 오버라이딩으로 가능해진다.


5 private 변수와 상속 — 런타임에서의 독립성
부모의 private은 자식이 접근할 수 없다

부모 클래스의 private $name은 자식 클래스에서 상속되지 않는다. 자식 클래스가 같은 이름의 private $name을 다시 선언하면 독립된 변수가 된다. 런타임에 Guest 객체의 $this->name은 Guest 자신이 선언한 "게스트" 값을 가리킨다.

class User { private $name = null; // User만의 private — Guest에서 접근 불가 } class Guest extends User { private $name = "게스트"; // Guest만의 독립 변수 — 부모와 완전히 별개 public function print_hello() { print $this->name; // 런타임에 Guest의 $name = "게스트" } }
⚠ protected를 쓰면 자식이 부모의 변수에 접근 가능. private은 완전히 자기 클래스만 접근 가능하다.

6 parent:: — 부모 메서드를 명시적으로 호출하기
오버라이딩해도 부모 로직을 살려두고 싶을 때

자식 클래스가 메서드를 오버라이딩하면 부모 버전은 기본적으로 실행되지 않는다. 그런데 부모의 동작을 그대로 쓰면서 추가 기능만 붙이고 싶을 때는 parent::메서드명()으로 부모 버전을 명시적으로 호출할 수 있다.

class Guest extends User { public function print_hello() { parent::print_hello(); // 부모 버전도 실행 print "(Guest 추가 메시지)"; } }
※ parent::를 쓰면 부모 메서드를 완전히 대체하지 않고 "확장"하는 형태로 오버라이딩할 수 있다.

7 instanceof — 런타임에 객체 타입을 확인하는 연산자
어떤 클래스의 객체인지 실행 중에 판별하기

instanceof는 런타임에 변수가 특정 클래스 또는 그 자식 클래스의 인스턴스인지 확인한다. 오버라이딩된 메서드가 어떤 버전으로 실행될지 판단하거나, 타입에 따라 분기 처리할 때 사용한다.

$newuser = new Guest(); var_dump($newuser instanceof Guest); // true — Guest 객체이므로 var_dump($newuser instanceof User); // true — Guest는 User의 자식이므로 // 타입에 따른 분기 처리 if ($newuser instanceof Guest) { print "게스트 전용 메시지 출력"; }
※ instanceof는 상속 체인을 고려한다. Guest extends User이면 $g instanceof User도 true를 반환한다. 다형성과 함께 자주 사용되는 런타임 타입 체크 도구다.

8 자주 하는 실수
실수 증상 해결
부모 메서드가 실행될 거라 예상했는데 자식 메서드가 실행됨 예상 밖의 출력 또는 동작 오버라이딩 확인. new로 생성한 객체 타입이 자식이면 자식 메서드가 실행됨
자식에서 부모의 private 변수에 $this->로 접근 null 또는 undefined 경고 부모의 private은 자식에서 접근 불가. protected로 변경하거나 getter 사용
클래스만 정의하고 new를 안 씀 메서드가 실행되지 않음 런타임 상태는 new로 객체를 생성해야 시작됨
오버라이딩 후 부모 로직이 사라짐 기존 기능이 누락됨 parent::메서드명()으로 부모 버전을 명시적으로 호출
런타임 vs 컴파일타임 혼동 오류 발생 위치 파악 어려움 파싱 오류=컴파일타임, 실행 중 오류=런타임으로 구분

핵심 한 줄 요약

런타임new로 객체가 메모리에 올라가 메서드가 실행되는 시점
오버라이딩 선택 시점코드를 쓸 때가 아니라 런타임에 객체 타입을 보고 결정됨
다형성같은 메서드 이름, 다른 동작 — 자식 객체가 들어오면 자식 버전이 자동 선택
private과 상속부모의 private은 자식에서 접근 불가 — 자식이 같은 이름 선언 시 독립 변수
parent::오버라이딩하면서도 부모 메서드 로직을 살릴 때 명시적으로 호출
instanceof런타임에 객체 타입 확인 — 상속 체인도 포함해서 판별함

Tags

#PHP 런타임 #런타임 상태 #메서드 오버라이딩 #다형성 #PHP OOP #동적 바인딩 #컴파일타임 #PHP 클래스 상속 #extends #PHP 객체지향 #웹개발 #티스토리
▼ 티스토리 태그 입력란 복사용
PHP 런타임, 런타임 상태, 메서드 오버라이딩, 다형성, PHP OOP, 동적 바인딩, 컴파일타임, PHP 클래스 상속, extends, PHP 객체지향
반응형

댓글