๐ฑ Today I Learned (์ง์ค์๊ฐ: 9์๊ฐ 30๋ถ)
- (01:00 ~ 06:00 / 5์๊ฐ) ๊ฐ์ธ๊ณผ์ ํ์ ๊ตฌํ ํ ์ทจ์นจ
- (09:30 ~ 10:30 / 1์๊ฐ) ์๊ณ ๋ฆฌ์ฆ ํ์ด ๋ฐ ํ ๋ฐ์ผ๋ฆฌ ์คํฌ๋ผ
- (16:40 ~ 18:20 / 1์๊ฐ 40๋ถ) ์๊ณ ๋ฆฌ์ฆ ์์ฑ ๋ฐ ์ ๋ฆฌ, Git SourceTree ํน๊ฐ
- (18:20 ~ 20:10 / 1์๊ฐ 50๋ถ) ๋น๊ทผ๋ง์ผ ๊ฐ์ธ๊ณผ์ ์์ : Adapter, Parcelize๋ก ๊ฐ ๋๊ฒจ์ฃผ๊ธฐ ๊ตฌํ ์ค
*** ์ ์ฌ 13:00 ~ 14:00 / ์ ๋ 18:00 ~ 19:00 ์ ์ธ
โ
๐ ์ด๋ฒ ์ฃผ ๋ชฉํ
[V] ์๋ จ ๊ฐ์ ๋ค ๋ฃ๊ธฐ[ ] ์คํ ๋ค๋ 2์ฃผ์ฐจ ์ฌํ ๊ตฌํ : ์๋ จ ๊ฐ์ ์ฒดํ(fragment, fragment ๊ฐ์ ๋ฐ์ดํฐ์ ๋ฌ) ํฌ๊ธฐ[V] ์คํ ๋ค๋๋ฐ ๋ฐ๋ฆฐ ๊ฐ์ ๋ฃ๊ธฐ[V] ์ ๋ฌธ ๊ฐ์ธ ๊ณผ์ ํด์ค ํ์ต[V] ๋ฒ ์ด์ง๋ฐ ๊ฐ์ 4์ฃผ์ฐจ๊น์ง[V] ์คํ ๋ค๋ 4์ฃผ์ฐจ ๊ณผ์ ๊ตฌํ[V] ์๋ จ ๊ฐ์ธ ๊ณผ์ ํ์ ๊ตฌํ : ์๋ จ ๊ฐ์ ์ฒดํ(notification, dialog, recyclerview, fragment ์ข ํฉ)- [ ] ์คํ ๋ค๋๋ฐ 5์ฃผ์ฐจ MVVM ๊ณผ์ ๊ตฌํ
- [ ] ์ ์ฐฝ๊ฒฝ ๋ด์ฉ ์ ๋ฆฌ
- [ ] ๋ฐ๋ฆฌ์ ์์ฌ ์๋๋ก์ด๋ ์์ ์ง๋ ๋ถ๋ถ๊น์ง ๋ค ํ๊ธฐ
- [ ] Fragment ์ฌ์ด์ ๋ฐ์ดํฐ ์ ์ก์ ๊ตฌํํ ๊ฐ์ธ ํ๋ก์ ํธ
- [ ] ์๊ณ ๋ฆฌ์ฆ ์ง์ค ์ฝ๋์นดํ
- [ ] ๋งํฌ ์๊ฐ
- [ ] (์ฌํ) KIA ๊ฐ๋ ํ๊ธฐ
- [ ] (์ฌํ) Android Developer ์ฝ๊ธฐ
- [ ] (์ฌํ) ๊ฐ์ธํ๋ก์ ํธ UI ๊ตฌํ
- [ ] (์ฌํ) ์ ๋ฒ ํ๋ก์ ํธ ์ฝ๋ ๋ฏ์ด๋ณด๊ธฐ
โ
1. ํ๋ก๊ทธ๋๋จธ์ค ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ํ์ด (ํฌ๊ธฐ๊ฐ ์์ ๋ถ๋ถ ๋ฌธ์์ด)
[kotlin] ํฌ๊ธฐ๊ฐ ์์ ๋ถ๋ถ๋ฌธ์์ด (ํ๋ก๊ทธ๋๋จธ์ค ์๊ณ ๋ฆฌ์ฆ) : substring(), windowed()
๋ฌธ์ https://school.programmers.co.kr/learn/courses/30/lessons/147355 ์ฑ๊ณต ์ฝ๋ class Solution { fun solution(t: String, p: String): Int { var count = 0 // p์ ๊ธธ์ด ๋งํผ, t์ ๋ฌธ์์ด์ ๋ฝ์์ ๋น๊ต for (i in 0 .. t.length - p.length){ va
limheejin.tistory.com
- substring()์ ์ด์ฉํ ํ์ด๊ฐ ์ผ๋ฐ์ ์ด์๋ค.
- ๋ค๋ฅธ ์ฌ๋์ ํ์ด๋ฅผ ํตํด windowed()๋ผ๋ ํจ์๋ฅผ ์ฒ์ ์์๋ค.
๐ก substring()
val str = "Hello, world!"
val result1 = str.substring(7) // "world!"
val result2 = str.substring(7, 12) // "world"
val result3 = str.substring(7..11) // "world"
- ๋ฌธ์์ด์์ ํน์ ๋ถ๋ถ ๋ฌธ์์ด์ ์ถ์ถํ๋๋ฐ ์ฌ์ฉํ๋ ๋ฉ์๋
- substring(startIndex: Int): String: ์์ ์ธ๋ฑ์ค๋ถํฐ ๋ฌธ์์ด์ ๋๊น์ง ์ถ์ถ
- substring(startIndex: Int, endIndex: Int): String: ์์ ์ธ๋ฑ์ค๋ถํฐ ๋ ์ธ๋ฑ์ค๊น์ง ์ถ์ถ
- substring(range: IntRange): String: ์ง์ ๋ ๋ฒ์์ ํด๋นํ๋ ๋ถ๋ถ ๋ฌธ์์ด์ ์ถ์ถ
๐กmap
val numbers = listOf(1, 2, 3, 4, 5)
val squaredNumbers = numbers.map { it * it }
println(squaredNumbers) // ์ถ๋ ฅ: [1, 4, 9, 16, 25]
- ๊ฐ ์์๋ฅผ ์ฃผ์ด์ง ๋๋ค ํจ์์ ์ ์ฉํ์ฌ ์๋ก์ด ์ปฌ๋ ์ ์ ์์ฑํ๋ค.
- ๊ธฐ์กด ์ปฌ๋ ์ ์ ๊ฐ ์์์ ๋ํด ์ฃผ์ด์ง ๋๋ค ํจ์๊ฐ ์ ์ฉ๋ ๊ฒฐ๊ณผ๋ฅผ ๋ด์ ์๋ก์ด ์ปฌ๋ ์ ์ ๋ฐํํ๋ค.
๐กwindowed()
fun <T> Iterable<T>.windowed(
size: Int,
step: Int = 1,
partialWindows: Boolean = false
): List<List<T>>
val list = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// ์๋์ฐ ํฌ๊ธฐ๊ฐ 3์ด๊ณ , ์ด๋ ๊ฑฐ๋ฆฌ๊ฐ 1์ธ ๊ฒฝ์ฐ
val result1 = list.windowed(size = 3, step = 1)
// ๊ฒฐ๊ณผ: [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8, 9], [8, 9, 10]]
// ์๋์ฐ ํฌ๊ธฐ๊ฐ 4์ด๊ณ , ์ด๋ ๊ฑฐ๋ฆฌ๊ฐ 2์ธ ๊ฒฝ์ฐ
val result2 = list.windowed(size = 4, step = 2)
// ๊ฒฐ๊ณผ: [[1, 2, 3, 4], [3, 4, 5, 6], [5, 6, 7, 8], [7, 8, 9, 10]]
// ์๋์ฐ ํฌ๊ธฐ๊ฐ 2์ด๊ณ , ์ด๋ ๊ฑฐ๋ฆฌ๊ฐ 3์ธ ๊ฒฝ์ฐ
val result3 = list.windowed(size = 2, step = 3)
// ๊ฒฐ๊ณผ: [[1, 2], [4, 5], [7, 8], [10]]
// ๋ถ๋ถ ์๋์ฐ ํฌํจ
val result4 = list.windowed(size = 3, step = 2, partialWindows = true)
// ๊ฒฐ๊ณผ: [[1, 2, 3], [3, 4, 5], [5, 6, 7], [7, 8, 9], [9, 10]]
// ์๋์ฐ ํฌ๊ธฐ๋ง ์ค์ , ์ด๋ ๊ฑฐ๋ฆฌ๋ ๊ธฐ๋ณธ 1๋ก ์ค์ ๋จ
val result5 = list.windowed(3)
// ๊ฒฐ๊ณผ : [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7], [6, 7, 8], [7, 8, 9], [8, 9, 10]]
- ์ฃผ์ด์ง ํฌ๊ธฐ์ ์ฐฝ์ ์ด๋ํ๋ฉด์ ์ปฌ๋ ์ ์ ๋ถํ ํ๋๋ฐ ์ฌ์ฉ
- ๋ฐํ ๊ฐ์ ์ฃผ์ด์ง ํฌ๊ธฐ์ ๋ถ๋ถ ์ปฌ๋ ์ ๋๋ ์๋์ฐ
- size: ์์ฑํ ๊ฐ ์๋์ฐ์ ํฌ๊ธฐ๋ฅผ ๋ํ๋ด๋ ๊ฐ
- step: ์๋์ฐ๋ฅผ ์ด๋์ํค๋ ๊ฐ๊ฒฉ์ ๋ํ๋ด๋ ๊ฐ. ๊ธฐ๋ณธ๊ฐ์ 1์ด๋ฉฐ, ์ด๋ ํ ๋ฒ์ ํ ์์์ฉ ์ด๋ํจ์ ์๋ฏธ
- partialWindows: ๋ง์ง๋ง ๋ถ๋ถ ์๋์ฐ์ ํฌ๊ธฐ๊ฐ size๋ณด๋ค ์์ ๋, ์ด ๋ถ๋ถ ์๋์ฐ๋ฅผ ํฌํจํ ์ง ์ฌ๋ถ๋ฅผ ๊ฒฐ์ ํ๋ ๋ถ๋ฆฌ์ธ ๊ฐ. ๊ธฐ๋ณธ๊ฐ์ false์ด๋ฉฐ, ์ด ๊ฒฝ์ฐ ๋ถ๋ถ ์๋์ฐ๋ ํฌํจ๋์ง ์์
2. ๊ฐ์ธ๊ณผ์ ๊ตฌํ
๐จ ๋ค๋ก๊ฐ๊ธฐ ๋ฒํผ ํด๋ฆญ์ ๋ค์ด์ผ๋ก๊ทธ ์ถ๋ ฅ ๋ฌธ์
override fun onBackPressed() {
var builder = AlertDialog.Builder(this)
builder.setTitle("์ข
๋ฃ")
builder.setMessage("์ ๋ง ์ข
๋ฃํ์๊ฒ ์ต๋๊น?")
builder.setIcon(R.mipmap.ic_launcher)
val listener = object : DialogInterface.OnClickListener{
override fun onClick(dialog: DialogInterface?, which: Int) {
when (which){
DialogInterface.BUTTON_POSITIVE -> finish()
DialogInterface.BUTTON_NEGATIVE -> dialog?.dismiss()
}
}
}
builder.setPositiveButton("ํ์ธ", listener)
builder.setNegativeButton("์ทจ์", listener)
builder.show()
}
- ๋ค๋ก๊ฐ๊ธฐ๋ฅผ ํด๋ฆญํ์ ๋, ๋ฐ๋ก ์กํฐ๋นํฐ๊ฐ ๊บผ์ง์ง ์๊ณ ๋ค์ด์ผ๋ก๊ทธ๋ฅผ ๋ ธ์ถ์ํค๊ธฐ ์ํ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
- ๋ค๋ง ์ด ์ฝ๋๋ก ์๋์ ํ๋๋ฐ, onBackPressed()๊ฐ deprecated ๋์ด ๊ณ์ ๋นจ๊ฐ์ค์ด ๋ด๋ค.
- deprecated๋์ง ์์ ๋ฐฉ์์ผ๋ก ์์ ํด์ผ ํ๋ค.
๐จ Notification ์๋ ์ค๋ฅ ๋ฌธ์
- ๊ฐ์๋ ๊ณต์ ๋ฌธ์์ ๋์ ์๋ ๋ฐฉ๋ฒ์ผ๋ก ๊ณ์ ์๋์ ์ํด์ ์ฐพ์๋ดค๋๋, notificationChannel์ ๋ง๋๋ ํจ์์ ์๋ก์ด Notification์ ๋ง๋๋ ํจ์๋ฅผ ๋ถ๋ฆฌํด์ ์ฑ๋id๊ฐ ๋ฌ๋ผ์ ธ ์๊ธด ๋ฌธ์ ๋ก ์ถ์ธก๋๋ค.
- ์ ํํ ๋ฌธ์ ๋ ๋ชจ๋ฅด๊ฒ ์ง๋ง, ํน์๋ ํด์ ๋ ๊ฐ๋ฅผ ํ๋์ ํจ์๋ก ํฉ์ณ์ฃผ๊ณ , channelID๋ฅผ ์คํธ๋ง์ ๋ฃ์ด์ฃผ์ง ์๊ณ ๊ทธ๋ฅ ํจ์ ๋ด์์ ์์ฒด์ ์ผ๋ก ์ ์ธํ๊ณ ๋์ผํ๊ฒ ๋ฃ์ด์ฃผ๋ ์ ์์ ์ผ๋ก ์๋ํ์๋ค.
- ์ String ๊ฐ์ผ๋ก ์ง์ ํ์ฌ ๋ค ๊ฐ์ด ๋๋ ์ธ ์ ์๋์ง๋ ๋ชจ๋ฅด๊ฒ ๋ค.
๋ฐฉ๋ฒ์ ๋ฌธ์ ์ผ ๊ฒ ๊ฐ์๋ฐ, ์ข ๋ ์ฐพ์๋ด์ผ๊ฒ ๋ค. - ํ์ฌ๋ notification ๊ถํ์ ์๋์ผ๋ก ํ์ฉํด์ผ๋ง ์๋ฆผ์ด ์๋๋๋ค. ๋ฐ๋ผ์ ์๋ฆผ์ ํด๋ฆญํ๋ฉด ์๋์ผ๋ก ๊ถํ ๋ถ์ฌ ์ฌ๋ถ๋ฅผ ํ์ธํ๊ณ , ์๋ ๊ฒฝ์ฐ ๊ถํ๋ถ์ฌ์ฐฝ์ด ๋จ๋ ๊ฒ์ ๊ตฌํํ๋ ค๊ณ ํ๋๋ฐ ์๊ฐ์ด ๋ชจ์๋๋ค. ๋ค์ ์ฐพ์๋ด์ผ ํ๋ค.
๐จ RecyclerView ์ฌ์ด์ ๊ตฌ๋ถ์ ์ถ๊ฐ (DividerItemDecoration)
- ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ ์์ดํ ์ฌ์ด์ ๊ตฌ๋ถ์ ์ ์ฝ์ ํ๊ธฐ ์ํด์๋ ์ด๋ฏธ ์ ์๋์ด ์๋ DividerItemDecoreation์ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ItemDecoration์ ์์๋ฐ์ ํ ์ค๋ฒ๋ผ์ด๋๋ฅผ ํด์ค์ผ๋ก์จ Custom ํ ๊ตฌ๋ถ์ ์ฝ์ ๋ ๊ฐ๋ฅํ๋ค.
- ๊ธฐ์กด xml์์์ View๋ก ๊ตฌํํ๋ ๋ถ๋ถ์ ์ญ์ ํ๊ณ , DividerItemDecoration์ ์ ์ฉํด์ฃผ์๋ค.
๐จ ์๋ฆผ ๊ถํ ํ์ฉํ๊ธฐ
- NotificationManagerCompat์ areNotificationsEnabled()๋ฅผ ์ด์ฉ
๐ฅ๏ธ DecimalFormat ์ด์ฉ
๐ฅ๏ธ UI ํ์ธ ๋ฐ notification
3. Git SourceTree ํน๊ฐ
- ํ์์ ์ผ๋ก ์ฌ๋ฌ ๋ฒ ์ฐ๊ฒ๋๋ ๋ช ๋ น์ด: Commit / push / pull / request / merger
- Git ํ์ต ์ฌ์ดํธ: https://learngitbranching.js.org/
- origin: ์๊ฒฉ ์ ์ฅ์
master: ๊ธฐ๋ณธ์ ์ธ ๋ธ๋์น
HEAD: ํ์ฌ ์์ ๊ณต๊ฐ - git rebase์ merge์ ์ฐจ์ด?
๐จ ํํ Git ๋ฌธ์ ๋ฐ์ ์์ธ
- ํ์ฌ HEAD ๊ฐ ๊ฐ๋ฆฌํค๋ Branch๋ฅผ ํ์ธํ์ง ์๋ ๊ฒฝ์ฐ ( Main/Dev ์ธ์ง ํ์ธํ๊ธฐ )
- ์ฝ๋ ์์ฑ์ด ์๋ฃ ๋์ง ์์ ์ํ์์ git ๋ช ๋ น์ ๋ด๋ฆฌ๋ ๊ฒฝ์ฐ ( git ์์ ์ ํ๋ ์์ ๋ง๋ฌด๋ฆฌ๋ ํ์ )
- ๊ฐ์ ธ์ค๊ณ ์ ํ๋ Branch ์ ์ ๋ฐ์ดํธ๋ฅผ ํ์ธํ์ง ์๊ณ merge ํ๋ ๊ฒฝ์ฐ (git ์์ ์ Tracking ํ๊ณ ์๋ Branch ์ ์ ๋ฐ์ดํธ ํ์ )
๐จ Git ์ถฉ๋ ๋ฐฉ์ง
- Commit ๋์ง ์์ ์์ค๊ฐ ์๋ ์ง ํ์ธ (git status ๋ฑ ์ด์ฉ)
- Main/Dev Branch Origin ์ ๋ณ๊ฒฝ์ ์ด ์๋์ง Pull
- Merge ํ๋ ๊ณผ์ ์์ ์์ค ์ถฉ๋ ๋ฐ์์ ์ ํด์ง ๋ฃฐ์ ๋ฐ๋ผ ์ฒ๋ฆฌํ๊ฑฐ๋ ๋ค๋ฅธ ๊ฒฝ์ฐ ์์ฌ์ํต์ ์งํ
- gitignore ์ค์ , gitignore ํ์ผ์ ์ถ๊ฐํ๊ณ ์ถ์ ํ์ฅ์ ์ ๋ ฅ (์ฃผ์ํด์ผ ํ๋ ๋ถ๋ถ์ด๋ฏ๋ก ํ๋ฌ๊ทธ์ธ ์ต๋ํ ํ๋ํ๊ธฐ)
- ํ์๋ค๊ณผ Platforms, SDK Tools ์๋ก์ ์ค์น ์ํฉ์ ๊ณต์ ํ์ฌ ํต์ผ
> Show Package Details ํ์ฑํ ํด์ ์ฐจ์ด์ ํ์ธ - ๊ณตํต์ ์ผ๋ก ์ฌ์ฉํ๊ณ ๊ด๋ฆฌํ๋ ํ์ผ ๊ฐ์ ๊ฒฝ์ฐ ๋จผ์ ์๊ธฐ๋ฅผ ๋๋๋ ๊ฒ ์ข์
- Manifest.xml (Permission, Activity, Application) ํ์ผ
- Resource Folder(String, Color, Style Theme...) - ํญ์ ๋ธ๋์น๋ฅผ ๊ฐ์ ์์ฑํด์ ์์ ํ PR, Merge ์งํ
๐จ gitignore ์ค์ ๋ฐฉ๋ฒ
- 1) ์ฌ์ดํธ ์ด์ฉ (https://www.toptal.com/developers/gitignore)
- 2) android studio .ignore plugin ์ค์นํ๊ธฐ
์ด๋ฏธ ์ ๋ฒ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉฐ ํฐ๋ฏธ๋/์๋๋ก์ด๋ ์คํ๋์ค ๋ด์ Git ํญ/Git Bash ๋ฑ์ ์ต์ํด์ ธ์ ์์ง๊น์ง๋ GUIํด์ ํ์์ฑ์ ๋ํด์ ์ ํํ๋ ๋ชจ๋ฅด๊ฒ ๋ค. ๋๊ธฐ์ ๊ฐ์ ๊ฒฝ์ฐ์๋ ์ฐ๋ ํด์ด ์ ํด์ ธ ์์ ์๋ ์๋๋ฐ, ํ์ฌ๋ง๋ค ์ฐ๋ GUIํด์ด ๋ค๋ฅด๊ธฐ๋ ํ๊ณ ๊ฒฐ๊ตญ์ ๊นํ๋ธ์ ์ฌ๋ผ๊ฐ๋ ๊ฒ์ ๋๊ฐ๊ธฐ์ ํธํ๊ฑฐ ์ ์ฐ๋ ๊ฒ ์ ์ผ ์ข๋ค๊ณ ํ๋ค.
๐ญ Retrospect
์ด๋ฒ์ฃผ ๋ชฉํ๋ ๋๋ถ๋ถ ๋ค ๊ณํ๋๋ก ์ํ์ด ๋ ๊ฒ ๊ฐ๋ค.
์ถ๊ฐ์ ์ผ๋ก ๋ ํ์ํ๋ค๊ณ ์๊ฐํ๊ฑฐ๋, ์ฌํ์ ์ธ ๊ตฌํ์ ์ฃผ๋ง๋์ ์ํํ ์์ ์ด๋ค.
์ค๋๋ง์ ์บ ํ๊ฐ ์์ํ๋ ๋๋ถํฐ ์ง๊ธ๊น์ง์ TIL์ ์ญ ์ฝ์ด๋ณด์๋ค. ์ธ์ ๋ญ ์ฒ์ ๋ฐฐ์ ๊ณ , ์ด๋ค ๋๋์ ๋ฐ์๊ตฌ๋, ์ด๋ค ํ๊ณ ๋ฅผ ํ๊ตฌ๋๋ฅผ ์ ์ ์์ด์ ์ฐธ ์ ์ตํ๋๋ผ. ์ค์ค๋ก๋ฅผ ๋์๋ณผ ์ ์๋ ๋ฐ์์ทจ๊ฐ ๋จ๊ฒจ์ง๊ณ ์๋ ๋๋. ๋ด๊ฐ ๋์ค์ ์ด๋ค ๋ถ์ผ์ ๋ฅํ๊ฒ ๋ฐ์ ๋ค์ฌ๋์ ์ง๋ ๋ชจ๋ฅด์ง๋ง, ์ด๋ ๋ถ์ผ๋ฅผ ๊ฐ์๋ ์ต์ํ WIL์ ์์ฑํ ๊ฒ ๊ฐ๋ค.
โ