๋ชจ๋ ์ฌ์ฉ์๋ ๋ชจ๋ฐ์ผ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋น ๋ฅธ ์คํ๊ณผ ๋ฐ์ํ UI๋ฅผ ๋น์ฐํ๊ฒ ์ฌ๊น๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๋ ๋ฐ ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฌ๋ฉด ์ฌ์ฉ์๋ ์ฌํ๊ณ ํ๋ฅผ ๋ด๊ธฐ ์์ํฉ๋๋ค. ๊ณ ๊ฐ ๊ฒฝํ์ ์ฝ๊ฒ ๋ง์น๊ฑฐ๋ ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ฌ์ฉ์ ์์ํ๊ธฐ๋ ์ ์ ์ฌ์ฉ์๋ฅผ ์์ ํ ๋์น ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ Dodo Pizza ์ฑ์ด ์คํ๋๋ ๋ฐ ํ๊ท 3์ด๊ฐ ๊ฑธ๋ฆฌ๊ณ ์ผ๋ถ "์ด์ด ์ข์ ์ฌ๋๋ค"์ ๊ฒฝ์ฐ 15~20์ด๊ฐ ๊ฑธ๋ฆฌ๋ ๊ฒ์ ๋ฐ๊ฒฌํ์ต๋๋ค.
์ปท ์๋์๋ ํ๋ณตํ ๊ฒฐ๋ง์ด ์๋ ์ด์ผ๊ธฐ๊ฐ ์์ต๋๋ค. Realm ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฑ์ฅ, ๋ฉ๋ชจ๋ฆฌ ๋์, ์ค์ฒฉ๋ ๊ฐ์ฒด๋ฅผ ์ถ์ ํ ํ ํจ๊ป ํ์ ํฉ์ณ ๋ชจ๋ ๊ฒ์ ๊ณ ์น ๋ฐฉ๋ฒ์ ๋ํ ์ด์ผ๊ธฐ์ ๋๋ค.
๋ฌธ์์ ์์ฑ์ :๋ง์ฌ ์นด์นํจ โ Dodo Pizza์ ์๋๋ก์ด๋ ๊ฐ๋ฐ์.
์ ํ๋ฆฌ์ผ์ด์ ์์ด์ฝ์ ํด๋ฆญํ ํ ์ฒซ ๋ฒ์งธ ํ๋์ onResume()๊น์ง 15์ด๋ ๋ฌดํ๋์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ผ๋ถ ์ฌ์ฉ์์ ๊ฒฝ์ฐ ์์ ์๊ฐ์ด 20-XNUMX์ด์ ๋๋ฌํ์ต๋๋ค. ์ด๊ฒ์ด ์ด๋ป๊ฒ ๊ฐ๋ฅํฉ๋๊น?
์ฝ์ ์๊ฐ์ด ์๋ ๋ถ๋ค์ ์ํ ์์ฃผ ์งง์ ์์ฝ
Realm ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋์์ด ์ฑ์ฅํ์ต๋๋ค. ์ผ๋ถ ์ค์ฒฉ๋ ๊ฐ์ฒด๋ ์ญ์ ๋์ง ์๊ณ ์ง์์ ์ผ๋ก ๋์ ๋์์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์
์์ ์๊ฐ์ด ์ ์ฐจ ๋์ด๋ฌ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์์ ์๊ฐ์ด ๋ชฉํ์ ๋๋ฌํ์ต๋๋ค. 1์ด ๋ฏธ๋ง์ด ๋์๊ณ ๋ ์ด์ ์ฆ๊ฐํ์ง ์์์ต๋๋ค. ์ด ๊ธฐ์ฌ์๋ ์ํฉ์ ๋ํ ๋ถ์๊ณผ ๋น ๋ฅธ ์๋ฃจ์
๊ณผ ์ผ๋ฐ์ ์ธ ์๋ฃจ์
์ ๋ ๊ฐ์ง ์๋ฃจ์
์ด ํฌํจ๋์ด ์์ต๋๋ค.
๋ฌธ์ ๊ฒ์ ๋ฐ ๋ถ์
์ค๋๋ ๋ชจ๋ ๋ชจ๋ฐ์ผ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋น ๋ฅด๊ฒ ์คํ๋๊ณ ๋ฐ์์ฑ์ด ์์ด์ผ ํฉ๋๋ค. ํ์ง๋ง ์ด๋ ๋จ์ง ๋ชจ๋ฐ์ผ ์ฑ๋ง์ ๋ฌธ์ ๊ฐ ์๋๋๋ค. ์๋น์ค ๋ฐ ํ์ฌ์์ ์ํธ ์์ฉ์ ๋ํ ์ฌ์ฉ์ ๊ฒฝํ์ ๋ณต์กํ ๊ฒ์ ๋๋ค. ์๋ฅผ ๋ค์ด, ์ฐ๋ฆฌ์ ๊ฒฝ์ฐ ๋ฐฐ๋ฌ ์๋๋ ํผ์ ์๋น์ค์ ์ฃผ์ ์งํ ์ค ํ๋์ ๋๋ค. ๋ฐฐ๋ฌ์ด ๋น ๋ฅด๋ฉด ํผ์๊ฐ ๋ฐ๋๋ฐ๋ํ ๊ฒ์ด๊ณ , ์ง๊ธ ๋จน๊ณ ์ถ์ ์๋์ ์ค๋ ๊ธฐ๋ค๋ฆฌ์ง ์์๋ ๋ ๊ฒ์ด๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ฒฝ์ฐ ๋น ๋ฅธ ์๋น์ค ๋๋์ ๋ง๋๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ์คํํ๋ ๋ฐ 20์ด๋ฐ์ ๊ฑธ๋ฆฌ์ง ์๋๋ค๋ฉด ํผ์๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ ๋ฐ ์ผ๋ง๋ ์ค๋ ๊ฑธ๋ฆฌ๋์?
์ฒ์์ ์ฐ๋ฆฌ๋ ๋๋๋ก ์์ฉ ํ๋ก๊ทธ๋จ์ ์์ํ๋ ๋ฐ ๋ช ์ด๊ฐ ๊ฑธ๋ฆฐ๋ค๋ ์ฌ์ค์ ์ง๋ฉดํ๊ณ , ๋ค๋ฅธ ๋๋ฃ๋ค๋ก๋ถํฐ ์๊ฐ์ด ์ผ๋ง๋ ๊ฑธ๋ฆฌ๋์ง์ ๋ํ ๋ถ๋ง์ ๋ฃ๊ธฐ ์์ํ์ต๋๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ ์ด๋ฐ ์ํฉ์ ์ผ๊ด๋๊ฒ ๋ฐ๋ณตํ ์ ์์์ต๋๋ค.
์ผ๋ง๋ ๊ฑธ๋ฆฌ๋์? ์ ๋ฐ๋ฅด๋ฉด
๊ทธ๋ฌ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ์์ํ๋ ๋ฐ ๋งค์ฐ ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค๋ ๋ถ๋ง์ด ๋ํ๋๊ธฐ ์์ํ์ต๋๋ค! ์ฐ์ , ์ฐ๋ฆฌ๋ "๋งค์ฐ, ๋งค์ฐ, ๋งค์ฐ ๊ธธ๋ค"๊ฐ ๋ฌด์์ธ์ง ์ธก์ ํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ ์ํด Firebase ์ถ์ ์ ์ฌ์ฉํ์ต๋๋ค.
์ด ํ์ค ์ถ์ ์ ์ฌ์ฉ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฌ๋ ์๊ฐ๊ณผ ์ฒซ ๋ฒ์งธ ํ๋์ onResume()์ด ์คํ๋๋ ์๊ฐ ์ฌ์ด์ ์๊ฐ์ ์ธก์ ํฉ๋๋ค. Firebase ์ฝ์์์๋ ์ด ์ธก์ ํญ๋ชฉ์ _app_start๋ผ๊ณ ํฉ๋๋ค. ๊ทธ๊ฒ์ ๋ฐํ์ก๋ค:
- ์ค์ ์ฝ๋ ์์ ์๊ฐ์ด 95์ด ๋ฏธ๋ง์์๋ ๋ถ๊ตฌํ๊ณ 20๋ฒ์งธ ๋ฐฑ๋ถ์์๋ฅผ ์ด๊ณผํ๋ ์ฌ์ฉ์์ ์์ ์๊ฐ์ ๊ฑฐ์ 5์ด(์ผ๋ถ๋ ๋ ๊ธธ๋ค)์ ๋๋ค.
- ์์ ์๊ฐ์ ์ผ์ ํ ๊ฐ์ด ์๋์ง๋ง ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ์ฆ๊ฐํฉ๋๋ค. ๊ทธ๋ฌ๋ ๋๋ก๋ ๋ฐฉ์ธ์ด ์์ต๋๋ค. ๋ถ์ ๊ท๋ชจ๋ฅผ 90์ผ๋ก ๋๋ ธ์ ๋ ์ด๋ฌํ ํจํด์ ๋ฐ๊ฒฌํ์ต๋๋ค.
๋ ๊ฐ์ง ์๊ฐ์ด ๋ ์ฌ๋์ต๋๋ค.
- ๋ญ๊ฐ๊ฐ ์๊ณ ์์ด์.
- ์ด "๋ฌด์ธ๊ฐ"๋ ๋ฆด๋ฆฌ์ค ํ ์ฌ์ค์ ๋ ๋ค์ ๋ค์ ๋์ถ๋ฉ๋๋ค.
โ์๋ง๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฌธ์ ๊ฐ ์๋ ๊ฒ ๊ฐ์์.โ ์ฐ๋ฆฌ๋ ์๊ฐํ๊ณ , ์ฐ๋ฆฌ๊ฐ ์ณ์์ต๋๋ค. ์ฒซ์งธ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์บ์๋ก ์ฌ์ฉํ๊ณ ๋ง์ด๊ทธ๋ ์ด์ ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ง์๋๋ค. ๋์งธ, ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋ ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ก๋๋ฉ๋๋ค. ๋ชจ๋ ๊ฒ์ด ์ ์ด์ธ๋ฆฝ๋๋ค.
Realm ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ด๋ค ๋ฌธ์ ๊ฐ ์๋์?
์ฐ๋ฆฌ๋ ์ฒซ ๋ฒ์งธ ์ค์น๋ถํฐ ํ์ฑ ์ฌ์ฉ ์ค์ ์ ํ๋ฆฌ์ผ์ด์
์๋ช
๋์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ด์ฉ์ด ์ด๋ป๊ฒ ๋ณ๊ฒฝ๋๋์ง ํ์ธํ๊ธฐ ์์ํ์ต๋๋ค. ๋ค์์ ํตํด Realm ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ด์ฉ์ ๋ณผ ์ ์์ต๋๋ค.
adb exec-out run-as ${PACKAGE_NAME} cat files/${DB_NAME}
์ฌ๋ฌ ๋ฒ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ด์ฉ์ ์ดํด๋ณธ ๊ฒฐ๊ณผ ํน์ ์ ํ์ ๊ฐ์ฒด ์๊ฐ ์ง์์ ์ผ๋ก ์ฆ๊ฐํ๊ณ ์์์ ๋ฐ๊ฒฌํ์ต๋๋ค.
๊ทธ๋ฆผ์ ๋ ํ์ผ์ ๋ํ Realm Studio์ ์ผ๋ถ๋ฅผ ๋ณด์ฌ์ค๋๋ค. ์ผ์ชฝ์ ์ค์น ํ ์ผ์ ์๊ฐ์ด ์ง๋ ์ ํ๋ฆฌ์ผ์ด์
๊ธฐ๋ฐ, ์ค๋ฅธ์ชฝ์ ํ์ฑ ์ฌ์ฉ ํ์
๋๋ค. ๊ฐ์ฒด์ ๊ฐ์๋ฅผ ์ ์ ์์ต๋๋ค. ImageEntity
ะธ MoneyType
ํฌ๊ฒ ์ฆ๊ฐํ์ต๋๋ค(์คํฌ๋ฆฐ์ท์ ๊ฐ ์ ํ์ ๊ฐ์ฒด ์๋ฅผ ๋ณด์ฌ์ค๋๋ค).
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฆ๊ฐ์ ์์ ์๊ฐ์ ๊ด๊ณ
ํต์ ๋์ง ์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฆ๊ฐ๋ ๋งค์ฐ ๋์ฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๊ฒ์ด ์ ํ๋ฆฌ์ผ์ด์ ์์ ์๊ฐ์ ์ด๋ค ์ํฅ์ ๋ฏธ์นฉ๋๊น? ActivityManager๋ฅผ ํตํด ์ด๋ฅผ ์ธก์ ํ๋ ๊ฒ์ ๋งค์ฐ ์ฝ์ต๋๋ค. Android 4.4๋ถํฐ logcat์ Displayed ๋ฌธ์์ด๊ณผ ์๊ฐ์ ์ฌ์ฉํ์ฌ ๋ก๊ทธ๋ฅผ ํ์ํฉ๋๋ค. ์ด ์๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋ ์๊ฐ๋ถํฐ ํ๋ ๋ ๋๋ง์ด ๋๋ ๋๊น์ง์ ๊ฐ๊ฒฉ๊ณผ ๊ฐ์ต๋๋ค. ์ด ์๊ฐ ๋์ ๋ค์๊ณผ ๊ฐ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํฉ๋๋ค.
- ํ๋ก์ธ์ค๋ฅผ ์์ํ์ญ์์ค.
- ๊ฐ์ฒด ์ด๊ธฐํ.
- ํ๋ ์์ฑ ๋ฐ ์ด๊ธฐํ.
- ๋ ์ด์์์ ์์ฑํฉ๋๋ค.
- ์ ํ๋ฆฌ์ผ์ด์ ๋ ๋๋ง.
์ฐ๋ฆฌ์๊ฒ ์ ํฉํฉ๋๋ค. -S ๋ฐ -W ํ๋๊ทธ๋ฅผ ์ฌ์ฉํ์ฌ ADB๋ฅผ ์คํํ๋ฉด ์์ ์๊ฐ๊ณผ ํจ๊ป ํ์ฅ๋ ์ถ๋ ฅ์ ์ป์ ์ ์์ต๋๋ค.
adb shell am start -S -W ru.dodopizza.app/.MainActivity -c android.intent.category.LAUNCHER -a android.intent.action.MAIN
๊ฑฐ๊ธฐ์ ์ก์์ค๋ฉด grep -i WaitTime
์๊ฐ์ด ์ง๋๋ฉด ์ด ์งํ ์์ง์ ์๋ํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ์๊ฐ์ ์ผ๋ก ๋ณผ ์ ์์ต๋๋ค. ์๋ ๊ทธ๋ํ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฝ๋ ์คํํธ โโํ์์ ๋ํ ์ ํ๋ฆฌ์ผ์ด์
์์ ์๊ฐ์ ์์กด์ฑ์ ๋ณด์ฌ์ค๋๋ค.
๋์์ 4MB์์ 15MB๋ก ์ฆ๊ฐํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํฌ๊ธฐ์ ์ฆ๊ฐ ์ฌ์ด์๋ ๋์ผํ ๊ด๊ณ๊ฐ ์์์ต๋๋ค. ์ ์ฒด์ ์ผ๋ก ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ(์ฝ๋ ์คํํธ์ ์ฆ๊ฐ์ ํจ๊ป) ์ ํ๋ฆฌ์ผ์ด์
์์ ์๊ฐ๊ณผ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํฌ๊ธฐ๊ฐ ๋ชจ๋ ์ฆ๊ฐํ ๊ฒ์ผ๋ก ๋ํ๋ฌ์ต๋๋ค. ์ฐ๋ฆฌ ์์๋ ๊ฐ์ค์ด ์์ต๋๋ค. ์ด์ ๋จ์ ๊ฒ์ ์์กด์ฑ์ ํ์ธํ๋ ๊ฒ๋ฟ์ด์์ต๋๋ค. ๋ฐ๋ผ์ ์ฐ๋ฆฌ๋ "๋์ถ"์ ์ ๊ฑฐํ๊ณ ์ด๊ฒ์ด ์ถ์ ์๋๋ฅผ ๋์ผ ์ ์๋์ง ํ์ธํ๊ธฐ๋ก ๊ฒฐ์ ํ์ต๋๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋์์์ด ์ฆ๊ฐํ๋ ์ด์
"๋์"๋ฅผ ์ ๊ฑฐํ๊ธฐ ์ ์, ๊ทธ๊ฒ์ด ์ฒ์์ ๋ํ๋ ์ด์ ๋ฅผ ์ดํดํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ฅผ ์ํด Realm์ด ๋ฌด์์ธ์ง ๊ธฐ์ตํด ๋ด ์๋ค.
Realm์ ๋น๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋๋ค. Android์ ORM ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์๋ฅผ ์ค๋ช ํ๋ ๊ฒ๊ณผ ์ ์ฌํ ๋ฐฉ์์ผ๋ก ๊ฐ์ฒด ๊ฐ์ ๊ด๊ณ๋ฅผ ์ค๋ช ํ ์ ์์ต๋๋ค. ๋์์ Realm์ ์ต์ํ์ ๋ณํ๊ณผ ๋งคํ์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋ฉ๋ชจ๋ฆฌ์ ์ง์ ์ ์ฅํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋์คํฌ์์ ๋ฐ์ดํฐ๋ฅผ ๋งค์ฐ ๋น ๋ฅด๊ฒ ์ฝ์ ์ ์์ผ๋ฉฐ ์ด๊ฒ์ด Realm์ ๊ฐ์ ์ด์ ์ฌ๋๋ฐ๋ ์ด์ ์ ๋๋ค.
(์ด ๊ธ์ ๋ชฉ์ ์ ์ด ์ค๋ช
๋ง์ผ๋ก๋ ์ถฉ๋ถํฉ๋๋ค. Realm์ ๋ํ ์์ธํ ๋ด์ฉ์ ๋ค์ ๋งํฌ์์ ํ์ธํ์ค ์ ์์ต๋๋ค.
๋ง์ ๊ฐ๋ฐ์๋ ๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค(์: ๋ด๋ถ์ ์ผ๋ก SQL์ด ํฌํจ๋ ORM ๋ฐ์ดํฐ๋ฒ ์ด์ค)๋ฅผ ์ฌ์ฉํ์ฌ ๋ ๋ง์ ์์ ์ ์ํํ๋ ๋ฐ ์ต์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ณ๋จ์ ๋ฐ์ดํฐ ์ญ์ ์ ๊ฐ์ ์ผ์ด ์ข ์ข ์ฃผ์ด์ง ๊ฒ์ฒ๋ผ ๋ณด์ ๋๋ค. ํ์ง๋ง Realm์์๋ ๊ทธ๋ ์ง ์์ต๋๋ค.
๊ทธ๋ฐ๋ฐ ์บ์ค์ผ์ด๋ ์ญ์ ๊ธฐ๋ฅ์ ์ค๋ซ๋์ ์์ฒญ์ด ๋ง์์ต๋๋ค. ์ด๊ฒ
๊ณ๋จ์ ์ญ์ ์์ด ๋ฐ์ดํฐ ์ ์ถ
์กด์ฌํ์ง ์๋ ๊ณ๋จ์ ์ญ์ ์ ์์กดํ๋ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๊ฐ ์ ํํ ์ด๋ป๊ฒ ์ ์ถ๋๋์? ์ค์ฒฉ๋ Realm ๊ฐ์ฒด๊ฐ ์์ผ๋ฉด ์ญ์ ํด์ผ ํฉ๋๋ค.
(๊ฑฐ์) ์ค์ ์ฌ๋ก๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ฐ๋ฆฌ์๊ฒ๋ ๊ฐ์ฒด๊ฐ ์์ต๋๋ค CartItemEntity
:
@RealmClass
class CartItemEntity(
@PrimaryKey
override var id: String? = null,
...
var name: String = "",
var description: String = "",
var image: ImageEntity? = null,
var category: String = MENU_CATEGORY_UNKNOWN_ID,
var customizationEntity: CustomizationEntity? = null,
var cartComboProducts: RealmList<CartProductEntity> = RealmList(),
...
) : RealmObject()
์ฅ๋ฐ๊ตฌ๋์ ์๋ ์ ํ์๋ ์ฌ์ง์ ํฌํจํ์ฌ ๋ค์ํ ํ๋๊ฐ ์์ต๋๋ค. ImageEntity
, ๋ง์ถคํ ์ฌ๋ฃ CustomizationEntity
. ๋ํ ์ฅ๋ฐ๊ตฌ๋์ ์๋ ์ํ์ ์์ฒด ์ํ ์ธํธ์ ์ฝค๋ณด๊ฐ ๋ ์ ์์ต๋๋ค. RealmList (CartProductEntity)
. ๋์ด๋ ๋ชจ๋ ํ๋๋ Realm ๊ฐ์ฒด์
๋๋ค. ๋์ผํ ID๋ฅผ ๊ฐ์ง ์ ๊ฐ์ฒด(copyToRealm() / copyToRealmOrUpdate())๋ฅผ ์ฝ์
ํ๋ฉด ์ด ๊ฐ์ฒด๋ฅผ ์์ ํ ๋ฎ์ด์ฐ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฌ๋ ๋ชจ๋ ๋ด๋ถ ๊ฐ์ฒด(image,customizationEntity ๋ฐ cartComboProducts)๋ ์์ ๊ฐ์ฒด์์ ์ฐ๊ฒฐ์ด ๋์ด์ง๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ง๋ฉ๋๋ค.
ํด๋น ํญ๋ชฉ๊ณผ์ ์ฐ๊ฒฐ์ด ๋์ด์ก์ผ๋ฏ๋ก ๋ ์ด์ ํด๋น ํญ๋ชฉ์ ์ฝ๊ฑฐ๋ ์ญ์ ํ ์ ์์ต๋๋ค(๋ช ์์ ์ผ๋ก ์ก์ธ์คํ๊ฑฐ๋ ์ ์ฒด "ํ ์ด๋ธ"์ ์ง์ฐ์ง ์๋ ํ). ์ฐ๋ฆฌ๋ ์ด๊ฒ์ "๋ฉ๋ชจ๋ฆฌ ๋์"๋ผ๊ณ ๋ถ๋ ์ต๋๋ค.
Realm์ผ๋ก ์์ ํ ๋ ๋ชจ๋ ์์๋ฅผ โโ๋ช ์์ ์ผ๋ก ์ดํด๋ณด๊ณ ํด๋น ์์ ์ ์ ๋ชจ๋ ํญ๋ชฉ์ ๋ช ์์ ์ผ๋ก ์ญ์ ํด์ผ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด ๋ค์๊ณผ ๊ฐ์ด ํ ์ ์์ต๋๋ค.
val entity = realm.where(CartItemEntity::class.java).equalTo("id", id).findFirst()
if (first != null) {
deleteFromRealm(first.image)
deleteFromRealm(first.customizationEntity)
for(cartProductEntity in first.cartComboProducts) {
deleteFromRealm(cartProductEntity)
}
first.deleteFromRealm()
}
// ะธ ะฟะพัะพะผ ัะถะต ัะพั
ัะฐะฝัะตะผ
์ด๋ ๊ฒ ํ๋ฉด ๋ชจ๋ ๊ฒ์ด ์ ์์ ์ผ๋ก ์๋ํ ๊ฒ์ ๋๋ค. ์ด ์์์๋ image,customizationEntity, cartComboProducts ๋ด๋ถ์ ๋ค๋ฅธ ์ค์ฒฉ๋ Realm ๊ฐ์ฒด๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ฏ๋ก ๋ค๋ฅธ ์ค์ฒฉ ๋ฃจํ์ ์ญ์ ๊ฐ ์์ต๋๋ค.
"๋น ๋ฅธ" ์๋ฃจ์
์ฐ๋ฆฌ๊ฐ ๊ฐ์ฅ ๋จผ์ ๊ฒฐ์ ํ ์ผ์ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์ฑ์ฅํ๋ ๊ฐ์ฒด๋ฅผ ์ ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ์ฌ ์ด๊ฒ์ด ์๋ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์๋์ง ํ์ธํ๋ ๊ฒ์ด์์ต๋๋ค. ์ฒซ์งธ, ๊ฐ์ฅ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ธ ํด๊ฒฐ์ฑ ์ด ๋ง๋ค์ด์ก์ต๋๋ค. ์ฆ, ๊ฐ ๊ฐ์ฒด๋ ์์ ์ ์์์ ์ ๊ฑฐํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ์ํด ์ฐ๋ฆฌ๋ ์ค์ฒฉ๋ Realm ๊ฐ์ฒด ๋ชฉ๋ก์ ๋ฐํํ๋ ์ธํฐํ์ด์ค๋ฅผ ๋์ ํ์ต๋๋ค.
interface NestedEntityAware {
fun getNestedEntities(): Collection<RealmObject?>
}
๊ทธ๋ฆฌ๊ณ ์ด๋ฅผ Realm ๊ฐ์ฒด์ ๊ตฌํํ์ต๋๋ค:
@RealmClass
class DataPizzeriaEntity(
@PrimaryKey
var id: String? = null,
var name: String? = null,
var coordinates: CoordinatesEntity? = null,
var deliverySchedule: ScheduleEntity? = null,
var restaurantSchedule: ScheduleEntity? = null,
...
) : RealmObject(), NestedEntityAware {
override fun getNestedEntities(): Collection<RealmObject?> {
return listOf(
coordinates,
deliverySchedule,
restaurantSchedule
)
}
}
ะ getNestedEntities
์ฐ๋ฆฌ๋ ๋ชจ๋ ํ์ ํญ๋ชฉ์ ๋จ์ ๋ชฉ๋ก์ผ๋ก ๋ฐํํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฐ ํ์ ๊ฐ์ฒด๋ NestedEntityAware ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ์ฌ ์ญ์ ํ ๋ด๋ถ Realm ๊ฐ์ฒด๊ฐ ์์์ ๋ํ๋ผ ์๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ScheduleEntity
:
@RealmClass
class ScheduleEntity(
var monday: DayOfWeekEntity? = null,
var tuesday: DayOfWeekEntity? = null,
var wednesday: DayOfWeekEntity? = null,
var thursday: DayOfWeekEntity? = null,
var friday: DayOfWeekEntity? = null,
var saturday: DayOfWeekEntity? = null,
var sunday: DayOfWeekEntity? = null
) : RealmObject(), NestedEntityAware {
override fun getNestedEntities(): Collection<RealmObject?> {
return listOf(
monday, tuesday, wednesday, thursday, friday, saturday, sunday
)
}
}
๋ฑ๋ฑ, ๊ฐ์ฒด ์ค์ฒฉ์ด ๋ฐ๋ณต๋ ์ ์์ต๋๋ค.
๊ทธ๋ฐ ๋ค์ ์ค์ฒฉ๋ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ์ฌ๊ท์ ์ผ๋ก ์ญ์ ํ๋ ๋ฉ์๋๋ฅผ ์์ฑํฉ๋๋ค. ๋ฐฉ๋ฒ(ํ์ฅ์ผ๋ก ๋ง๋ค์ด์ง) deleteAllNestedEntities
๋ชจ๋ ์ต์์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ๊ฐ์ ธ์ต๋๋ค. deleteNestedRecursively
NestedEntityAware ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋ ์ค์ฒฉ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ ๊ฑฐํฉ๋๋ค.
fun <T> Realm.deleteAllNestedEntities(entities: Collection<T>,
entityClass: Class<out RealmObject>,
idMapper: (T) -> String,
idFieldName : String = "id"
) {
val existedObjects = where(entityClass)
.`in`(idFieldName, entities.map(idMapper).toTypedArray())
.findAll()
deleteNestedRecursively(existedObjects)
}
private fun Realm.deleteNestedRecursively(entities: Collection<RealmObject?>) {
for(entity in entities) {
entity?.let { realmObject ->
if (realmObject is NestedEntityAware) {
deleteNestedRecursively((realmObject as NestedEntityAware).getNestedEntities())
}
realmObject.deleteFromRealm()
}
}
}
์ฐ๋ฆฌ๋ ๊ฐ์ฅ ๋น ๋ฅด๊ฒ ์ฑ์ฅํ๋ ๊ฐ์ฒด๋ฅผ ๋์์ผ๋ก ์ด ์์ ์ ์ํํ๊ณ ๋ฌด์จ ์ผ์ด ์ผ์ด๋ฌ๋์ง ํ์ธํ์ต๋๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก ์ด ์๋ฃจ์
์ผ๋ก ๋ฎ์ ๊ฐ์ฒด๋ ์ฑ์ฅ์ ๋ฉ์ท์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ฒ ์ด์ค์ ์ ๋ฐ์ ์ธ ์ฑ์ฅ์ ๋ํ๋์์ง๋ง ๋ฉ์ถ์ง ์์์ต๋๋ค.
"์ ์์ ์ธ" ์๋ฃจ์
๋ฒ ์ด์ค๊ฐ ๋ ์ฒ์ฒํ ์ฑ์ฅํ๊ธฐ ์์ํ์ง๋ง ์ฌ์ ํ ์ฑ์ฅํ์ต๋๋ค. ๊ทธ๋์ ์ฐ๋ฆฌ๋ ๋ ์์ธํ ์์๋ณด๊ธฐ ์์ํ์ต๋๋ค. ์ฐ๋ฆฌ ํ๋ก์ ํธ๋ Realm์ ๋ฐ์ดํฐ ์บ์ฑ์ ๋งค์ฐ ์ ๊ทน์ ์ผ๋ก ์ฌ์ฉํฉ๋๋ค. ๋ฐ๋ผ์ ๊ฐ ๊ฐ์ฒด์ ๋ํด ์ค์ฒฉ๋ ๊ฐ์ฒด๋ฅผ ๋ชจ๋ ์์ฑํ๋ ๊ฒ์ ๋ ธ๋ ์ง์ฝ์ ์ด๋ฉฐ, ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ ๋ ๊ฐ์ฒด ์ง์ ์ ์์ด๋ฒ๋ฆด ์ ์๊ธฐ ๋๋ฌธ์ ์ค๋ฅ ์ํ๋ ์ฆ๊ฐํฉ๋๋ค.
์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ์ง ์๊ณ ๋ชจ๋ ๊ฒ์ด ์์ฒด์ ์ผ๋ก ์๋ํ๋์ง ํ์ธํ๊ณ ์ถ์์ต๋๋ค.
๋ฌด์ธ๊ฐ๊ฐ ์ค์ค๋ก ์๋ํ๊ธฐ๋ฅผ ์ํ๋ค๋ฉด ๋ฆฌํ๋ ์ ์ ์ฌ์ฉํด์ผ ํฉ๋๋ค. ์ด๋ฅผ ์ํด ๊ฐ ํด๋์ค ํ๋๋ฅผ ์ดํด๋ณด๊ณ ๊ทธ๊ฒ์ด Realm ๊ฐ์ฒด์ธ์ง ๊ฐ์ฒด ๋ชฉ๋ก์ธ์ง ํ์ธํฉ๋๋ค.
RealmModel::class.java.isAssignableFrom(field.type)
RealmList::class.java.isAssignableFrom(field.type)
ํ๋๊ฐ RealmModel ๋๋ RealmList์ธ ๊ฒฝ์ฐ ์ด ํ๋์ ๊ฐ์ฒด๋ฅผ ์ค์ฒฉ๋ ๊ฐ์ฒด ๋ชฉ๋ก์ ์ถ๊ฐํ์ธ์. ๋ชจ๋ ๊ฒ์ ์์์ ํ ๊ฒ๊ณผ ๋๊ฐ์ต๋๋ค. ์ฌ๊ธฐ์๋ง ์์ฒด์ ์ผ๋ก ์ํ๋ฉ๋๋ค. ๊ณ๋จ์ ์ญ์ ๋ฐฉ๋ฒ ์์ฒด๋ ๋งค์ฐ ๊ฐ๋จํ๋ฉฐ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
fun <T : Any> Realm.cascadeDelete(entities: Collection<T?>) {
if(entities.isEmpty()) {
return
}
entities.filterNotNull().let { notNullEntities ->
notNullEntities
.filterRealmObject()
.flatMap { realmObject -> getNestedRealmObjects(realmObject) }
.also { realmObjects -> cascadeDelete(realmObjects) }
notNullEntities
.forEach { entity ->
if((entity is RealmObject) && entity.isValid) {
entity.deleteFromRealm()
}
}
}
}
ํ๋ filterRealmObject
Realm ๊ฐ์ฒด๋ง ํํฐ๋งํ๊ณ ์ ๋ฌํฉ๋๋ค. ๋ฐฉ๋ฒ getNestedRealmObjects
๋ฆฌํ๋ ์
์ ํตํด ๋ชจ๋ ์ค์ฒฉ๋ Realm ๊ฐ์ฒด๋ฅผ ์ฐพ์ ์ ํ ๋ชฉ๋ก์ ๋ฃ์ต๋๋ค. ๊ทธ๋ฐ ๋ค์ ๋์ผํ ์์
์ ์ฌ๊ท์ ์ผ๋ก ์ํํฉ๋๋ค. ์ญ์ ์ ๊ฐ์ฒด์ ์ ํจ์ฑ์ ํ์ธํด์ผ ํฉ๋๋ค. isValid
, ์๋ํ๋ฉด ์๋ก ๋ค๋ฅธ ์์ ๊ฐ์ฒด๊ฐ ๋์ผํ ๊ฐ์ฒด๋ฅผ ์ค์ฒฉํ ์ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ด๋ฅผ ํผํ๊ณ ์ ๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ID ์๋ ์์ฑ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
getNestedRealmObjects ๋ฉ์๋์ ์ ์ฒด ๊ตฌํ
private fun getNestedRealmObjects(realmObject: RealmObject) : List<RealmObject> {
val nestedObjects = mutableListOf<RealmObject>()
val fields = realmObject.javaClass.superclass.declaredFields
// ะัะพะฒะตััะตะผ ะบะฐะถะดะพะต ะฟะพะปะต, ะฝะต ัะฒะปัะตััั ะปะธ ะพะฝะพ RealmModel ะธะปะธ ัะฟะธัะบะพะผ RealmList
fields.forEach { field ->
when {
RealmModel::class.java.isAssignableFrom(field.type) -> {
try {
val child = getChildObjectByField(realmObject, field)
child?.let {
if (isInstanceOfRealmObject(it)) {
nestedObjects.add(child as RealmObject)
}
}
} catch (e: Exception) { ... }
}
RealmList::class.java.isAssignableFrom(field.type) -> {
try {
val childList = getChildObjectByField(realmObject, field)
childList?.let { list ->
(list as RealmList<*>).forEach {
if (isInstanceOfRealmObject(it)) {
nestedObjects.add(it as RealmObject)
}
}
}
} catch (e: Exception) { ... }
}
}
}
return nestedObjects
}
private fun getChildObjectByField(realmObject: RealmObject, field: Field): Any? {
val methodName = "get${field.name.capitalize()}"
val method = realmObject.javaClass.getMethod(methodName)
return method.invoke(realmObject)
}
๊ฒฐ๊ณผ์ ์ผ๋ก ํด๋ผ์ด์ธํธ ์ฝ๋์์๋ ๊ฐ ๋ฐ์ดํฐ ์์ ์์ ์ "๊ณ๋จ์ ์ญ์ "๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด ์ฝ์ ์์ ์ ๊ฒฝ์ฐ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
override fun <T : Entity> insert(
entityInformation: EntityInformation,
entities: Collection<T>): Collection<T> = entities.apply {
realmInstance.cascadeDelete(getManagedEntities(entityInformation, this))
realmInstance.copyFromRealm(
realmInstance
.copyToRealmOrUpdate(this.map { entity -> entity as RealmModel }
))
}
๋ฐฉ๋ฒ ์ฐ์ getManagedEntities
์ถ๊ฐ๋ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๋ฐ์ ๋ค์ ๋ฉ์๋๋ฅผ ๋ฐ์ต๋๋ค. cascadeDelete
์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ ์ ์์ง๋ ๋ชจ๋ ๊ฐ์ฒด๋ฅผ ๋ฐ๋ณต์ ์ผ๋ก ์ญ์ ํฉ๋๋ค. ๊ฒฐ๊ตญ ์ฐ๋ฆฌ๋ ์ ํ๋ฆฌ์ผ์ด์
์ ์ฒด์์ ์ด ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค. Realm์ ๋ฉ๋ชจ๋ฆฌ ๋์๋ ์์ ํ ์ฌ๋ผ์ก์ต๋๋ค. ์ ํ๋ฆฌ์ผ์ด์
์ ์ฝ๋ ์คํํธ โโํ์์ ๋ํ ์์ ์๊ฐ์ ์์กด์ฑ์ ๋์ผํ ์ธก์ ์ ํตํด ๊ฒฐ๊ณผ๋ฅผ ํ์ธํ์ต๋๋ค.
๋
น์ ์ ์ ์ค์ฒฉ๋ ๊ฐ์ฒด์ ์๋ ๊ณ๋จ์ ์ญ์ ์ค ์ฝ๋ ์คํํธ โโํ์์ ๋ํ ์ ํ๋ฆฌ์ผ์ด์
์์ ์๊ฐ์ ์์กด์ฑ์ ๋ณด์ฌ์ค๋๋ค.
๊ฒฐ๊ณผ ๋ฐ ๊ฒฐ๋ก
๊ณ์ํด์ ์ฆ๊ฐํ๋ Realm ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ก ์ธํด ์ ํ๋ฆฌ์ผ์ด์ ์คํ ์๋๊ฐ ๋งค์ฐ ๋๋ ค์ก์ต๋๋ค. ์ค์ฒฉ๋ ๊ฐ์ฒด์ ๋ํ ์์ฒด์ ์ธ "๊ณ๋จ์ ์ญ์ " ๊ธฐ๋ฅ์ด ํฌํจ๋ ์ ๋ฐ์ดํธ๋ฅผ ์ถ์ํ์ต๋๋ค. ์ด์ _app_start ์ธก์ ํญ๋ชฉ์ ํตํด ์ฐ๋ฆฌ์ ๊ฒฐ์ ์ด ์ ํ๋ฆฌ์ผ์ด์ ์์ ์๊ฐ์ ์ด๋ค ์ํฅ์ ๋ฏธ์ณค๋์ง ๋ชจ๋ํฐ๋งํ๊ณ ํ๊ฐํฉ๋๋ค.
๋ถ์์ ์ํด 90์ผ์ ๊ธฐ๊ฐ์ ์ฌ์ฉํ์ฌ ์ค์๊ฐ๊ณผ ์ฌ์ฉ์์ 95๋ฒ์งธ ๋ฐฑ๋ถ์์์ ํด๋นํ๋ ์ ํ๋ฆฌ์ผ์ด์
์์ ์๊ฐ์ด ๊ฐ์ํ๊ธฐ ์์ํ๊ณ ๋ ์ด์ ์ฆ๊ฐํ์ง ์๋ ๊ฒ์ ํ์ธํ์ต๋๋ค.
1์ผ ์ฐจํธ๋ฅผ ๋ณด๋ฉด _app_start ์ธก์ ํญ๋ชฉ์ด ์์ ํ ์ ์ ํด ๋ณด์ด๊ณ XNUMX์ด ๋ฏธ๋ง์
๋๋ค.
๋ํ _app_start์ ์ค์๊ฐ์ด 5์ด๋ฅผ ์ด๊ณผํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก Firebase๊ฐ ์๋ฆผ์ ๋ณด๋ธ๋ค๋ ์ ๋ ์ถ๊ฐํ ๊ฐ์น๊ฐ ์์ต๋๋ค. ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ๊ฐ ๋ณผ ์ ์๋ฏ์ด ์ด๊ฒ์ ์์กดํด์๋ ์ ๋๋ฉฐ, ๋ค์ด๊ฐ์ ๋ช ์์ ์ผ๋ก ํ์ธํด์ผ ํฉ๋๋ค.
Realm ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํน๋ณํ ์ ์ ๋น๊ด๊ณํ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ผ๋ ๊ฒ์ ๋๋ค. ์ฌ์ฉ ํธ์์ฑ, ORM ์๋ฃจ์ ๋ฐ ๊ฐ์ฒด ์ฐ๊ฒฐ๊ณผ์ ์ ์ฌ์ฑ์๋ ๋ถ๊ตฌํ๊ณ ๊ณ๋จ์ ์ญ์ ๊ธฐ๋ฅ์ด ์์ต๋๋ค.
์ด๋ฅผ ๊ณ ๋ คํ์ง ์์ผ๋ฉด ์ค์ฒฉ๋ ๊ฐ์ฒด๊ฐ ๋์ ๋์ด "๋์ถ"๋ฉ๋๋ค. ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ์ง์์ ์ผ๋ก ์ฆ๊ฐํ๋ฏ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ ์ ํ๋ ์์์ ์ํฅ์ ๋ฏธ์นฉ๋๋ค.
Realm์์ ๊ฐ์ฒด๋ฅผ ๋น ๋ฅด๊ฒ ์ญ์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํ ๊ฒฝํ์ ๊ณต์ ํ์ต๋๋ค. ์ด ๋ฐฉ๋ฒ์ ์์ง ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋์ง๋ ์์ง๋ง ์ค๋ซ๋์ ์ด์ผ๊ธฐ๋์ด ์์ต๋๋ค.
์ด ๊ธฐ๋ฅ์ ์๋ฐํ ๋ฑ์ฅ์ ๋ํ ๋
ผ์์๋ ๋ถ๊ตฌํ๊ณ Realm์์๋ ๊ณ๋จ์ ์ญ์ ๊ธฐ๋ฅ์ด ์๋๋ก ์ค๊ณ๋์์ต๋๋ค. ์๋ก์ด ์ ํ๋ฆฌ์ผ์ด์
์ ๋์์ธํ๋ ๊ฒฝ์ฐ ์ด ์ ์ ๊ณ ๋ คํ์ญ์์ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฏธ Realm์ ์ฌ์ฉํ๊ณ ๊ณ์๋ค๋ฉด ์ด๋ฐ ๋ฌธ์ ๊ฐ ์๋์ง ํ์ธํด ๋ณด์ธ์.
์ถ์ฒ : habr.com