๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ iOS/๐Ÿ”ฅ ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…

[iOS] Test ํŒŒ์ผ์„ ๋„ฃ์„ Asset ์ƒ์„ฑ์‹œ ์˜ค๋ฅ˜_ Bundle ์‚ฌ์šฉ

by MINT09 2024. 1. 28.

ํ…Œ์ŠคํŠธ์šฉ JSON ํŒŒ์ผ์€ ์ดํ›„์—๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๊ธฐ์— test ํด๋”์— ๋”ฐ๋กœ Asset catalog๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ทธ๊ณณ์—์„œ๋งŒ ๋„ฃ์–ด๋‘๊ณ  ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์—ˆ๋‹ค. ๋•Œ๋ฌธ์— ํด๋”๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ ์ด๋ฆ„์„ Json.xcassets ์œผ๋กœ ์„ ์–ธํ•˜๊ณ  ๊ทธ ์•ˆ์— ํŒŒ์ผ์„ ๋„ฃ์—ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ asset catalog์˜ ๋ชจ์–‘์ด ๊ธฐ์กด์˜ ๊ฒƒ๊ณผ๋Š” ๋‹ฌ๋ž๋‹ค. ํ™•์ธํ•ด๋ณด๋‹ˆ asset catalog๋ฅผ ๋งŒ๋“ค๋•Œ๋Š” ๋‹จ์ˆœํ•˜๊ฒŒ ํด๋”๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ File → New → File์„ ํƒ€๊ณ  ๋“ค์–ด๊ฐ€ Resource์˜ Asset Catalog๋ฅผ ์„ ํƒํ•˜์—ฌ ๋งŒ๋“ค์–ด์•ผ ํ–ˆ๋‹ค.

๊ทธ ํ›„ test code๋ฅผ ์ž‘์„ฑํ•˜์—ฌ ๋Œ๋ฆฌ๋Š”๋ฐ ์ด๋ฒˆ์—๋Š” NSDataAsset์„ ๊ฐ€์ ธ์˜ค๋Š” guard๋ฌธ์—์„œ ๊ณ„์† retrun์œผ๋กœ ๋น ์ง€๋ฉฐ ์ข…๋ฃŒ๋˜์—ˆ๋‹ค.

guard let json = NSDataAsset(name: "box_office_sample") else {
    return
}

์ง์ ‘ ์ƒ์„ฑํ–ˆ๋˜ Json asset ๋ง๊ณ  main asset์— ํŒŒ์ผ์„ ๋„ฃ์–ด๋ณด๋‹ˆ ์ด๋ฒˆ์—๋Š” ์ œ๋Œ€๋กœ binding ๋˜์—ˆ๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ bundle์„ ๋งŒ๋“ค์–ด์„œ ์„ค์ •ํ•ด์ฃผ์—ˆ๋‹ค.

โ„๏ธBundle

๋ฒˆ๋“ค์€ ๋ฌด์—‡์ผ๊นŒ? ๊ณต์‹๋ฌธ์„œ์˜ ์ •์˜์—์„œ ๋ฒˆ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๐Ÿ’ก A representation of the code and resources stored in a bundle directory on disk.
๋””์Šคํฌ์˜ ๋ฒˆ๋“ค ๋””๋ ‰ํ† ๋ฆฌ์— ์ €์žฅ๋œ ์ฝ”๋“œ ๋ฐ resource์˜ ํ‘œํ˜„

๊ทธ๋™์•ˆ ์šฐ๋ฆฌ๊ฐ€ UIImage๋ฅผ Asset์—์„œ ์ฐพ์•„์„œ ๊ฐ€์ ธ์˜ฌ ๋•Œ ํ•ญ์ƒ ์ด ๋ฒˆ๋“ค์„ ์ด์šฉํ–ˆ์—ˆ๋‹ค. ๊ธฐ๋ณธ์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋Š” main์—์„œ ๊ฐ€์ ธ์™”๊ธฐ์— ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์•˜์„ ๋ฟ! ํ•„์š”ํ•œ resource๋ฅผ ์ฐพ์œผ๋ ค๋ฉด, ๋จผ์ € ํ•ด๋‹น resource๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฒˆ๋“ค์„ ์ง€์ •ํ•ด์•ผํ•œ๋‹ค.

main Bundle

