20 ๋ถ„ ์†Œ์š”

๐Ÿ“ย ํ•™์Šต ๋ชฉํ‘œ


  1. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ดํ•ดํ•œ๋‹ค.
  2. iOS์—์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ตฌ์ถ•ํ•˜๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. UserDefaults๋ฅผ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

โœ๐Ÿปย ์ˆ˜์—… ๋‚ด์šฉ ์ •๋ฆฌ


DB๋ฅผ ๊ณ„์ขŒ๋กœ ์„ค๋ช… 1

์€ํ–‰์˜ ๊ณ ๊ฐ์ด ATM์„ ํ†ตํ•ด ํ˜„๊ธˆ์„ ์ธ์ถœํ•œ๋‹ค

์„œ๋น„์Šค ์ด์šฉ ๊ณผ์ •์—์„œ DBMS์— ์ ‘๊ทผํ•˜๊ณ  DBMS์—์„œ ๊ณ ๊ฐ ์ •๋ณด๋ฅผ ์ˆ˜์ •ํ•ด์„œ ๋ˆ์„ ๋น ์ ธ๋‚˜๊ฐ€๊ฒŒ ํ•œ๋‹ค.

DBMS๋Š” DB๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” sw

DBMS๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์ผ ํ˜•ํƒœ๋กœ ๋‹ค๋ฃจ๋Š”๋ฐ

๋ฐ์ดํ„ฐ๊ฐ€ ๋ˆ๊ณผ ๊ด€๋ จ๋˜์–ด์žˆ๊ธฐ์— ๋ณด์•ˆ ์ƒ์— ํฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜๋„ ์žˆ์–ด์„œ

๋‹จ์ ์„ ๋ณด์™„ํ•œ RDBMS๊ฐ€ ํƒ„์ƒํ–ˆ๋‹ค. 2

์ด๋•Œ R๋Š” relational ๊ด€๊ณ„ํ˜•์ด๋ž€ ๋œป์ด๋‹ค

๋ง ๊ทธ๋Œ€๋กœ ๋ฐ์ดํ„ฐ๋“ค์ด ๊ด€๊ณ„๋ฅผ ์ง€๋‹ˆ๊ฒŒ ๋๋‹ค.

์ „์—๋Š” ๊ฐ๊ฐ ํŒŒ์ผ ํ˜•ํƒœ์˜€๋Š”๋ฐ

์ด์   ํ…Œ์ด๋ธ”์ด๋ž€ ๊ฐœ๋…์„ ํ†ตํ•ด ๊ด€๋ฆฌ๋œ๋‹ค.

์ด ํ…Œ์ด๋ธ”๋ผ๋ฆฌ ๊ด€๊ณ„์„ฑ์„ ๋„๊ณ  ์žˆ๋‹ค.

์ €๊ธฐ ์˜ค๋ฅธ์ชฝ ํ…Œ์ด๋ธ”์˜ ํšŒ์ƒ‰ ๊ธ€์”จ๊ฐ€ ๋ณด์ด๋Š”๊ฐ€

ํ…Œ์ด๋ธ”๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด์„œ ๋‚˜ํƒ€๋‚œ ํ‚ค๋ž€ ๊ฐœ๋…์ด๋‹ค.

์ด RDBMS ์ƒ์˜ ํ…Œ์ด๋ธ”์„ ๊ด€๋ฆฌํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์–ธ์–ด๊ฐ€

์šฐ๋ฆฌ๊ฐ€ ์ตํžˆ ๋“ค์–ด๋ณธ

SQL์ด๋‹ค

SQL(Structured Query Language) 3

์•ฑ์„ ๊บผ๋„ ๋ฐ์ดํ„ฐ ์กด์žฌํ•˜๋„๋กโ†’ UserDefaults ์‚ฌ์šฉ

