앱 내부 저장소: 개념, 데이터 저장 방법 및 개발에서의 작동 방식

저자: IT Sectr 게시일: 2026-03-13 읽는 시간: 11 분

앱 내부 저장소는 격리된 저장소를 통해 특정 애플리케이션만 액세스할 수 있는 기기의 전용 공간입니다. Android Developers, 2026에 따르면, 각 애플리케이션은 고유한 샌드박스 디렉토리를 받으며 다른 애플리케이션은 직접 액세스할 수 없습니다. 이 접근 방식은 무단 읽기로부터 데이터를 보호하고 모바일 기기의 멀티태스킹 환경에서 안정적인 작동을 보장합니다.

주요 포인트

  • Internal Storage — 각 애플리케이션의 격리된 저장소, 다른 프로그램이 액세스 불가
  • 샌드박스 모델은 특별 권한 없이 다른 앱이 데이터를 읽을 수 없도록 보장
  • Android는 내부 저장소 액세스를 위해 Context.getFilesDir(), getCacheDir(), getDataDir() 제공
  • iOS는 앱 샌드박스 컨테이너에서 NSDocumentDirectoryNSCachesDirectory 사용
  • 자동 정리는 앱 제거 시 내부 저장소의 모든 데이터가 완전히 삭제되도록 보장

앱 내부 저장소란?

앱 내부 저장소는 운영 체제가 설치 시 각 애플리케이션에 할당하는 격리된 디렉토리입니다. 다른 애플리케이션과 사용자는 표준 파일 관리자를 통해 이 디렉토리에 액세스할 수 없습니다. 시스템은 애플리케이션이 제거될 때 이 디렉토리 내의 모든 데이터가 완전히 삭제되도록 보장합니다. 이 접근 방식은 모바일 운영 체제 보안 모델의 기초를 형성하여 프로그램 간 기밀 정보 유출을 방지합니다.

외부 저장소(SD 카드)와 달리 내부 저장소는 항상 사용 가능하며 미디어 존재 여부를 확인할 필요가 없습니다. 최신 기기의 NAND 플래시 메모리 읽기 및 쓰기 속도는 순차 읽기 800~900MB/s, 순차 쓰기 200~300MB/s에 도달하며 SATA SSD와 비슷합니다. 할당된 영역의 크기는 기기의 총 용량과 제조업체 정책에 따라 다릅니다. 64GB 플래시 메모리가 있는 기기에서 앱은 필요에 따라 확장 가능한 16~64MB의 초기 공간을 받습니다.

내부 저장소 아키텍처는 Android와 iOS 간에 다릅니다. Android에서 각 애플리케이션은 /data/data/<package_name>/ 디렉토리를 받으며, 그 안에 시스템이 files/, cache/, databases/ 하위 디렉토리를 만듭니다. iOS에서 애플리케이션은 Documents/, Library/, tmp/ 디렉토리가 있는 샌드박스 컨테이너에서 작동하며, 각각 고유한 목적과 백업 정책이 있습니다.

내부 메모리의 데이터 저장 방법

개발자는 앱 내부 저장소에 데이터를 저장하는 여러 방법을 사용할 수 있습니다. 각 방법은 특정 작업을 해결하고 특정 데이터 유형에 적합합니다. 올바른 방법을 선택하면 애플리케이션 성능, 개발 편의성 및 사용자 데이터 보안에 직접적인 영향을 미칩니다.

격리된 파일 저장소

가장 낮은 수준의 방법은 파일 디렉토리에 직접 파일을 쓰는 것입니다. 앱은 샌드박스 내에서 모든 파일과 디렉토리를 만들 수 있습니다. 이 방법은 미디어 파일, 사용자 문서 및 구조화된 구성이 필요하지 않은 모든 바이너리 데이터를 저장하는 데 적합합니다. Android에서는 Context.getFilesDir() 호출을 통해 디렉토리에 액세스하며, 앱의 파일 디렉토리 절대 경로를 반환합니다. iOS에서는 NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) 함수가 비슷한 목적을 수행합니다.

SharedPreferences 및 DataStore

키-값 쌍을 저장하기 위해 Android는 SharedPreferences와 Kotlin 코루틴 및 protobuf 프로토콜 기반의 더 현대적인 DataStore를 제공합니다. SharedPreferences는 /data/data/<package>/shared_prefs/ 디렉토리 내의 XML 파일에 데이터를 저장합니다. 단순함에도 불구하고 SharedPreferences에는 단점이 있습니다. 동기 쓰기는 UI 스레드에서 지연을 유발할 수 있으며, 타입 안전성 부족은 오류 위험을 증가시킵니다. DataStore는 Flow 기반 비동기 API와 protobuf 스키마를 통한 완전한 타입 지원을 제공하여 이러한 문제를 해결합니다.

