Lazy Loading(지연 로딩)이란?
Lazy Loading은 프로그램이 실행될 때 전체 데이터를 한꺼번에 로딩하지 않고, 접근이 실제로 발생했을 때 필요한 데이터만 메모리에 적재하는 전략입니다.
즉, "필요할 때까지 기다렸다가 불러오는 방식"입니다.
PintOS에서의 Lazy Loading
PintOS의 Project 3에서는 실행 파일 전체를 한 번에 메모리에 적재하던 기존의 load_segment() 방식을 개선하여,
실제 접근 시점에만 메모리에 로딩하는 Lazy Loading 기법이 도입됩니다.
Lazy Loading 방식 vs Eager Loading 방식 비교
| 항목 | Earger Loading | Lazy Loading |
| 데이터 로딩 시점 | 프로그램 실행 시 전체 적재 | 접근이 발생할 때만 적재 |
| 메모리 사용량 | 초기부터 높음 | 필요한 페이지만 적재해 효율적 |
| 실행 속도 | 초기 실행 빠름, 이후 메모리 부족 위험 | 초기엔 느리지만 전체적으로 효율 |
| 구현 난이도 | 구현 쉬움 | 어려워요....(설계 잘하셔야함) |
| Page Fault | 거의 없음 | 필연적으로 발생(정상 동작) |
| 디스크 접근 | 초기 한 번에 집중 | 필요할 때마다 디스크 접근 |
| 예시 코드 | load_segment() | vm_alloc_page_with_initializer() + lazy_load_segment() 등 |
Lazy Loading의 장점
- 메모리 효율성: 실제로 사용하는 페이지만 메모리에 올리므로 낭비가 적습니다.
- 대형 실행 파일에 유리: 전체 파일을 미리 다 올릴 필요가 없어 부담이 적습니다.
- 성능 향상 가능성: 자주 쓰이지 않는 데이터를 굳이 메모리에 올릴 필요가 없습니다.
Lazy Loading의 단점
- Page Fault 처리 부담: 접근 시마다 발생하는 Page Fault를 안정적으로 처리해야 합니다.
- 구현 복잡도 증가: Page 초기화, 디스크 I/O, 파일 매핑, 구조체 관리 등 고려 사항이 많습니다.
- I/O 과부하 위험: 페이지마다 디스크 접근이 빈번하게 발생할 수 있습니다.
Lazy Loading Flow Chart in PintOS
프로그램 실행
↓
load_segment() → vm_alloc_page_with_initializer()
↓
Page Fault 발생
↓
Page Fault Handler 동작
↓
lazy_load_segment() 실행 → 디스크에서 해당 페이지 로딩
↓
Page를 Frame에 적재 후 다시 실행
이 과정은 PintOS의 가상 메모리 시스템에서 Page의 초기 상태를 UNINIT으로 등록한 뒤,
실제 접근 시 initializer 함수를 호출하여 디스크에서 데이터를 읽고 메모리에 적재하는 방식으로 작동합니다.
보너스 : JPA(Hibernate)의 Lazy Loading과의 간단 비교
| 항목 | PintOS (OS 레벨) | JPA (백엔드 레벨) |
| 지연 대상 | 실행 파일 → 메모리 Page | DB → 연관 엔티티 |
| 트리거 | Page Fault | 프록시 객체 접근 |
| 장점 | 메모리 효율적, 빠른 시작 간으 | DB 쿼리 최적화, 성능개선 |
| 단점 | 구현 복잡도 ↑ | N + 1 문제, 예외 처리 필요 |
| 주요 함수/키워드 | lazy_load_segment() 등 | @ManyToOne(fetch = FetchType.LAZY) 등 |
마무리
PintOS에서의 Lazy Loading은 단순한 최적화 기법을 넘어, 운영체제의 메모리 효율성과 실행 성능을 결정짓는 핵심 전략입니다.
그리고 이 개념은 JPA와 같은 백엔드 프레임워크에서도 동일한 철학으로 활용됩니다.
Lazy Loading은 단지 "게으른 로딩"이 아닌, 똑똑한 로딩입니다.
언제 어떻게 로딩할지를 잘 설계한다면, 전체 시스템의 효율성과 안정성을 동시에 높일 수 있습니다.