ํ‰์ƒ์‹œ์— main์œผ๋กœ ์ง€์ •๋˜์–ด ์žˆ์„ ๋ฟ์ด๋‹ค. ๊ธฐ๋ณธ ๋ฒˆ๋“ค์ธ main์€ ํ˜„์žฌ ์‹คํ–‰ ์ค‘์ธ ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์•ฑ์—์„œ ๊ธฐ๋ณธ ๋ฒˆ๋“ค์€ ์•ฑ๊ณผ ํ•จ๊ป˜ ์ œ๊ณต๋˜๋Š” resource์— ๋Œ€ํ•œ ์ ‘์† ๊ถŒํ•œ์„ ์ œ๊ณตํ•œ๋‹ค. ์•ฑ์ด main ๋ฒˆ๋“ค๊ณผ ์ง์ ‘ ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋”ฐ๋กœ ์ƒ์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์ง€๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ์šฐ๋ฆฌ์˜ ํ”„๋กœ์ ํŠธ์—์„œ์™€ ๊ฐ™์€ ์ƒํ™ฉ์ด๋‹ค. ๋ณดํ†ต ๋ฒˆ๋“ค์€ ์•ฑ ํ”„๋กœ์ ํŠธ ํŒŒ์ผ์„ ๋งŒ๋“ค๋ฉด ๊ธฐ๋ณธ์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

ํŒŒ์ผ ์„ค๋ช…
myApp (ํ•„์ˆ˜)application code๊ฐ€ ํฌํ•จ๋œ ์‹คํ–‰ ํŒŒ์ผ
Application Icon (ํ•„์ˆ˜/๊ถŒ์žฅ) application์„ ๋‚˜ํƒ€๋‚ด๊ธฐ ์œ„ํ•œ ์•„์ด์ฝ˜.
Info.plist (ํ•„์ˆ˜) ๋ฒˆ๋“ค ID, ๋ฒ„์ „ ๋ฒˆํ˜ธ, ํ‘œ์‹œ ์ด๋ฆ„ ๋“ฑ application์— ๋Œ€ํ•œ ๊ตฌ์„ฑ ์ •๋ณด
MainWindow.nib (๊ถŒ์žฅ) ์•ฑ์˜ ๊ธฐ๋ณธ nib ํŒŒ์ผ. ์‹œ์ž‘ ์‹œ ๋กœ๋“œํ•  ๊ธฐ๋ณธ interface ๊ฐœ์ฒด
Settings.bundle ์„ค์ • application์— ์ถ”๊ฐ€ํ•˜๋ ค๋Š” ์•ฑ ๋ณ„ ๊ธฐ๋ณธ ์„ค์ •์„ ํฌํ•จํ•˜๋Š” ํŠน์ˆ˜ํ•œ ์œ ํ˜•์˜ ํ”Œ๋Ÿฌ๊ทธ์ธ
Custom resource ํŒŒ์ผ localize resource X: ์ตœ์ƒ์œ„ ๋””๋ ‰ํ† ๋ฆฌ ๋ฐฐ์น˜
localize resource O: ๋ฒˆ๋“ค์˜ ์–ธ์–ด๋ณ„ ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ ๋ฐฐ์น˜
Resource = nib files, images, sound files, configuration files, strings files, other custom data files

init(for:)

์šฐ๋ฆฌ์˜ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ์—์„œ nil๋กœ ๋ฐ˜ํ™˜๋˜์—ˆ๋˜ ๊ฒƒ๋„ ์ด ๊ธฐ๋ณธ ์ƒ์„ฑ๋œ ๋ฒˆ๋“ค์— ์ƒˆ๋กœ ๋งŒ๋“  custom resource ํŒŒ์ผ์ด ์˜ฌ๋ผ๊ฐ€ ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด์—ˆ๋‹ค. ๋•Œ๋ฌธ์— ์ด resource ํŒŒ์ผ์„ ํฌํ•จํ•˜๋Š” ๋‹จ์œ„๋ฅผ ๋ฒˆ๋“ค ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ €์žฅํ•ด ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ–ˆ๋‹ค.

let bundle = Bundle(for: JsonDecodeTests.self)
guard let json = NSDataAsset(name: "box_office_sample", bundle: bundle) else {
    return
}
// Get the app's main bundle
let mainBundle = Bundle.main


// Get the bundle containing the specified private class.
let myBundle = Bundle(for: NSClassFromString("MyPrivateClass")!)