SQLite 데이터베이스 및 Room

관계형 연결이 있는 구조화된 데이터에는 SQLite 또는 Room 래퍼가 최적의 선택입니다. 데이터베이스는 databases/ 디렉토리 내의 단일 파일에 저장되며 완전한 SQL 구문을 지원합니다. Room은 공식 Jetpack 라이브러리로, 타입 안전 API, 자동 스키마 마이그레이션 및 코루틴 지원을 제공합니다. 적절한 인덱싱을 통해 데이터베이스 크기는 성능 저하 없이 수 기가바이트에 도달할 수 있습니다. 모바일 기기의 SQLite는 최신 플래그십 프로세서에서 초당 최대 50,000회 쓰기 작업을 처리합니다.

EncryptedSharedPreferences

인증 토큰 및 암호화 키와 같은 기밀 데이터를 저장하기 위해 Android는 EncryptedSharedPreferences를 제공합니다. 표준 SharedPreferences를 래핑하는 이 기능은 AES256-GCM-None을 사용하여 키와 값을 자동으로 암호화합니다. 암호화는 디스크에 쓰기 전에 파일 수준에서 수행되므로 기기에 물리적으로 액세스하더라도 공격자가 내용을 읽을 수 없습니다. EncryptedSharedPreferences는 AndroidX Security 라이브러리의 일부이며, 전체 파일을 암호화하는 EncryptedFile도 포함합니다.

Android에서 내부 저장소 사용 방법

Android SDK는 Context 클래스를 통해 내부 저장소를 사용하는 다양한 메서드를 제공합니다. 각 메서드는 앱 샌드박스 내의 특정 시스템 디렉토리 경로를 반환합니다. Kotlin 예제를 사용하여 기본 파일 쓰기 및 읽기 작업을 살펴보겠습니다.

Context를 통한 filesDir 액세스

내부 파일 디렉토리 경로를 가져오는 주요 메서드는 context.filesDir입니다. /data/data/<package>/files/ 디렉토리를 가리키는 File 객체를 반환합니다. 첫 액세스 시 시스템이 필요한 모든 상위 디렉토리를 자동으로 만듭니다. 내부 저장소의 파일 크기는 명시적으로 제한되지 않지만, 총 데이터 양은 /data 파티션의 사용 가능한 공간을 초과해서는 안 되며, 일반적으로 전체 플래시 메모리 용량의 60~80%입니다.

kotlin
val context = getApplicationContext()
val file = File(context.filesDir, "notes.txt")

file.writeText("노트 내용")

val content = file.readText()
println("읽음: $content")

writeText 및 readText 메서드는 Kotlin 표준 라이브러리의 확장 함수입니다. 스트림 열기와 닫기를 자동으로 관리하여 메모리 누수를 방지합니다. 바이너리 데이터에는 writeBytesreadBytes를 사용합니다. 인코딩이 필요 없으며 ByteArray 배열로 작동합니다. 큰 파일 작업 시 버퍼링된 스트림 사용을 권장합니다. 텍스트에는 BufferedReaderBufferedWriter, 바이너리 데이터에는 BufferedInputStreamBufferedOutputStream을 사용합니다.

내부 저장소에 하위 디렉토리 만들기

파일을 계층적으로 구성하려면 filesDir 내에 하위 디렉토리를 만드세요. 이미지, 문서, 내보내기 파일 등 유형별로 데이터를 구조화하는 데 도움이 됩니다. mkdirs() 메서드는 중첩된 디렉토리를 포함하여 경로에서 누락된 모든 디렉토리를 만듭니다. 생성 작업이 성공했는지 확인하세요. 메서드는 새 디렉토리가 생성된 경우에만 true를 반환합니다. 생성 실패는 대부분 /data 파티션의 공간 부족 또는 파일 시스템 inode 고갈과 관련됩니다.

kotlin
val imagesDir = File(context.filesDir, "images")
if (imagesDir.mkdirs()) {
    println("디렉토리가 생성되었습니다")
}

val imageFile = File(imagesDir, "photo.jpg")
imageFile.writeBytes(byteArray)

큰 파일을 쓰기 전에 사용 가능한 공간을 확인하려면 File.getFreeSpace() 또는 File.getUsableSpace()를 사용하세요. 두 번째 메서드는 보안 할당량을 고려하여 현재 애플리케이션이 사용 가능한 바이트 수를 반환하며, 다중 사용자 기기 컨텍스트에서 더 정확합니다. 사용 가능한 공간이 예상 파일 크기보다 작으면 사용자에게 메시지를 표시하고 기기 설정에서 공간을 확보하도록 제안합니다.

iOS에서 내부 저장소 사용 방법