๐ŸŽฏย ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ


  • DB

    ์ค„์—ฌ์„œ

    DB

    ํŠน์ • ๋‹ค์ˆ˜์˜ ์ด์šฉ์ž๋“ค์—๊ฒŒ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค๋“ ์ง€ ์กฐ์ง ๋‚ด์—์„œ ํ•„์š”๋กœ ํ•˜๋Š” ์ •๋ณด๋ฅผ ์ฒด๊ณ„์ ์œผ๋กœ ์ถ•์ ํ•˜์—ฌ ๊ทธ ์กฐ์ง ๋‚ด์˜ ์ด์šฉ์ž์—๊ฒŒ ํ•„์š”ํ•œ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” ์ •๋ณด ์„œ๋น„์Šค ๊ธฐ๊ด€์˜ ์‹ฌ์žฅ๋ถ€์— ํ•ด๋‹น๋œ๋‹ค.

    ์ผ๋ฐ˜์ ์œผ๋กœ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ๊ณผ๋Š” ๋ณ„๊ฐœ์˜ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ํ†ตํ•ด์„œ ๊ด€๋ฆฌ๋œ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž์ฒด๋งŒ์œผ๋กœ๋Š” ๊ฑฐ์˜ ์•„๋ฌด ๊ฒƒ๋„ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๊ฑธ ๊ด€๋ฆฌํ•˜๋Š” ์‹œ์Šคํ…œ๊ณผ ํ†ตํ•ฉ๋ผ ์ œ๊ณต๋˜๋ฉฐ ๋”ฐ๋ผ์„œ ์ •ํ™•ํ•œ ๋ช…์นญ์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ์‹œ์Šคํ…œDBMS์ด ๋œ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋งŒ ์ œ๊ณต๋˜๋Š” ๊ฑด CSV ๊ฐ™์ด ์•„์ฃผ ๋‹จ์ˆœํ•œ ๋ฐ์ดํ„ฐ์— ๊ตญํ•œ๋˜๋Š”๋ฐ ์ด๊ฑธ ์ง์ ‘ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ๋งŽ์ง€ ์•Š๊ณ  ์ด๋Ÿฐ ๋ฐ์ดํ„ฐ๋ฅผ RAW๋ฐ์ดํ„ฐ๋กœ ๊ฐ„์ฃผํ•ด ๋‹ค๋ฅธ DBMS์‹œ์Šคํ…œ์— ์ ์žฌํ•˜๊ณ  ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ผ๋ฐ˜์ ์ด๋‹ค.

    ๊ฐ„๋‹จํžˆ ๋น„์œ ํ•˜์ž๋ฉด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ž์ฒด๋Š” ํ™”๋ฌผ(๋ฐ์ดํ„ฐ)์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ์ฐฝ๊ณ  ๊ทธ ์ž์ฒด์˜ ์—ญํ• ๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ , ํ™”๋ฌผ์„ ์ ์žฌํ•˜๊ฑฐ๋‚˜ ์ ์žฌ๋œ ํ™”๋ฌผ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์€ ์—†๋‹ค. ์ด ๋•Œ๋ฌธ์— DBMS๋ผ๋Š” ๊ด€๋ฆฌ์ž๋“ค์„ ๊ณ ์šฉํ•˜์—ฌ ํ™”๋ฌผ์„ ์ ์žฌํ•˜๊ฑฐ๋‚˜ ์ด๋™์‹œํ‚ค๋Š” ๋“ฑ ํฌ๋ ˆ์ธ๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์—…๋ฌด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(RDBMS)๊ฐ€ ๊ฐ€์žฅ ๋„๋ฆฌ ์“ฐ์ด๊ณ  ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•œ ํ‘œ์ค€ ์–ธ์–ด๊ฐ€ ๋งŒ๋“ค์–ด์ ธ ์žˆ๋Š”๋ฐ ๊ทธ๊ฒƒ์ด SQL์ด๋‹ค. ๊ตฌ์กฐํ™” ์งˆ์˜ ์–ธ์–ด(Structured Query Language)์˜ ์•ฝ์ž. ์˜ˆ์ „์—๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋Œ€๋ช…์‚ฌ์ฒ˜๋Ÿผ ์—ฌ๊ฒจ์กŒ์œผ๋‚˜ ์š”์ฆ˜์—๋Š” ๋‹ค๋ฅธ ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋„ ๋งŽ์ด ๋‚˜์™€์žˆ๋‹ค. ๊ฐ€ํžˆ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ถ˜์ถ”์ „๊ตญ์‹œ๋Œ€. ์ด๋Ÿฐ ๋น„-๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” NoSQL์ด๋ผ ๋ถˆ๋ฆฐ๋‹ค.

    SQL์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ๋Š” ๋‹ค์†Œ ์žฅ๋‚œ์Šค๋Ÿฐ ํ‘œํ˜„. ๋ฌผ๋ก  ์ •์‹ ๋ช…์นญ์€ ๊ฐ์ž ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ฐ์ฒดํ˜•, ๋ฌธ์„œํ˜•, ์ปฌ๋Ÿผํ˜• ๋“ฑ๋“ฑ์ด ํ•ด๋‹น๋œ๋‹ค.

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด ๋งŒ๋“ค์–ด์ง„ SQL๋ฌธ์€ ๋ฐฐ์›Œ ๋‘๋ฉด ์—ฌ๋Ÿฌ๋ชจ๋กœ ์“ธ ๋ฐ๊ฐ€ ๋งŽ๋‹ค.

    ์ปดํ“จํ„ฐ๋กœ ํ•˜๋Š” ์ผ์—์„œ ๋Œ€๋ถ€๋ถ„์„ ์ฐจ์ง€ํ•˜๋Š” ์ž‘์—…์€ ๋ฐ”๋กœ ์ •๋ ฌ๊ณผ ํƒ์ƒ‰์ธ๋ฐ ์ด ๋‘ ์ž‘์—…์„ ๊ฐ€์žฅ ์ „๋ฌธ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฑด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์ด๋‹ค. ์ปดํ“จํ„ฐ๋กœ ๊ณ„์‚ฐ์„ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ์˜์™ธ๋กœ ์ •๋ ฌ๊ณผ ํƒ์ƒ‰์— ๋น„ํ•˜๋ฉด ๋น„์ค‘์ด ๋‚ฎ์€ ํŽธ์ด๋‹ค.

    https://namu.wiki/w/๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

  • DBMS

    ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ผ๋Š” ๋ฐ์ดํ„ฐ์˜ ์ง‘ํ•ฉ์„ ๋งŒ๋“ค๊ณ , ์ €์žฅ ๋ฐ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ๋“ค์„ ์ œ๊ณตํ•˜๋Š” ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค. ์ฆ‰,ย ๋ฐ์ดํ„ฐ์˜ ๊ด€๋ฆฌ์— ํŠนํ™”๋œ ํ”„๋กœ๊ทธ๋žจ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ํŽธํ•˜๋‹ค. ์ข…๋ฅ˜์— ๋”ฐ๋ผ DataBase Server๊นŒ์ง€ ์ง€์›ํ•˜๊ธฐ๋„ ํ•œ๋‹ค.์ฃผ๋กœ ์„œ๋ฒ„์— ์‚ฌ์šฉํ•˜๋Š” ์šฉ๋„๋งŒ DBMS๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ์˜ค๊ฐœ๋…์ด ๋งŽ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ย Microsoft Access๋ผ๋Š” ๊ฐœ์ธ์šฉ ์ปดํ“จํ„ฐ์— ์ €์žฅํ•˜๋Š” ์šฉ๋„์˜ ํ”„๋กœ๊ทธ๋žจ๋„ ํ›Œ๋ฅญํ•œ DBMS์ด๋‹ค.ย ๋ธ”๋ฃธ๋ฒ„๊ทธย ํ„ฐ๋ฏธ๋„ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ์ž์ฒด์ ์œผ๋กœ DBMS๋ฅผ ๋‚ด์žฅํ•˜๊ณ  ์žˆ๋‹ค.

  • RDBMS

    https://cloud.google.com/learn/what-is-a-relational-database?hl=ko

    # ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ •์˜

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(RDB)๋Š” ํ…Œ์ด๋ธ”, ํ–‰, ์—ด์˜ ์ •๋ณด๋ฅผ ๊ตฌ์กฐํ™”ํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. RDB์—๋Š” ํ…Œ์ด๋ธ”์„ ์กฐ์ธํ•˜์—ฌ ์ •๋ณด ๊ฐ„ ๊ด€๊ณ„ ๋˜๋Š” ๋งํฌ๋ฅผ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ์–ด, ์—ฌ๋Ÿฌ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ณ  ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    # ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ

    ###

    1970๋…„๋Œ€ IBM์˜ EF Codd๊ฐ€ ๊ฐœ๋ฐœํ•œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ชจ๋“  ํ…Œ์ด๋ธ”์„ ๊ณตํ†ต ์†์„ฑ์„ ์‚ฌ์šฉํ•ด ๋‹ค๋ฅธ ํ…Œ์ด๋ธ”๊ณผ ์—ฐ๊ด€์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Codd๋Š” ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ •๋ฆฌํ•˜๋Š” ๋Œ€์‹  ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋œ ํ…Œ์ด๋ธ”์„ ์žฌ๊ตฌ์„ฑํ•˜์ง€ ์•Š๊ณ  ํ…Œ์ด๋ธ”์— ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ, ์•ก์„ธ์Šค ๋ฐ ์—ฐ๊ฒฐ๋˜๋Š” ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์ „ํ™˜ํ•  ๊ฒƒ์„ ์ œ์•ˆํ–ˆ์Šต๋‹ˆ๋‹ค.

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋น„์ฆˆ๋‹ˆ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์„ฑ, ๊ด€๋ฆฌ, ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์Šคํ”„๋ ˆ๋“œ์‹œํŠธ ํŒŒ์ผ ๋ชจ์Œ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์—์„œ ๊ฐ โ€˜์Šคํ”„๋ ˆ๋“œ์‹œํŠธโ€™๋Š” ์—ด(์†์„ฑ)๊ณผ ํ–‰(๋ ˆ์ฝ”๋“œ ๋˜๋Š”ย ํŠœํ”Œ)์œผ๋กœ ๋Œ€ํ‘œ๋˜๋Š” ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค.

    ์†์„ฑ(์—ด)์€ ๋ฐ์ดํ„ฐ ์œ ํ˜•์„ ์ง€์ •ํ•˜๋ฉฐ ๊ฐ ๋ ˆ์ฝ”๋“œ(๋˜๋Š” ํ–‰)๋Š” ๊ตฌ์ฒด์ ์ธ ๋ฐ์ดํ„ฐ ์œ ํ˜•์˜ ๊ฐ’์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค. ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ๋ชจ๋“  ํ…Œ์ด๋ธ”์—๋Š” ํ–‰์—์„œ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„ ๊ฐ€๋Šฅํ•œย ๊ธฐ๋ณธ ํ‚ค๋ผ๋Š” ์†์„ฑ์ด ์žˆ์œผ๋ฉฐ,ย ์™ธ๋ž˜ ํ‚ค(๋‹ค๋ฅธ ๊ธฐ์กด ํ…Œ์ด๋ธ”์˜ ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์ฐธ์กฐ)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ํ–‰์—์„œ ์„œ๋กœ ๋‹ค๋ฅธ ํ…Œ์ด๋ธ” ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ด์ œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์˜ ์‹ค์ œ ์ž‘๋™ ๋ฐฉ์‹์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    ๊ณ ๊ฐย ํ…Œ์ด๋ธ”๊ณผย ์ฃผ๋ฌธย ํ…Œ์ด๋ธ”์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    https://lh3.googleusercontent.com/_j-DAQG6tx5MwOwhdNFkHMou4fWHRuEbzYr3wEaRClkCnC3W2TR8CnMsAvmVX-rgOICpWX-wrBPc=e14-rj-sc0xffffff-h1000-w1000

    ###

    ๊ณ ๊ฐย ํ…Œ์ด๋ธ”์—๋Š” ๊ณ ๊ฐ์— ๊ด€ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

    • ๊ณ ๊ฐ ID(๊ธฐ๋ณธ ํ‚ค)
    • ๊ณ ๊ฐ ์ด๋ฆ„
    • ์ฒญ๊ตฌ์„œ ์ˆ˜์‹  ์ฃผ์†Œ
    • ๋ฐฐ์†ก์ง€ ์ฃผ์†Œ

    ๊ณ ๊ฐย ํ…Œ์ด๋ธ”์—์„œ ๊ณ ๊ฐ ID๋Š” ๊ณ ๊ฐ์ด ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ณ ์œ ํ•˜๊ฒŒ ์‹๋ณ„๋˜๋Š” ๊ธฐ๋ณธ ํ‚ค์ž…๋‹ˆ๋‹ค. ๋™์ผํ•œ ๊ณ ๊ฐ ID๋ฅผ ๊ฐ€์ง€๋Š” ๋‹ค๋ฅธ ๊ณ ๊ฐ์€ ์—†์Šต๋‹ˆ๋‹ค.

    ์ฃผ๋ฌธย ํ…Œ์ด๋ธ”์—๋Š” ์ฃผ๋ฌธ์— ๊ด€ํ•œ ๊ฑฐ๋ž˜ ์ •๋ณด๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.

    • ์ฃผ๋ฌธ ID(๊ธฐ๋ณธ ํ‚ค)
    • ๊ณ ๊ฐ ID(์™ธ๋ž˜ ํ‚ค)
    • ์ฃผ๋ฌธ ๋‚ ์งœ
    • ๋ฐฐ์†ก์ผ
    • ์ฃผ๋ฌธ ์ƒํƒœ

    ์—ฌ๊ธฐ์—์„œ ํŠน์ • ์ฃผ๋ฌธ์„ ์‹๋ณ„ํ•˜๋Š” ๊ธฐ๋ณธ ํ‚ค๋Š” ์ฃผ๋ฌธ ID์ž…๋‹ˆ๋‹ค. ์™ธ๋ž˜ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌย ๊ณ ๊ฐย ํ…Œ์ด๋ธ”์˜ ๊ณ ๊ฐ ID๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ๊ณ ๊ฐ์„ ์ฃผ๋ฌธ๊ณผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ด์ œ ๋‘ ํ…Œ์ด๋ธ”์ด ๊ณต์œ ๋œ ๊ณ ๊ฐ ID๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋‘ ํ…Œ์ด๋ธ”์„ ์ฟผ๋ฆฌํ•˜์—ฌ ๊ณต์‹ ๋ณด๊ณ ์„œ๋ฅผ ๋งŒ๋“ค๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ๋ฐ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์†Œ๋งค ์ง€์  ๊ด€๋ฆฌ์ž๋Š” ํŠน์ • ๋‚ ์งœ์— ๊ตฌ๋งคํ•œ ๋ชจ๋“  ๊ณ ๊ฐ์— ๊ด€ํ•œ ๋ณด๊ณ ์„œ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์ง€๋‚œ ๋‹ฌ์— ๋ฐฐ์†ก์ผ์ด ์ง€์—ฐ๋œ ์ฃผ๋ฌธ์„ ๋ฐ›์€ ๊ณ ๊ฐ์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์œ„์˜ ์„ค๋ช…์€ ๊ฐ„๋‹จํ•˜์ง€๋งŒ, ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฐ์ดํ„ฐ ๊ฐ„์˜ ๋งค์šฐ ๋ณต์žกํ•œ ๊ด€๊ณ„๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๋ฐ์—๋„ ํƒ์›”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์‚ฌ์ „ ์ •์˜๋œ ๊ด€๊ณ„ํ˜• ์Šคํ‚ค๋งˆ๋ฅผ ์ค€์ˆ˜ํ•˜๋Š” ํ•œ ๋” ๋งŽ์€ ํ…Œ์ด๋ธ”์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฌ์ „ ์ •์˜๋œ ๊ด€๊ณ„๋กœ ๊ตฌ์„ฑ๋˜๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์„ ์–ธ์ ์œผ๋กœ ์ฟผ๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ์–ธ์  ์ฟผ๋ฆฌ๋Š” ์‹œ์Šคํ…œ์ด ๊ฒฐ๊ณผ๋ฅผ ์–ด๋–ป๊ฒŒ ์—ฐ์‚ฐํ•ด์•ผ ํ•˜๋Š”์ง€ ํ‘œํ˜„ํ•˜์ง€ ์•Š๊ณ  ์‹œ์Šคํ…œ์—์„œ ์ถ”์ถœํ•  ๋‚ด์šฉ์„ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค๋ฅธ ์‹œ์Šคํ…œ๊ณผ ๋‹ฌ๋ฆฌ ๊ด€๊ณ„ํ˜• ์‹œ์Šคํ…œ์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค.

    # ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์˜ˆ

    ###

    ์ด์ œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ž‘๋™ ๋ฐฉ์‹์„ ์ดํ•ดํ–ˆ์œผ๋ฏ€๋กœ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜๋Š” ์—ฌ๋Ÿฌ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ์‹œ์Šคํ…œ์— ๋Œ€ํ•ด ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ด€๋ฆฌ ์‹œ์Šคํ…œ(RDBMS)์€ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์—…๋ฐ์ดํŠธํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ž…๋‹ˆ๋‹ค. ์ž˜ ์•Œ๋ ค์ง„ RDBMS์˜ ์˜ˆ๋กœ๋Š” MySQL, PostgreSQL, MariaDB, Microsoft SQL Server, Oracle Database๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

    Cloud SQL,ย Cloud Spanner,ย AlloyDB์™€ ๊ฐ™์€ ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์œ ์ง€๋ณด์ˆ˜, ํŒจ์น˜, ์šฉ๋Ÿ‰ ๊ด€๋ฆฌ, ํ”„๋กœ๋น„์ €๋‹, ์ธํ”„๋ผ ์ง€์›์„ ์œ„ํ•œ ๊ด€๋ฆฌํ˜• ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ ์  ๋” ๋งŽ์€ ์ธ๊ธฐ๋ฅผ ์–ป๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

    ์‹œ์ž‘ํ•  ์ค€๋น„๊ฐ€ ๋˜์…จ๋‚˜์š”? 10GB ์Šคํ† ๋ฆฌ์ง€๋ฅผ ํฌํ•จํ•œ 90์ผย Cloud Spanner ๋ฌด๋ฃŒ ์ฒดํ—˜ํŒ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฌด๋ฃŒ๋กœ ๋งŒ๋“œ์„ธ์š”.

    # ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ด์ 

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชจ๋ธ์˜ ์ฃผ์š” ์ด์ ์€ ์ง๊ด€์ ์ธ ๋ฐ์ดํ„ฐ ํ‘œํ˜„ ๋ฐฉ๋ฒ•์„ ์ œ๊ณตํ•˜๊ณ  ๊ด€๋ จ ๋ฐ์ดํ„ฐ ํฌ์ธํŠธ์— ์‰ฝ๊ฒŒ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ธ๋ฒคํ† ๋ฆฌ ์ถ”์ ๋ถ€ํ„ฐ ํŠธ๋žœ์žญ์…˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋กœ๊น…์— ์ด๋ฅด๊ธฐ๊นŒ์ง€ ๋Œ€๋Ÿ‰์˜ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋Š” ์กฐ์ง์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์ €์žฅํ•  ๋•Œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    ### ์œ ์—ฐ์„ฑ

    ์ „์ฒด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ๊ธฐ์กด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๊ฐ„ํŽธํ•˜๊ฒŒ ํ…Œ์ด๋ธ”, ๊ด€๊ณ„๋ฅผ ์ถ”๊ฐ€ ๋˜๋Š” ์‚ญ์ œํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ### ACID ๊ทœ์ • ์ค€์ˆ˜

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ACID(์›์ž์„ฑ, ์ผ๊ด€์„ฑ, ๊ฒฉ๋ฆฌ, ๋‚ด๊ตฌ์„ฑ) ์„ฑ๋Šฅ์„ ์ง€์›ํ•˜๋ฏ€๋กœ ์˜ค๋ฅ˜, ์‹คํŒจ, ๊ธฐํƒ€ ์ž ์žฌ์  ์˜ค์ž‘๋™์— ๊ด€๊ณ„์—†์ด ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ### ์‚ฌ์šฉ ํŽธ์˜์„ฑ

    ๊ธฐ์ˆ ์ž๊ฐ€ ์•„๋‹Œ ์‚ฌ์šฉ์ž๋„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ๋Š” SQL์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ณต์žกํ•œ ์ฟผ๋ฆฌ๋ฅผ ์‰ฝ๊ฒŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ### ๊ณต๋™์ž‘์—…

    ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๊ฐ€ ๋™์‹œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์šด์˜ํ•˜๊ณ  ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์ œ๊ณต๋˜๋Š” ์ž ๊ธˆ ๊ธฐ๋Šฅ์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋„์ค‘ ๋ฐ์ดํ„ฐ์— ๋™์‹œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

    ### ๋‚ด์žฅ๋œ ๋ณด์•ˆ ๊ธฐ๋Šฅ

    ์—ญํ•  ๊ธฐ๋ฐ˜ ๋ณด์•ˆ์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ ์•ก์„ธ์Šค๊ฐ€ ํŠน์ • ์‚ฌ์šฉ์ž๋กœ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค.

    ### ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ •๊ทœํ™”

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๋ฐ์ดํ„ฐ ์ค‘๋ณต์„ฑ์„ ์ค„์ด๊ณ  ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ๊ฐœ์„ ํ•˜๋Š” ์ •๊ทœํ™”๋ผ๋Š” ์„ค๊ณ„ ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    # ๊ด€๊ณ„ํ˜• ๋ฐ ๋น„๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค

    ###

    ๊ด€๊ณ„ํ˜• ๋ฐ ๋น„๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค(NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค)์˜ ์ฃผ์š” ์ฐจ์ด์ ์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ๋น„๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ๊ทœ์น™ ๊ธฐ๋ฐ˜์˜ ํ…Œ์ด๋ธ” ํ˜•์‹ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  ๋ฐ์ดํ„ฐ๋ฅผ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ๊ฐœ๋ณ„ ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๋ฉฐ, ๋ฌธ์„œ ๋˜๋Š” ๋ฆฌ์น˜ ๋ฏธ๋””์–ด ํŒŒ์ผ๊ณผ ๊ฐ™์€ ๋ณต์žกํ•˜๊ณ  ๊ตฌ์กฐํ™”๋˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ ์œ ํ˜•์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋‹ฌ๋ฆฌ NoSQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์œ ์—ฐํ•œ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ๋”ฐ๋ฅด๋ฏ€๋กœ ์ž์ฃผ ๋ณ€๊ฒฝ๋˜๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ๋‹ค์–‘ํ•œ ์œ ํ˜•์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

  • SQL

    https://aws.amazon.com/ko/what-is/sql/

    ## SQL์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€์š”?

    ๊ตฌ์กฐ์  ์ฟผ๋ฆฌ ์–ธ์–ด(SQL)๋Š” ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. ๊ด€๊ณ„ํ˜• ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” ์ •๋ณด๋ฅผ ํ‘œ ํ˜•์‹์œผ๋กœ ์ €์žฅํ•˜๋ฉฐ, ํ–‰๊ณผ ์—ด์€ ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ ์†์„ฑ๊ณผ ๋ฐ์ดํ„ฐ ๊ฐ’ ๊ฐ„์˜ ๋‹ค์–‘ํ•œ ๊ด€๊ณ„๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. SQL ๋ฌธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ •๋ณด๋ฅผ ์ €์žฅ, ์—…๋ฐ์ดํŠธ, ์ œ๊ฑฐ, ๊ฒ€์ƒ‰ ๋ฐ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ฑ๋Šฅ์„ ์œ ์ง€ ๊ด€๋ฆฌํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐ SQL์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  • UserDefaults

    Class UserDefaults

    An interface to the userโ€™s defaults database, where you store key-value pairs persistently across launches of your app.

    iOS 2.0+iPadOS 2.0+macOS 10.0+Mac Catalyst 13.0+tvOS 9.0+watchOS 2.0+

    ## Declaration

    class UserDefaults : [NSObject](https://developer.apple.com/documentation/objectivec/nsobject)

    ## Overview

    Theย UserDefaultsย class provides a programmatic interface for interacting with the defaults system. The defaults system allows an app to customize its behavior to match a userโ€™s preferences. For example, you can allow users to specify their preferred units of measurement or media playback speed. Apps store these preferences by assigning values to a set of parameters in a userโ€™s defaults database. The parameters are referred to asย defaultsย because theyโ€™re commonly used to determine an appโ€™s default state at startup or the way it acts by default.

    At runtime, you useย UserDefaultsย objects to read the defaults that your app uses from a userโ€™s defaults database.ย UserDefaultsย caches the information to avoid having to open the userโ€™s defaults database each time you need a default value. When you set a default value, itโ€™s changed synchronously within your process, and asynchronously to persistent storage and other processes.

    Important Donโ€™t try to access the preferences subsystem directly. Modifying preference property list files may result in loss of changes, delay of reflecting changes, and app crashes. To configure preferences, use theย defaultsย command-line utility in macOS instead.

    With the exception of managed devices in educational institutions, a userโ€™s defaults are stored locally on a single device, and persisted for backup and restore. To synchronize preferences and other data across a userโ€™s connected devices, useย [NSUbiquitousKeyValueStore](https://developer.apple.com/documentation/foundation/nsubiquitouskeyvaluestore)ย instead.

    ### Storing Default Objects

    Theย UserDefaultsย class provides convenience methods for accessing common types such as floats, doubles, integers, Boolean values, and URLs. These methods are described inย Setting Default Values.

    A default object must be a property listโ€”that is, an instance of (or for collections, a combination of instances of)ย [NSData](https://developer.apple.com/documentation/foundation/nsdata),ย [NSString](https://developer.apple.com/documentation/foundation/nsstring),ย [NSNumber](https://developer.apple.com/documentation/foundation/nsnumber),ย [NSDate](https://developer.apple.com/documentation/foundation/nsdate),ย [NSArray](https://developer.apple.com/documentation/foundation/nsarray), orย [NSDictionary](https://developer.apple.com/documentation/foundation/nsdictionary). If you want to store any other type of object, you should typically archive it to create an instance ofย NSData.

    Values returned fromย UserDefaultsย are immutable, even if you set a mutable object as the value. For example, if you set a mutable string as the value for โ€œMyStringDefaultโ€, the string you later retrieve using theย [string(forKey:)](https://developer.apple.com/documentation/foundation/userdefaults/1416700-string)ย method will be immutable. If you set a mutable string as a default value and later mutate the string, the default value wonโ€™t reflect the mutated string value unless you callย [set(_:forKey:)](https://developer.apple.com/documentation/foundation/userdefaults/1414067-set)ย again.

    For more details, seeย Preferences and Settings Programming Guide.

    ### Persisting File References

    A file URL specifies a location in the file system. If you use theย [set(_:forKey:)](https://developer.apple.com/documentation/foundation/userdefaults/1414194-set)ย method to store the location for a particular file and the user moves that file, your app may not be able to locate that file on next launch. To store a reference to a file by its file system identity, you can instead createย NSURLย bookmark data using theย [bookmarkData(options:includingResourceValuesForKeys:relativeTo:)](https://developer.apple.com/documentation/foundation/nsurl/1417795-bookmarkdata)ย method and persist it using theย [set(_:forKey:)](https://developer.apple.com/documentation/foundation/userdefaults/1414067-set)ย method. You can then use theย [URLByResolvingBookmarkData:options:relativeToURL:bookmarkDataIsStale:error:](https://developer.apple.com/documentation/foundation/nsurl/1572035-urlbyresolvingbookmarkdata)ย method to resolve the bookmark data stored in user defaults to a file URL.

    ### Responding to Defaults Changes

    You can use key-value observing to be notified of any updates to a particular default value. You can also register as an observer forย [didChangeNotification](https://developer.apple.com/documentation/foundation/userdefaults/1408206-didchangenotification)ย on theย [default](https://developer.apple.com/documentation/foundation/notificationcenter/1414169-default)ย notification center in order to be notified of all updates to a local defaults database.

    For more details, seeย Key-Value Observing Programming Guideย andย Notification Programming Topics.

    ### Using Defaults in Managed Environments

    If your app supports managed environments, you can useย UserDefaultsย to determine which preferences are managed by an administrator for the benefit of the user. In a managed environment, such as a computer lab or classroom, an administrator or teacher can configure the systems by establishing a set of default preferences for users. If a preference is managed in this manner (as determined by the methods described inย Accessing Managed Environment Keys), your app should prevent users from editing that preference by disabling or hiding controls.

    For more details, seeย Mobile Device Management Protocol Reference.

    An app running on a device managed by an educational institution can use the iCloud key-value store to share small amounts of data with other instances of itself on the userโ€™s other devices. For example, a textbook app might store the current page number being read by the user so that other instances of the app can open to the same page when launched.

    For more information, seeย Storing Preferences in iCloudย inย Preferences and Settings Programming Guide.

    ### Sandbox Considerations

    A sandboxed app cannot access or modify the preferences for any other app, with the following exceptions:

    • App extensions on macOS and iOS
    • Other apps in your application group on macOS

    Adding a third-party appโ€™s domain using theย [addSuite(named:)](https://developer.apple.com/documentation/foundation/userdefaults/1410294-addsuite)ย method doesnโ€™t allow your app to access to that appโ€™s preferences. Attempting to access or modify another appโ€™s preferences doesnโ€™t result in an error; instead, macOS reads and writes files located within your appโ€™s container, rather than the actual preference files for the other application.

    ### Thread Safety

    Theย UserDefaultsย class is thread-safe.

    ## Topics

    **Getting the Standard User Defaults Object**

    [class varย standard: UserDefaults](https://developer.apple.com/documentation/foundation/userdefaults/1416603-standard)

    Returns the shared defaults object.

    **Creating User Defaults Objects**

    [init()](https://developer.apple.com/documentation/foundation/userdefaults/1414356-init)

    Creates a user defaults object initialized with the defaults for the app and current user.

    [init?(suiteName: String?)](https://developer.apple.com/documentation/foundation/userdefaults/1409957-init)

    Creates a user defaults object initialized with the defaults for the specified database name.

    **Getting Default Values**

    [funcย object(forKey: String) -> Any?](https://developer.apple.com/documentation/foundation/userdefaults/1410095-object)

    Returns the object associated with the specified key.

    [funcย url(forKey: String) -> URL?](https://developer.apple.com/documentation/foundation/userdefaults/1408648-url)

    Returns the URL associated with the specified key.

    [funcย array(forKey: String) -> [Any]?](https://developer.apple.com/documentation/foundation/userdefaults/1414792-array)

    Returns the array associated with the specified key.

    [funcย dictionary(forKey: String) -> [String : Any]?](https://developer.apple.com/documentation/foundation/userdefaults/1408563-dictionary)

    Returns the dictionary object associated with the specified key.

    [funcย string(forKey: String) -> String?](https://developer.apple.com/documentation/foundation/userdefaults/1416700-string)

    Returns the string associated with the specified key.

    [funcย stringArray(forKey: String) -> [String]?](https://developer.apple.com/documentation/foundation/userdefaults/1416414-stringarray)

    Returns the array of strings associated with the specified key.

    [funcย data(forKey: String) -> Data?](https://developer.apple.com/documentation/foundation/userdefaults/1409590-data)

    Returns the data object associated with the specified key.

    [funcย bool(forKey: String) -> Bool](https://developer.apple.com/documentation/foundation/userdefaults/1416388-bool)

    Returns the Boolean value associated with the specified key.

    [funcย integer(forKey: String) -> Int](https://developer.apple.com/documentation/foundation/userdefaults/1407405-integer)

    Returns the integer value associated with the specified key.

    [funcย float(forKey: String) -> Float](https://developer.apple.com/documentation/foundation/userdefaults/1414027-float)

    Returns the float value associated with the specified key.

    [funcย double(forKey: String) -> Double](https://developer.apple.com/documentation/foundation/userdefaults/1416581-double)

    Returns the double value associated with the specified key.

    [funcย dictionaryRepresentation() -> [String : Any]](https://developer.apple.com/documentation/foundation/userdefaults/1415919-dictionaryrepresentation)

    Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.

    **Setting Default Values**

    [funcย set(Any?,ย forKey: String)](https://developer.apple.com/documentation/foundation/userdefaults/1414067-set)

    Sets the value of the specified default key.

    [funcย set(Float,ย forKey: String)](https://developer.apple.com/documentation/foundation/userdefaults/1413320-set)

    Sets the value of the specified default key to the specified float value.

    [funcย set(Double,ย forKey: String)](https://developer.apple.com/documentation/foundation/userdefaults/1408646-set)

    Sets the value of the specified default key to the double value.

    [funcย set(Int,ย forKey: String)](https://developer.apple.com/documentation/foundation/userdefaults/1413614-set)

    Sets the value of the specified default key to the specified integer value.

    [funcย set(Bool,ย forKey: String)](https://developer.apple.com/documentation/foundation/userdefaults/1408905-set)

    Sets the value of the specified default key to the specified Boolean value.

    [funcย set(URL?,ย forKey: String)](https://developer.apple.com/documentation/foundation/userdefaults/1414194-set)

    Sets the value of the specified default key to the specified URL.

    **Removing Defaults**

    [funcย removeObject(forKey: String)](https://developer.apple.com/documentation/foundation/userdefaults/1411182-removeobject)

    Removes the value of the specified default key.

    **Maintaining Suites**

    [funcย addSuite(named: String)](https://developer.apple.com/documentation/foundation/userdefaults/1410294-addsuite)

    Inserts the specified domain name into the receiverโ€™s search list.

    [funcย removeSuite(named: String)](https://developer.apple.com/documentation/foundation/userdefaults/1408047-removesuite)

    Removes the specified domain name from the receiverโ€™s search list.

    **Registering Defaults**

    [funcย register(defaults: [String : Any])](https://developer.apple.com/documentation/foundation/userdefaults/1417065-register)

    Adds the contents of the specified dictionary to the registration domain.

    **Maintaining Persistent Domains**

    [funcย persistentDomain(forName: String) -> [String : Any]?](https://developer.apple.com/documentation/foundation/userdefaults/1412197-persistentdomain)

    Returns a dictionary representation of the defaults for the specified domain.

    [funcย setPersistentDomain([String : Any],ย forName: String)](https://developer.apple.com/documentation/foundation/userdefaults/1408187-setpersistentdomain)

    Sets a dictionary for the specified persistent domain.

    [funcย removePersistentDomain(forName: String)](https://developer.apple.com/documentation/foundation/userdefaults/1417339-removepersistentdomain)

    Removes the contents of the specified persistent domain from the userโ€™s defaults.

    ~~[funcย persistentDomainNames() -> [Any]](https://developer.apple.com/documentation/foundation/userdefaults/1589081-persistentdomainnames)~~

    Returns an array of the current persistent domain names.

    Deprecated

    **Maintaining Volatile Domains**

    [varย volatileDomainNames: [String]](https://developer.apple.com/documentation/foundation/userdefaults/1414231-volatiledomainnames)

    The current volatile domain names.

    [funcย volatileDomain(forName: String) -> [String : Any]](https://developer.apple.com/documentation/foundation/userdefaults/1409592-volatiledomain)

    Returns the dictionary for the specified volatile domain.

    [funcย setVolatileDomain([String : Any],ย forName: String)](https://developer.apple.com/documentation/foundation/userdefaults/1413720-setvolatiledomain)

    Sets the dictionary for the specified volatile domain.

    [funcย removeVolatileDomain(forName: String)](https://developer.apple.com/documentation/foundation/userdefaults/1415955-removevolatiledomain)

    Removes the specified volatile domain from the userโ€™s defaults.

    **Accessing Managed Environment Keys**

    [funcย objectIsForced(forKey: String) -> Bool](https://developer.apple.com/documentation/foundation/userdefaults/1408635-objectisforced)

    Returns a Boolean value indicating whether the specified key is managed by an administrator.

    [funcย objectIsForced(forKey: String,ย inDomain: String) -> Bool](https://developer.apple.com/documentation/foundation/userdefaults/1416306-objectisforced)

    Returns a Boolean value indicating whether the key in the specified domain is managed by an administrator.

    **Domains**

    [class letย argumentDomain: String](https://developer.apple.com/documentation/foundation/userdefaults/1410665-argumentdomain)

    The domain consisting of defaults parsed from the applicationโ€™s arguments. These are one or more pairs of the formย -default valueย included in the command-line invocation of the application.

    [class letย globalDomain: String](https://developer.apple.com/documentation/foundation/userdefaults/1407355-globaldomain)

    The domain consisting of defaults meant to be seen by all applications.

    [class letย registrationDomain: String](https://developer.apple.com/documentation/foundation/userdefaults/1415953-registrationdomain)

    The domain consisting of a set of temporary defaults whose values can be set by the application to ensure that searches will always be successful.

    **Notifications**

    [class letย didChangeNotification: NSNotification.Name](https://developer.apple.com/documentation/foundation/userdefaults/1408206-didchangenotification)

    Posted when user defaults are changed within the current process.

    [class letย sizeLimitExceededNotification: NSNotification.Name](https://developer.apple.com/documentation/foundation/userdefaults/1617187-sizelimitexceedednotification)

    Posted when more data is stored in user defaults than is allowed.

    [class letย completedInitialCloudSyncNotification: NSNotification.Name](https://developer.apple.com/documentation/foundation/userdefaults/1617169-completedinitialcloudsyncnotific)

    Posted when ubiquitous defaults finish downloading data, either the first time a device is connected to an iCloud account or when a user switches their primary iCloud account.

    [class letย didChangeCloudAccountsNotification: NSNotification.Name](https://developer.apple.com/documentation/foundation/userdefaults/1617438-didchangecloudaccountsnotificati)

    Posted when the user changes the primary iCloud account.

    [class letย noCloudAccountNotification: NSNotification.Name](https://developer.apple.com/documentation/foundation/userdefaults/1648504-nocloudaccountnotification)

    Posted when a cloud default is set, but no iCloud user is logged in.

    • dictionary

      tructure Dictionary

      A collection whose elements are key-value pairs.

      iOS 8.0+iPadOS 8.0+macOS 10.10+Mac Catalyst 13.0+tvOS 9.0+watchOS 2.0+

      ## Declaration

      @frozen struct Dictionary<Key, Value> where Key : [Hashable](https://developer.apple.com/documentation/swift/hashable)

      ## Overview

      A dictionary is a type of hash table, providing fast access to the entries it contains. Each entry in the table is identified using its key, which is a hashable type such as a string or number. You use that key to retrieve the corresponding value, which can be any object. In other languages, similar data types are known as hashes or associated arrays.

      Create a new dictionary by using a dictionary literal. A dictionary literal is a comma-separated list of key-value pairs, in which a colon separates each key from its associated value, surrounded by square brackets. You can assign a dictionary literal to a variable or constant or pass it to a function that expects a dictionary.

      Hereโ€™s how you would create a dictionary of HTTP response codes and their related messages:

      var responseMessages = [200: "OK", 403: "Access forbidden", 404: "File not found", 500: "Internal server error"]

      Theย responseMessagesย variable is inferred to have typeย [Int: String]. Theย Keyย type of the dictionary isย Int, and theย Valueย type of the dictionary isย String.

      To create a dictionary with no key-value pairs, use an empty dictionary literal ([:]).

      var emptyDict: [String: String] = [:]

      Any type that conforms to theย Hashableย protocol can be used as a dictionaryโ€™sย Keyย type, including all of Swiftโ€™s basic types. You can use your own custom types as dictionary keys by making them conform to theย Hashableย protocol.

      # Getting and Setting Dictionary Values

      The most common way to access values in a dictionary is to use a key as a subscript. Subscripting with a key takes the following form:

      print(responseMessages[200])// Prints "Optional("OK")"

      Subscripting a dictionary with a key returns an optional value, because a dictionary might not hold a value for the key that you use in the subscript.

      The next example uses key-based subscripting of theย responseMessagesย dictionary with two keys that exist in the dictionary and one that does not.

      let httpResponseCodes = [200, 403, 301]for code in httpResponseCodes { if let message = responseMessages[code] { print("Response \(code): \(message)") } else { print("Unknown response \(code)") }}// Prints "Response 200: OK"// Prints "Response 403: Access forbidden"// Prints "Unknown response 301"

      You can also update, modify, or remove keys and values from a dictionary using the key-based subscript. To add a new key-value pair, assign a value to a key that isnโ€™t yet a part of the dictionary.

      responseMessages[301] = "Moved permanently"print(responseMessages[301])// Prints "Optional("Moved permanently")"

      Update an existing value by assigning a new value to a key that already exists in the dictionary. If you assignย nilย to an existing key, the key and its associated value are removed. The following example updates the value for theย 404ย code to be simply โ€œNot foundโ€ and removes the key-value pair for theย 500ย code entirely.

      responseMessages[404] = "Not found"responseMessages[500] = nilprint(responseMessages)// Prints "[301: "Moved permanently", 200: "OK", 403: "Access forbidden", 404: "Not found"]"

      In a mutableย Dictionaryย instance, you can modify in place a value that youโ€™ve accessed through a keyed subscript. The code sample below declares a dictionary calledย interestingNumbersย with string keys and values that are integer arrays, then sorts each array in-place in descending order.

      var interestingNumbers = ["primes": [2, 3, 5, 7, 11, 13, 17], "triangular": [1, 3, 6, 10, 15, 21, 28], "hexagonal": [1, 6, 15, 28, 45, 66, 91]]for key in interestingNumbers.keys { interestingNumbers[key]?.sort(by: >)} print(interestingNumbers["primes"]!)// Prints "[17, 13, 11, 7, 5, 3, 2]"

      # Iterating Over the Contents of a Dictionary

      Every dictionary is an unordered collection of key-value pairs. You can iterate over a dictionary using aย for-inย loop, decomposing each key-value pair into the elements of a tuple.

      let imagePaths = ["star": "/glyphs/star.png", "portrait": "/images/content/portrait.jpg", "spacer": "/images/shared/spacer.gif"] for (name, path) in imagePaths { print("The path to '\(name)' is '\(path)'.")}// Prints "The path to 'star' is '/glyphs/star.png'."// Prints "The path to 'portrait' is '/images/content/portrait.jpg'."// Prints "The path to 'spacer' is '/images/shared/spacer.gif'."

      The order of key-value pairs in a dictionary is stable between mutations but is otherwise unpredictable. If you need an ordered collection of key-value pairs and donโ€™t need the fast key lookup thatย Dictionaryย provides, see theย KeyValuePairsย type for an alternative.

      You can search a dictionaryโ€™s contents for a particular value using theย contains(where:)ย orย firstIndex(where:)ย methods supplied by default implementation. The following example checks to see ifย imagePathsย contains any paths in theย "/glyphs"ย directory:

      let glyphIndex = imagePaths.firstIndex(where: { $0.value.hasPrefix("/glyphs") })if let index = glyphIndex { print("The '\(imagePaths[index].key)' image is a glyph.")} else { print("No glyphs found!")}// Prints "The 'star' image is a glyph.")

      Note that in this example,ย imagePathsย is subscripted using a dictionary index. Unlike the key-based subscript, the index-based subscript returns the corresponding key-value pair as a non-optional tuple.

      print(imagePaths[glyphIndex!])// Prints "(key: "star", value: "/glyphs/star.png")"

      A dictionaryโ€™s indices stay valid across additions to the dictionary as long as the dictionary has enough capacity to store the added values without allocating more buffer. When a dictionary outgrows its buffer, existing indices may be invalidated without any notification.

      When you know how many new values youโ€™re adding to a dictionary, use theย init(minimumCapacity:)ย initializer to allocate the correct amount of buffer.

๐Ÿ“ขย 7์ฃผ์ฐจ ์ˆ˜์—… ํ›„๊ธฐ


  • 7์ฃผ์ฐจ ์ˆ˜์—…์„ ๋“ฃ๊ณ  ์„œ๋กœ ๋Š๋‚€ ์ ์„ ์ด์•ผ๊ธฐํ•ด์ฃผ์„ธ์š”!
  • ํ•ต์‹ฌ ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด ์™„๋ฒฝํ•˜๊ฒŒ ์ดํ•ดํ–ˆ๋Š”์ง€? ํ˜น์‹œ ์ดํ•ด๊ฐ€ ์•ˆ ๋˜๋Š” ๋ถ€๋ถ„์€ ๋ญ์˜€๋Š”์ง€? ์„œ๋กœ ์ด์•ผ๊ธฐํ•ด์ฃผ์„ธ์š”!

UserDefaults๋Š” ์ด์ „ ๋ฏธ์…˜์—์„œ๋„ ๋ช‡ ๋ฒˆ ์‚ฌ์šฉํ•œ ์ ์ด ์žˆ์–ด ์‰ฝ๊ฒŒ ์ดํ•ดํ–ˆ๋‹ค.

ํŠœํ”Œ๊ณผ ๋”•์…”๋„ˆ๋ฆฌ ํ™œ์šฉ ๋ฐฉ๋ฒ•์ด ์ˆ˜์—†์ด ๋งŽ์•„์„œ ๊ด€๋ จ ๊ฒฝํ—˜์ด ๋งŽ์„ ์ˆ˜๋ก ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.

โš ๏ธย ์Šคํ„ฐ๋””๊ฐ„ ์ฃผ์˜์‚ฌํ•ญ


  1. ๊ณผ์ œ ํ”ผ๋“œ๋ฐฑ ๊ธฐ๋ฐ˜ ์ง„ํ–‰์ž…๋‹ˆ๋‹ค - ํ•œ๋ช…์”ฉ ๋ณธ์ธ์˜ ๊ณผ์ œ๋ฅผ ๋ฐœํ‘œํ•˜๋Š” ์‹œ๊ฐ„ ๊ทธ๋ฆฌ๊ณ  ํ•ด์˜จ ๊ณผ์ œ์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ํ•˜๋Š” ์‹œ๊ฐ„ (ex:์ „ ์ด๋ ‡๊ฒŒ ์ƒ๊ฐํ•ด์„œ ์ด๋Ÿฐ ๋ถ€๋ถ„ ๋‹ค๋ฅด๊ฒŒ ํ•ด์™”๋Š”๋ฐ ์ €๊ฒƒ๋„ ๊ดœ์ฐฎ์€ ๊ฒƒ ๊ฐ™์•„์š”!)์ด ๋ฌด์กฐ๊ฑด ๊ธฐ๋ฐ˜์ด ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค!
  2. ๋ถ€๊ฐ€์ ์œผ๋กœ ์›Œํฌ๋ถ์—์„œ ์ œ๊ณต๋˜๋Š” ํ‚ค์›Œ๋“œ ํ˜น์€ ๊ฐ•์˜์—์„œ ๋“ค์€ ๋””ํ…Œ์ผ์ ์ธ ๋ถ€๋ถ„์—์„œ ๋” ํ† ์˜ํ•ด๋ด๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

โœ…ย ์‹ค์Šต ์ฒดํฌ๋ฆฌ์ŠคํŠธ


  • dictionary์˜ ์ •์˜์™€ ์‹คํ–‰ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ–ˆ๋‚˜์š”?

  • UserDefaults๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํšŒ์›๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ ๋กœ์ง์„ ๊ตฌํ˜„ํ–ˆ๋‚˜์š”?

  • ํšŒ์›๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ์ด ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ๋‚˜์š”?

  • ํšŒ์›๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ์— ๋Œ€ํ•œ ์˜ˆ์™ธ์ฒ˜๋ฆฌ ์ฝ”๋“œ ๋ฐ ๋กœ์ง์„ ์ดํ•ดํ–ˆ๋‚˜์š”?

  • ๋ฏธ์…˜ ์ฐธ๊ณ  ์˜์ƒ

    [iOS] #7. DB - Practice

โšก ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ…


  • โšก์ด์Šˆ No.1 (์˜ˆ์‹œ, ์„œ์‹๋งŒ ๋ณต์‚ฌํ•˜์‹œ๊ณ  ์ง€์›Œ์ฃผ์„ธ์š”.)

    ์ด์Šˆ

    ๐Ÿ‘‰ ์•ฑ ์‹คํ–‰ ์ค‘์— ๋…ธ๋ž˜ ๋‹ค์Œ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋‹ˆ๊นŒ ์•ฑ์ด ์ข…๋ฃŒ๋˜์—ˆ๋‹ค.

    ๋ฌธ์ œ

    ๐Ÿ‘‰ ๋…ธ๋ž˜ํด๋ž˜์Šค์˜ ๋ฐ์ดํ„ฐ๋ฆฌ์ŠคํŠธ์˜ Size๋ฅผ ๋„˜์–ด์„œ NullPointException์ด ๋ฐœ์ƒํ•˜์—ฌ ์•ฑ์ด ์ข…๋ฃŒ๋œ ๊ฒƒ์ด์—ˆ๋‹ค.

    ํ•ด๊ฒฐ

    ๐Ÿ‘‰ ๋…ธ๋ž˜ ๋‹ค์Œ ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ ๋ฐ์ดํ„ฐ๋ฆฌ์ŠคํŠธ์˜ Size๋ฅผ ๊ฒ€์‚ฌํ•ด Size๋ณด๋‹ค ๋„˜์–ด๊ฐ€๋ ค๊ณ  ํ•˜๋ฉด ๋‹ค์Œ์œผ๋กœ ๋„˜์–ด๊ฐ€๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค์ง€ ์•Š๊ณ , ์ฒซ ๋…ธ๋ž˜๋กœ ๋Œ์•„๊ฐ€๊ฒŒ๋” ํ•ด๊ฒฐ

    ์ฐธ๊ณ  ๋ ˆํผ๋Ÿฐ์Šค

    • ๋งํฌ

๐Ÿค”ย ์ด๊ฒƒ๋„ ํ•œ ๋ฒˆ ์ƒ๊ฐํ•ด๋ด์š”!


  • DB ํŠน์„ฑ์— ๋Œ€ํ•ด ์ƒ๊ฐํ•ด๋ณด์„ธ์š”! (ex ์˜์†์„ฑ)

  • dictionary์˜ ๋ฌธ๋ฒ•๊ณผ ์ž๋ฃŒ๊ตฌ์กฐ์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด๋ณด์„ธ์š”!

  • UserDefaults์˜ ๋‹ค๋ฅธ ์˜ต์…˜๋„ ๊ณต๋ถ€ํ•ด๋ณด์„ธ์š”!

  • JSON์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด๋ณด์„ธ์š”!

  • ์„œ๋ฒ„์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ios๋Š” ์–ด๋–ป๊ฒŒ ์†Œํ†ตํ• ์ง€ ์ƒ๊ฐํ•ด๋ณด์„ธ์š”!

  • UserDefaults ๋ณด๋‹ค ๋” ์œ ์šฉํ•œ ์ž์ฒด DB๋Š” ์—†์„์ง€ ์กฐ์‚ฌํ•ด๋ณด์„ธ์š”! (ex. CoreData, Realm, FireBase)7wnck

์Šคํƒ ๋‹ค๋“œ ๋ฏธ์…˜ ๐Ÿ˜Ž

์›๋ž˜๋Š” 6์ฃผ์ฐจ ์•ฑ์œผ๋กœ ์ ์šฉํ•ด๋ณด๋ ค๊ณ  ํ–ˆ์ง€๋งŒ

unable to open dependencies file ์ด๋ผ๋Š” ์ •์ฒด๋ชจ๋ฅผ ์—๋Ÿฌ๊ฐ€ 7๊ฐœ๋‚˜ ๋œฌ ๊ด€๊ณ„๋กœ

(์–ด๋–ป๊ฒŒ๋“  ๊ณ ์ณ๋ณด๋ ค๊ณ  pod ๋„ ์—…๋ฐ์ดํŠธ ํ•ด๋ณด๊ณ , ๊ตฌ๊ธ€๋งํ•œ target ์„ค์ •๋„ ๋ฐ”๊ฟ”๋ณด์•˜๋Š”๋ฐ๋„ ํ•ด๊ฒฐ ๋ชป ํ•จ. ๊ฒฐ๊ตญ xcode๋ฅผ ๋‹ค์‹œ ์ง€์› ๋‹ค๊ฐ€ ๊น”์•„๋ณด๋‹ˆ ์ •์ƒ ์ž‘๋™, ์•„๋งˆ xcode ์—…๋ฐ์ดํŠธ ์ƒ์—์„œ ๋ญ”๊ฐ€ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ ๋“ฏ ํ•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฌ์ „ํžˆ 6์ฃผ์ฐจ ํŒŒ์ผ์ด ์ž‘๋™์„ ์•ˆํ•œ๋‹ค)

์˜ˆ์ „์— ํ•œ ๋ฒˆ ๋งŒ๋“ค์–ด ๋†“์€ ๋ฝ€๋ชจ๋„๋กœ ์•ฑ์— userDefaults๋ฅผ ์ ์šฉํ•ด ๋ณด์•˜๋‹ค.

 import UIKit
import AudioToolbox

enum TimerStatus {
    case start
    case pause
    case end
}

class ViewController: UIViewController {

    
    @IBOutlet weak var timerLabel: UILabel!
    @IBOutlet weak var progessView: UIProgressView!
    @IBOutlet weak var datePicker: UIDatePicker!
    
    @IBOutlet weak var cancelButton: UIButton!
    @IBOutlet weak var toggleButton: UIButton!
    
    @IBOutlet weak var imageView: UIImageView!
    var duration = 60
    var timerStatus: TimerStatus = .end
    var timer: DispatchSourceTimer?
    var currentSeconds = 0
    
    
    var clockRecord: [String] = []
    
    override func viewDidLoad() {
        
        super.viewDidLoad()
        self.configureToggleButton()

  
    }
    

    func setTimerInfoViewVisible(isHidden: Bool){
        self.timerLabel.isHidden = isHidden
        self.progessView.isHidden = isHidden
        
    }
    
    func configureToggleButton(){
        self.toggleButton.setTitle("์‹œ์ž‘", for: .normal)
        self.toggleButton.setTitle("์ผ์‹œ์ •์ง€", for: .selected)
    }
    
    func startTimer() {
        if self.timer == nil {
            self.timer = DispatchSource.makeTimerSource(flags: [], queue: .main)
            self.timer?.schedule(deadline: .now(), repeating: 1)
            self.timer?.setEventHandler(handler: { [weak self] in
                guard let self = self else { return }
                self.currentSeconds -= 1
                let hour = self.currentSeconds / 3600
                let minute = (self.currentSeconds % 3600) / 60
                let seconds = (self.currentSeconds % 3600) % 60
                self.timerLabel.text = String(format: "%02d:%02d:%02d", hour, minute, seconds)
                self.progessView.progress = Float(self.currentSeconds) / Float(self.duration)
                UIView.animate(withDuration: 0.5, delay: 0, animations: {
                    self.imageView.transform = CGAffineTransform(rotationAngle: .pi)
                    
                })
                UIView.animate(withDuration: 0.5, delay: 0.5, animations: {
                    self.imageView.transform = CGAffineTransform(rotationAngle: .pi * 2)
                    
                })
                if self.currentSeconds <= 0 {
                    
                    self.stopTimer()
                    AudioServicesPlaySystemSound(1005) 
                }
                
            })
            self.timer?.resume()
        }
        
        
    }
    
    func stopTimer(){
        if self.timerStatus == .pause {
            self.timer?.resume()
        }
        self.timerStatus = .end
        self.cancelButton.isEnabled = false
        UIView.animate(withDuration: 0.5, animations: {
            self.timerLabel.alpha = 0
            self.progessView.alpha = 0
            self.datePicker.alpha = 1
            self.imageView.transform = .identity
        })
        self.toggleButton.isSelected = false
        self.timer?.cancel()
        self.timer = nil
        
        
    }
    
    @IBAction func tapCancelButton(_ sender: UIButton) {
        switch self.timerStatus {
        case .start, .pause:
            self.stopTimer()
        default:
            break
            
        }
    }
    
    @IBAction func tapToggleButton(_ sender: UIButton) {
        self.duration = Int(self.datePicker.countDownDuration)
        self.clockRecord.append(String(self.duration))
        UserDefaults.standard.set(self.clockRecord, forKey: "clockRecord")
        switch self.timerStatus {
        case .end:
            self.currentSeconds = self.duration
            self.timerStatus = .start
            UIView.animate(withDuration: 0.5, animations: {
                self.timerLabel.alpha = 1
                self.progessView.alpha = 1
                self.datePicker.alpha = 0
                
            })
            self.toggleButton.isSelected = true
            self.cancelButton.isEnabled = true
            self.startTimer()
            
        case .start:
            self.timerStatus = .pause
            self.toggleButton.isSelected = false
            self.timer?.suspend()
            
        case .pause:
            self.timerStatus = .start
            self.toggleButton.isSelected =  true
            self.timer?.resume()
    
            
            
        }
    }
    
    
}
import UIKit

class recordViewController: UIViewController {
    
    @IBOutlet weak var tableView: UITableView!
    
    var timeRecord: [String] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let clockRecord: [String] = UserDefaults.standard.stringArray(forKey: "clockRecord") else {return}
        timeRecord = clockRecord
        tableView.dataSource = self
    }
    
    
    
}

extension recordViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection: Int) -> Int {
        return timeRecord.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = timeRecord[indexPath.row]
        return cell
    }
}

ํ† ๊ธ€๋ฒ„ํŠผ์„ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค userDefaults์— ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์„œ, ๊ทธ๋™์•ˆ ์„ค์ •ํ•œ ํƒ€์ž„ duration์„ ๋ณผ ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค.

01

์‹ค์ œ๋กœ 1๋ถ„์„ ์ ์šฉํ•˜๋ฉด ํ…Œ์ด๋ธ” ๋ทฐ์— ์ด๋ ‡๊ฒŒ ๊ธฐ๋ก๋œ๋‹ค. 02

3๋ถ„์„ ์ ์šฉํ•˜๋ฉด 03

์ด๋ ‡๊ฒŒ ๋ฐ”๋€Œ๊ณ 

04

์•ฑ์„ ๊ป๋‹ค๊ฐ€ ์ผœ๋„ 05

์™„๋ฒฝํ•˜๊ฒŒ ์œ ์ง€!

ํƒœ๊ทธ: ,

์นดํ…Œ๊ณ ๋ฆฌ:

์—…๋ฐ์ดํŠธ:

๋Œ“๊ธ€๋‚จ๊ธฐ๊ธฐ