코드와 리소스를 보유하는 표준화된 계층 구조를 가지는 디렉토리
번들이란 하나의 디렉토리입니다. 모든 디렉토리가 번들은 아닙니다. 디렉토리지만 표준화된 계층 구조를 가지고 있어야만 번들이라고 말할 수 있습니다.
예를 들어서 아래에 존재하는 앱들은 사실 모두 번들입니다.

실제로 계산기 앱에서 패키지 내용 보기 하면은 디렉토리를 확인할 수 있는데, 보다시피 디렉토리에서는 코드와 리소스, 메타데이터들을 보유하고 있습니다. 이것은 하나의 번들이라고 할 수 있습니다.

번들이라고 판단할 수 있는 특정한 계층 구조의 디렉토리를 가지고 있다면, 시스템에서는 번들이라고 구분합니다. 시스템이 번들이라고 판단하고 실행 가능한 APP 으로 분류하는 것입니다.
(정확히 말하면 모든 번들을 앱으로 분류하지는 않고, 해당 번들 내부에서 앱으로 분류될 수 있는 데이터가 존재해야 합니다.)
시스템이 디렉토리를 번들로 인식하기 위해서는 어떤 데이터를 가지고 있어야 할까?
.app 에 한해서 필수).app, .framework, .bundle , .plugin)Swift에서는 이 번들의 개념을 하나의 객체로 제공하고 있습니다. 예를 들면 다음과 같습니다.
guard let url = Bundle.main.url(forResource: "appl", withExtension: "json") else {
fatalError("appl.json 파일을 찾을 수 없습니다.")
}
코드에서 번들을 통해 파일의 내용에 접근하고 있습니다. 위의 코드는 메인 번들에 접근하고 있는데, 앱이 컴파일될 때 .app 의 확장자를 가진 메인 번들이 만들어집니다.
메인 번들은 현재 실행중인 코드가 포함된 번들입니다. 실제로 앱의 번들을 확인해보면 다음과 같습니다.
print(Bundle.main.bundlePath)

번들 디렉토리 안에 appl.json 리소스도 들어있는 것을 확인할 수 있습니다. 사실 아래와 같은 코드도 번들에서 이미지를 가져오는 메소드입니다.
let image = UIImage(named: "~~")
해당 코드는 런타임에 메인 번들에서 이름에 맞는 이미지를 찾아서 반환하겠다는 의미입니다. 리소스는 기본적으로 번들 내부에 존재하기 때문입니다.
다음과 같이 번들을 지정해서 이미지를 가져오는 것도 가능합니다.
init?(
named name: String,
in bundle: Bundle?,
compatibleWith traitCollection: UITraitCollection?
)