iOS에서 각 애플리케이션은 격리된 샌드박스 컨테이너에서 작동합니다. 시스템은 특별한 entitlements 없이 경계를 넘는 API를 제공하지 않습니다. 파일 시스템 작업의 주요 도구는 Foundation 프레임워크의 FileManager 클래스입니다. 샌드박스 컨테이너에는 각각 고유한 백업 정책이 있는 여러 표준 디렉토리가 포함됩니다.

FileManager를 통한 Documents 디렉토리 액세스

Documents 디렉토리는 애플리케이션 실행 간에 유지되고 백업에서 복원되어야 하는 사용자 데이터를 위한 것입니다. iOS는 자동으로 이 디렉토리를 iCloud 및 iTunes 백업에 포함합니다. urls(for:in:) 메서드는 요청된 디렉토리의 URL 배열을 반환하며, 배열의 첫 번째 요소가 기본입니다.

swift
let fm = FileManager.default
let docs = fm.urls(
    for: .documentDirectory,
    in: .userDomainMask
).first!

let fileURL = docs.appendingPathComponent("data.plist")
try data.write(to: fileURL)

FileManager는 파일 생성, 복사, 이동, 삭제, 이름 변경 등 완전한 파일 작업 세트를 지원합니다. 각 작업은 오류를 던질 수 있으므로 모든 호출을 do-catch 구문으로 감싸야 합니다. 파일 삭제에 특히 주의하세요. 작업은 되돌릴 수 없으며, removeItem(at:) 이후 데이터 복원은 사전 백업 없이 불가능합니다.

백업 예외 관리

샌드박스 컨테이너의 모든 데이터를 iCloud 백업에 포함해서는 안 됩니다. 예를 들어, 다운로드한 캐시된 이미지나 임시 처리 파일은 복원할 필요가 없으며 다음 사용 시 다시 생성됩니다. 디렉토리나 파일을 백업에서 제외하려면 isExcludedFromBackup 속성을 true로 설정합니다. Apple은 원격으로 복원할 수 있는 데이터를 항상 백업에서 제외할 것을 권장합니다. 이렇게 하면 iCloud 저장소 사용을 최소화하고 복구 시간을 단축할 수 있습니다.

swift
var cacheURL = fm.urls(
    for: .cachesDirectory,
    in: .userDomainMask
).first!
cacheURL.hasExcludedFromBackupKey = true

var values = URLResourceValues()
values.isExcludedFromBackup = true
try cacheURL.setResourceValues(values)

내부 저장소, 캐시, 외부 저장소의 차이점

모바일 기기의 각 저장소 유형에는 고유한 목적과 사용 규칙이 있습니다. 이러한 차이점을 이해하면 개발자가 각 데이터 유형에 적합한 위치를 선택하는 데 도움이 됩니다. 아래는 애플리케이션에서 사용 가능한 세 가지 주요 저장소 유형의 비교입니다.

특성Internal Storage캐시 디렉토리External Storage
다른 앱에 대한 가시성숨김숨김액세스 가능
앱 제거 시 삭제완전완전위치에 따라 다름
백업Android — 없음, iOS — 있음 (Documents)없음동기화 시에만
미디어 없이 사용 가능항상항상SD 카드 필요
데이터 손실 위험최소높음중간
권장 파일 크기최대 100 MB최대 50 MB모든 크기

내부 저장소는 다른 프로그램이 액세스할 수 없는 앱 설정, 데이터베이스 파일 및 사용자 문서를 저장하는 데 최적입니다. 캐시 디렉토리는 다운로드한 이미지, API 응답, 중간 처리 데이터 등 다음 사용 시 다시 생성할 수 있는 임시 파일을 위한 것입니다. 외부 저장소는 대용량 미디어 파일(사진, 비디오, 음악)과 사용자가 공유 액세스를 통해 다른 애플리케이션과 공유하려는 데이터에 가장 적합합니다.

저장소 유형 선택은 Google Play 및 App Store의 앱 평점에도 영향을 미칩니다. 정리 없이 내부 저장소에 대량의 데이터를 저장하는 앱은 부정적인 리뷰를 받습니다. 사용자는 공간 부족을 불평합니다. App Annie의 연구에 따르면, 사용자의 62%가 정리 옵션 없이 기기 내부 저장소의 500MB 이상을 차지하는 앱을 삭제합니다.

내부 저장소 사용 권장 사항