https://developer.apple.com/documentation/foundation/bundle/1417717-init

 

init(for:) | Apple Developer Documentation

Returns the object with which the specified class is associated.

developer.apple.com

์ด๋•Œ init(for:)์„ ์‚ฌ์šฉํ–ˆ๋‹ค. ์ด๋ฅผ ์ด์šฉํ•˜๋ฉด ์ง€์ •ํ•œ class๊ฐ€ ์—ฐ๊ฒฐ๋œ NSBundle ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

init(for aClass: AnyClass)

 

โ„๏ธLocating Resources in a Bundle

๋ฒˆ๋“ค์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฒˆ๋“ค ๋‚ด์˜ ํŠน์ • resource์˜ ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด resource๋ฅผ ์ฐพ๋Š”๋ฐ, ํŠน์ • ํ•˜์œ„ ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ๋Š” resource์˜ ๊ฒฝ์šฐ ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ง€์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค. resource๋ฅผ ์ฐพ๊ณ  ๋‚˜๋ฉด ๋ฒˆ๋“ค์€ ํŒŒ์ผ์„ ์—ด ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ ๋ฌธ์ž์—ด์ด๋‚˜ URL์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ฒˆ๋“ค์€ ๋””์Šคํฌ์˜ resource๋ฅผ ์ฐพ์„ ๋•Œ ํŠน์ •ํ•œ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ผ ๊ฐ„๋‹ค.

  1. Global (nonlocalized) resources
  2. Region-specific localized resources (based on the user’s region preferences)
  3. Language-specific localized resources (based on the user’s language preferences)
  4. Development language resources (as specified by the CFBundleDevelopmentRegion key in the bundle’s Info.plist file)

๋ฒˆ๋“ค์€ ์ด ์ˆœ์„œ๋Œ€๋กœ resource๋ฅผ ์ฐพ๋Š”๋‹ค. ์ด๋•Œ 1๋ฒˆ์—์„œ ์ฐพ๊ณ  ๋‚˜๋ฉด 2๋ฒˆ, 3๋ฒˆ, 4๋ฒˆ์—์„œ๋Š” resource๋ฅผ ์ฐพ์ง€ ์•Š๋Š”๋‹ค. → ์‹œ๊ฐ„ ๋‚ญ๋น„ ์—†์• ์„œ ์„ฑ๋Šฅ์„ ์˜ฌ๋ฆฌ๊ธฐ ์œ„ํ•ด.

 

 โ„๏ธUnderstanding Bundle Structures

๋ฒˆ๋“ค ๊ตฌ์กฐ๋Š” ํ”Œ๋žซํผ๊ณผ ๋ฒˆ๋“ค ์œ ํ˜•์— ๋”ฐ๋ผ ๋‹ค๋ฅด๋‹ค. ๋Œ€๋ถ€๋ถ„ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋ฅผ ์ˆจ๊ธฐ๊ณ , ๋ณดํ†ต ๋ฒˆ๋“ค์—์„œ resource๋Š” ์ž๋™์œผ๋กœ ์‹œ์ž‘ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ฐพ๊ณ  ์•Œ๋ ค์ง„ ์œ„์น˜์—์„œ ์ฐพ์•„์ ธ์„œ load ๋œ๋‹ค. ๋˜ํ•œ ๋ฒˆ๋“ค ํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ์™€ ์†์„ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์•Œ๋ ค์ง„ ๋ฒˆ๋“ค ๋””๋ ‰ํ† ๋ฆฌ์˜ ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ํ•ด๋‹น ๋””๋ ‰ํ† ๋ฆฌ์—์„œ ๊ตฌ์ฒด์ ์œผ๋กœ resource๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

→ ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์˜ ๊ฒฝ์šฐ๋„ ์ด๋ฅผ ํ™œ์šฉํ•œ ๊ฒƒ์ด๋‹ค. ํ…Œ์ŠคํŠธ ํด๋ž˜์Šค๊ฐ€ ์žˆ๋Š” ๋””๋ ‰ํ† ๋ฆฌ์˜ ์œ„์น˜๋ฅผ ๊ฐ€์ ธ์˜ค๋ฉด ์ด ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด๋ถ€์— ์—์…‹์œผ๋กœ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋Š” json ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์—ˆ๋‹ค.