앱 내부 저장소의 적절한 관리는 성능, 보안 및 사용자 경험을 향상시킵니다. 다음 권장 사항은 공식 Android 및 iOS 문서는 물론 수백만 설치 수의 애플리케이션 개발 실무 경험을 기반으로 합니다.

  • 저장 데이터 양을 최소화하세요. 내부 저장소는 중요한 파일에만 사용하고 나머지는 캐시 또는 외부 저장소에 배치
  • 임시 파일을 정기적으로 정리하세요. 실행 시 캐시 디렉토리를 확인하고 24시간 이상 된 파일을 삭제하여 시스템 부하를 줄이고 /data 파티션 오버플로를 방지
  • 기밀 데이터를 암호화하려면 AndroidX Security 라이브러리의 EncryptedSharedPreferences 또는 EncryptedFile을 사용. 일반 텍스트로 토큰과 비밀번호를 저장하는 것은 루트 액세스 권한이 있는 트로이 목마가 악용하는 일반적인 취약점
  • 파일 구조 업데이트 시 마이그레이션을 사용하세요. 새 버전의 앱을 출시할 때 이전 파일이 있는지 확인하고 이전 파일을 삭제하기 전에 새 디렉토리로 이동

경계 사례 테스트에 특히 주의해야 합니다. 내부 저장소가 가득 찬 경우, 쓰기 작업이 예기치 않게 중단된 경우(앱 충돌, 수신 전화), iOS 백업에서 복원할 때의 애플리케이션 동작을 확인하세요. 이러한 각 시나리오에서 데이터는 일관성을 유지하거나 마지막 안정 상태로 복원되어야 합니다. 트랜잭션 파일을 사용하세요. 임시 파일에 데이터를 쓴 다음 원자적으로 대상 파일로 이름을 변경합니다. 이렇게 하면 쓰기 실패 시 손상된 데이터를 읽는 것을 방지할 수 있습니다.

사용자 제어를 잊지 마세요. 앱 설정에서 임시 데이터를 지우고 점유된 내부 저장소 용량을 표시하는 옵션을 제공하세요. Google Play Console에 따르면, 이 기능이 있는 앱은 “성능” 카테고리에서 18% 더 많은 긍정적인 리뷰를 받습니다.

자주 묻는 질문

앱 제거 후 Internal Storage는 어떻게 되나요?

앱의 내부 저장소에 있는 모든 데이터가 완전히 삭제됩니다. 운영 체제는 데이터베이스, 설정, 임시 파일을 포함한 잔여 파일이 없음을 보장합니다. 외부 저장소의 데이터는 남을 수 있습니다.

다른 앱이 Internal Storage의 파일을 읽을 수 있나요?

기기에 대한 루트 액세스 없이 다른 앱은 다른 앱의 Internal Storage에서 파일을 읽을 수 없습니다. Android에서는 슈퍼유저 권한이 필요하며, iOS에서는 샌드박스를 통해 커널 수준에서 격리가 적용됩니다.

내부 메모리에 저장할 수 있는 최대 데이터 양은?

명시적 제한은 없지만 총량은 /data 파티션의 사용 가능한 공간에 의해 제한됩니다. 앱당 100MB를 초과하지 않는 것이 좋습니다. 더 큰 용량은 외부 저장소나 클라우드에 배치하는 것이 좋습니다.

Android에서 filesDir과 cacheDir의 차이점은?

filesDir은 영구 앱 데이터용이며 시스템이 필요할 때만 삭제합니다. cacheDir은 임시 파일용으로 메모리 부족 시 시스템이 삭제할 수 있습니다. 시스템은 cacheDir의 지속성을 보장하지 않습니다.

Internal Storage에서 SD 카드로 데이터를 전송하는 방법은?

Internal Storage에서 SD 카드로 직접 복사는 보안 정책에 의해 금지됩니다. 사용자 동의를 받아 공유 저장소에 데이터 복사본을 만들려면 Android 10+의 MediaStore API 또는 SAF(Storage Access Framework)를 사용하세요.

요약

  • Internal Storage — 각 애플리케이션의 격리된 디렉토리, 다른 프로그램 및 사용자 액세스로부터 보호
  • Android 및 iOS의 샌드박스 아키텍처는 다른 앱의 데이터가 겹치지 않고 루트 액세스 없이 읽을 수 없도록 보장
  • 저장 방법 선택은 데이터 유형에 따라 다름: 파일은 filesDir, 설정은 DataStore, 구조화된 데이터는 Room
  • iOS 샌드박스는 중요하지 않은 데이터의 경우 isExcludedFromBackup 속성으로 제어해야 하는 백업 정책 포함
  • 캐시와의 차이점은 데이터 지속성 보장: Internal Storage는 시스템이 삭제하지 않지만 cacheDir는 메모리 부족 시 지워질 수 있음
  • 내부 저장소의 권장 데이터 양 — 최대 100MB. 큰 파일은 외부 저장소나 클라우드 서비스에 배치
  • 사용자 제어를 통한 점유 공간 확인 및 데이터 정리 기능은 스토어에서 신뢰도와 앱 평점을 높임

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기