PostgreSQL์์ ๋ฐ๋ณต ์ผ์ ๊ณผ ์๊ฐ๋: ํจํด
PostgreSQL์์ ๋ฐ๋ณต ์ผ์ ๊ณผ ์๊ฐ๋๋ฅผ ๋ค๋ฃจ๋ ์ค์ฉ์ ์ ์ฅ ํ์, ๋ฐ๋ณต ๊ท์น, ์์ธ ์ฒ๋ฆฌ, ์ฟผ๋ฆฌ ํจํด์ ๋ฐฐ์ฐ๊ณ ์บ๋ฆฐ๋๋ฅผ ์ ํํ๊ฒ ์ ์งํ๋ ๋ฒ์ ์์๋ณด์ธ์.

์๊ฐ๋์ ๋ฐ๋ณต ์ด๋ฒคํธ๊ฐ ์๋ชป๋๋ ์ด์
๋๋ถ๋ถ์ ์บ๋ฆฐ๋ ๋ฒ๊ทธ๋ ์ํ์ ์ค๋ฅ๊ฐ ์๋๋๋ค. ์๋ฏธ์์ ์ค๋ฅ์ ๋๋ค. ํ ๊ฐ์ง(ํน์ ์์ )๋ฅผ ์ ์ฅํ๋๋ฐ, ์ฌ์ฉ์๋ ๋ค๋ฅธ ๊ฒ(ํน์ ์ฅ์์ ๋ก์ปฌ ์๊ฐ)์ ๊ธฐ๋ํฉ๋๋ค. ์ด ์ฐจ์ด๊ฐ ๋ฐ๋ณต ์ผ์ ๊ณผ ์๊ฐ๋๋ฅผ ํ ์คํธ์์๋ ๊ด์ฐฎ์ ๋ณด์ด๊ฒ ํ๋ค๊ฐ ์ค์ ์ฌ์ฉ์๊ฐ ๋ํ๋๋ฉด ๊นจ์ง๋ ์ด์ ์ ๋๋ค.
์ผ๊ด์ ์ฝ์๊ฐ(DST)์ ์ ํ์ ์ธ ํธ๋ฆฌ๊ฑฐ์ ๋๋ค. โ๋งค์ฃผ ์ผ์์ผ 09:00โ์ด๋ผ๋ ํํ์ โ์์ ํ์์คํฌํ์์ 7์ผ๋ง๋คโ์ ๊ฐ์ง ์์ต๋๋ค. ์คํ์ ์ด ๋ฐ๋๋ฉด ๋ ๊ฐ๋ ์ ํ ์๊ฐ์ฉ ์ด๊ธ๋๊ณ ์บ๋ฆฐ๋๋ ์กฐ์ฉํ ํ์ด์ง๋๋ค.
์ฌํ๊ณผ ํผํฉ๋ ์๊ฐ๋๋ ๋ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ๋ํฉ๋๋ค. ์์ฝ์ ๋ฌผ๋ฆฌ์ ์ฅ์(์: ์์นด๊ณ ์ ๋ฏธ์ฉ์ค ์ข์)์ ๋ฌถ์ฌ ์๋๋ฐ, ์ด๋ฅผ ๋ณด๋ ์ฌ๋์ ๋ฐ๋์ ์์ ์ ์์ต๋๋ค. ์ฅ์ ๊ธฐ๋ฐ ์ค์ผ์ค์ ์ฌ๋ ๊ธฐ๋ฐ์ผ๋ก ์ฒ๋ฆฌํ๋ฉด ์ ์ด๋ ํ์ชฝ์๋ ์๋ชป๋ ๋ก์ปฌ ์๊ฐ์ด ๋ณด์ฌ์ง๋๋ค.
์ผ๋ฐ์ ์ธ ์คํจ ๋ชจ๋:
- ์ ์ฅ๋ ํ์์คํฌํ์ ๊ฐ๊ฒฉ์ ๋ํด ๋ฐ์์ ์์ฑํ๋๋ฐ DST๊ฐ ๋ฐ๋๋๋ค.
- ์๊ฐ๋ ๊ท์น ์์ด "๋ก์ปฌ ์๊ฐ"๋ง ์ ์ฅํด ๋์ค์ ์๋ํ ์์ ์ ์ฌ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
- DST ๊ฒฝ๊ณ๋ฅผ ๋์ง ์๋ ๋ ์ง๋ง ํ ์คํธํฉ๋๋ค.
- ํ๋์ ์ฟผ๋ฆฌ์์ โ์ด๋ฒคํธ ์๊ฐ๋โ, โ์ฌ์ฉ์ ์๊ฐ๋โ, โ์๋ฒ ์๊ฐ๋โ๋ฅผ ์์ด ์ฌ์ฉํฉ๋๋ค.
์คํค๋ง๋ฅผ ์ ํํ๊ธฐ ์ ์, ์ ํ์์ โ์ ํํจโ์ด ๋ฌด์์ ์๋ฏธํ๋์ง ๊ฒฐ์ ํ์ธ์.
์์ฝ์ ๊ฒฝ์ฐ โ์ ํํจโ์ ๋ณดํต: ์ฝ์์ด ์ฅ์์ ์๊ฐ๋์์ ์๋๋ ๋ฒฝ์๊ณ ์๊ฐ์ ๋ฐ์ํ๊ณ , ์ด๋ฅผ ๋ณด๋ ๋ชจ๋ ์ฌ๋์๊ฒ ์ฌ๋ฐ๋ฅด๊ฒ ๋ณํ๋์ด ๋ณด์ด๋ ๊ฒ์ ๋๋ค.
๊ต๋ ๊ทผ๋ฌด์ ๊ฒฝ์ฐ โ์ ํํจโ์ ์ข ์ข : ์ง์์ด ์ฌํ ์ค์ด๋๋ผ๋ ๊ทผ๋ฌด๋ ๋งค์ฅ ๊ณ ์ ์ ๋ก์ปฌ ์๊ฐ์ ์์๋๋ ๊ฒ์ ๋๋ค.
์ฅ์์ ๋ฌถ์์ง ์ฌ๋์ ๋ฌถ์์ง ํ๋ ๊ทธ ํ ๊ฐ์ง ๊ฒฐ์ ์ด ๋๋จธ์ง๋ฅผ ๋ชจ๋ ์ข์ฐํฉ๋๋ค: ๋ฌด์์ ์ ์ฅํ ์ง, ์ด๋ป๊ฒ ๋ฐ๋ณต์ ์์ฑํ ์ง, ๊ทธ๋ฆฌ๊ณ ํ ์๊ฐ ์ฐจ์ด์ ๋๋ผ์ ์์ด ์บ๋ฆฐ๋ ๋ทฐ๋ฅผ ์ด๋ป๊ฒ ์กฐํํ ์ง.
์ฌ๋ฐ๋ฅธ ์ฌ๊ณ ๋ชจ๋ธ ์ ํ: ์ธ์คํดํธ vs ๋ก์ปฌ ์๊ฐ
๋ง์ ๋ฒ๊ทธ๋ ๋ ๊ฐ์ง ์๊ฐ ๊ฐ๋ ์ ์์ด์ ๋ฐ์ํฉ๋๋ค:
- ์ธ์คํดํธ: ์ ๋์ ์ธ ํ ์๊ฐ. ํ ๋ฒ ๋ฐ์ํฉ๋๋ค.
- ๋ก์ปฌ ์๊ฐ ๊ท์น: โํ๋ฆฌ์์ ๋งค์ฃผ ์์์ผ ์ค์ 9์โ ๊ฐ์ ๋ฒฝ์๊ณ ์๊ฐ.
์ธ์คํดํธ๋ ์ด๋์๋ ๋์ผํฉ๋๋ค. โ2026-03-10 14:00 UTCโ๋ ์ธ์คํดํธ์ ๋๋ค. ํ์ ํตํ, ํญ๊ณตํธ ์ถ๋ฐ, โ์ ํํ ์ด ์๊ฐ์ ์๋ฆผ์ ๋ณด๋ธ๋คโ๋ ๋ณดํต ์ธ์คํดํธ์ ๋๋ค.
๋ก์ปฌ ์๊ฐ์ ํน์ ์ฅ์์ ์๊ณ์์ ์ฝํ๋ ์๊ฐ์ ๋๋ค. โEurope/Paris์์ ํ์ผ๋ง๋ค ์ค์ 9์โ๋ ๋ก์ปฌ ์๊ฐ์ ๋๋ค. ์์ ์๊ฐ, ๋ฐ๋ณต ์์ , ์ง์ ๊ต๋๋ ๋ณดํต ์ฅ์์ ์๊ฐ๋์ ๊ณ ์ ๋ฉ๋๋ค. ์๊ฐ๋๋ ๋จ์ํ ํ์ ์ ํธ๊ฐ ์๋๋ผ ์๋ฏธ์ ์ผ๋ถ์ ๋๋ค.
๊ฐ๋จํ ๊ฒฝํ ๋ฒ์น:
- ์ด๋ฒคํธ๊ฐ ์ ์ธ๊ณ์์ ํ๋์ ์ค์ ์๊ฐ์ ์ผ์ด๋์ผ ํ๋ฉด ์์/์ข
๋ฃ๋ฅผ ์ธ์คํดํธ๋ก(
timestamptz) ์ ์ฅํ์ธ์. - ์ด๋ฒคํธ๊ฐ ํ ์ฅ์์ ์๊ณ์ ๋ฐ๋ผ์ผ ํ๋ฉด ๋ก์ปฌ ๋ ์ง์ ๋ก์ปฌ ์๊ฐ์ ์๊ฐ๋ ID๋ฅผ ํจ๊ป ์ ์ฅํ์ธ์. ๋ฐ์์ ์์ฑํ ๋๋ง ์ด๋ฅผ ์ค์ ์ธ์คํดํธ๋ก ๋ณํํ์ธ์.
- ์ฌ์ฉ์๊ฐ ์ด๋ ์ค์ด๋ฉด ๋ทฐ์ด์ ์๊ฐ๋๋ก ํ์ํ๋, ์ค์ผ์ค์ ๊ทธ ์ฅ์์ ๊ณ ์ ํ์ธ์.
+02:00๊ฐ์ ์คํ์ ์ผ๋ก ์๊ฐ๋๋ฅผ ์ถ์ ํ์ง ๋ง์ธ์. ์คํ์ ์ DST ๊ท์น์ ํฌํจํ์ง ์์ต๋๋ค.
์: ๋ณ์ ๊ต๋๋ โMon-Fri 09:00-17:00 America/New_Yorkโ์ ๋๋ค. DST๊ฐ ๋ฐ๋๋ ์ฃผ์๋ ๊ต๋๋ ํ์ง ๊ธฐ์ค์ผ๋ก ์ฌ์ ํ 9์๋ถํฐ 5์์ ๋๋ค. ๋ค๋ง UTC ์ธ์คํดํธ๋ ํ ์๊ฐ์ฉ ์ด๋ํฉ๋๋ค.
PostgreSQL์์ ์ค์ํ ํ์ (๊ทธ๋ฆฌ๊ณ ํผํ ๊ฒ)
๋๋ถ๋ถ์ ์บ๋ฆฐ๋ ๋ฒ๊ทธ๋ ์๋ชป๋ ์ปฌ๋ผ ํ์ ์์ ์์ํฉ๋๋ค. ํต์ฌ์ ์ค์ ์๊ฐ๊ณผ ๋ฒฝ์๊ณ ๊ธฐ๋๋ฅผ ๋ถ๋ฆฌํ๋ ๊ฒ์ ๋๋ค.
์ค์ ์ธ์คํดํธ์๋ timestamptz๋ฅผ ์ฌ์ฉํ์ธ์: ์์ฝ, ์ถํด๊ทผ ๊ธฐ๋ก, ์๋ฆผ, ์ฌ์ฉ์๋ ์ง์ญ ๊ฐ ๋น๊ต๊ฐ ํ์ํ ๊ฒ๋ค. PostgreSQL์ ์ด๋ฅผ ์ ๋ ์์ ์ผ๋ก ์ ์ฅํ๊ณ ํ์ํ ๋ ๋ณํํ๋ฏ๋ก ์ ๋ ฌ๊ณผ ์ค๋ณต ๊ฒ์ฌ์์ ๊ธฐ๋ํ ๋์์ ํฉ๋๋ค.
๋ก์ปฌ ๋ฒฝ์๊ณ ๊ฐ์๋ timestamp without time zone(๋๋ ๋จ์ํ time/date ์กฐํฉ)์ ์ฌ์ฉํ์ธ์. ์: โ๋งค์ฃผ ์์์ผ 09:00โ ๊ฐ์ ๊ฐ์ ์์ฒด๋ก ์ธ์คํดํธ๊ฐ ์๋๋ฏ๋ก ์๊ฐ๋ ์๋ณ์์ ์์ผ๋ก ์ ์ฅํ๊ณ ๋ฐ์์ ์์ฑํ ๋๋ง ์ธ์คํดํธ๋ก ๋ณํํฉ๋๋ค.
๋ฐ๋ณต ํจํด์๋ ๊ธฐ๋ณธ ํ์ ๋ค์ด ๋์์ด ๋ฉ๋๋ค:
date๋ ๋ ์ง ๋จ์ ์์ธ(๊ณตํด์ผ)์ ์ ์ฉtime์ ์ผ๋ณ ์์ ์๊ฐinterval์ ์ง์ ์๊ฐ(์: 6์๊ฐ ๊ต๋)
์๊ฐ๋๋ IANA ์ด๋ฆ(์: America/New_York)์ผ๋ก text ์ปฌ๋ผ์ ์ ์ฅํ์ธ์(๋๋ ์์ ๋ฃฉ์
ํ
์ด๋ธ). -0500 ๊ฐ์ ์คํ์
์ DST ๊ท์น์ ํฌํจํ์ง ์์ผ๋ฏ๋ก ์ถฉ๋ถํ์ง ์์ต๋๋ค.
๋ง์ ์ฑ์ ์ค์ฉ์ ์ธ ์ธํธ:
- ์์ฝ๋ ์ฝ์์ ์์/์ข
๋ฃ ์ธ์คํดํธ๋
timestamptz - ์์ธ์ผ์
date - ๋ฐ๋ณต ๋ก์ปฌ ์์ ์๊ฐ์
time - ์ง์ ์๊ฐ์
interval - IANA ์๊ฐ๋ ID๋
text
์์ฝ ๋ฐ ๊ต๋ ์ฑ์ ์ํ ๋ฐ์ดํฐ ๋ชจ๋ธ ์ต์
์ต๊ณ ์ ์คํค๋ง๋ ์ค์ผ์ค์ด ์ผ๋ง๋ ์์ฃผ ๋ฐ๋๋์ง์ ์ฌ์ฉ์๊ฐ ์ผ๋ง๋ ๋ฉ๋ฆฌ ์์ ์กฐํํ๋์ง์ ๋ฐ๋ผ ๋ค๋ฆ ๋๋ค. ๋ณดํต์ ์ฒ์์ ๋ง์ ํ์ ์ฐ๊ฑฐ๋ ์ฝ์ ๋ ์์ฑํ๋ ๊ฒ ์ค ํ๋๋ฅผ ์ ํํ๊ฒ ๋ฉ๋๋ค.
์ต์ A: ๋ชจ๋ ๋ฐ์์ ์ ์ฅํ๊ธฐ
ํ์ฅ๋ ๊ฐ ๊ต๋๋ ์์ฝ๋ง๋ค ํ ํ์ ์ฝ์ ํฉ๋๋ค. ์ฟผ๋ฆฌ๊ฐ ์ฝ๊ณ ์ดํดํ๊ธฐ ์ฝ์ต๋๋ค. ๋์ ์ฐ๊ธฐ ๋น์ฉ์ด ํฌ๊ณ ๊ท์น์ด ๋ฐ๋๋ฉด ๋ง์ ์ ๋ฐ์ดํธ๊ฐ ํ์ํฉ๋๋ค.
์ด ๋ฐฉ์์ ์ด๋ฒคํธ๊ฐ ๋๋ถ๋ถ ์ผํ์ฑ์ด๊ฑฐ๋, ์์ผ๋ก ์งง์ ๊ธฐ๊ฐ(์: ๋ค์ 30์ผ)๋ง ์์ฑํ ๊ฒฝ์ฐ ์ ๋ง์ต๋๋ค.
์ต์ B: ๊ท์น์ ์ ์ฅํ๊ณ ์ฝ์ ๋ ํ์ฅํ๊ธฐ
์ค์ผ์ค ๊ท์น(์: "America/New_York์์ ๋งค์ฃผ ์ยท์ ์ค์ 9์")์ ์ ์ฅํ๊ณ ์์ฒญ๋ ๋ฒ์์์ ๋ฐ์์ ์จ๋๋งจ๋๋ก ์์ฑํฉ๋๋ค.
์ ์ฐํ๊ณ ์ ์ฅ ๊ณต๊ฐ์ด ์ ๊ฒ ๋ค์ง๋ง, ์ฟผ๋ฆฌ๊ฐ ๋ ๋ณต์กํด์ง๋๋ค. ์๋ณ ๋ณด๊ธฐ์์๋ ๋๋ ค์ง ์ ์์ผ๋ฏ๋ก ์บ์๊ฐ ํ์ํ ์ ์์ต๋๋ค.
์ต์ C: ๊ท์น + ์บ์๋ ๋ฐ์(ํ์ด๋ธ๋ฆฌ๋)
๊ท์น์ ์ง์ค์ ๊ทผ์์ผ๋ก ๋๊ณ , ๋กค๋ง ์๋์ฐ(์: 60-90์ผ) ๋์ ์์ฑ๋ ๋ฐ์์ ์ ์ฅํฉ๋๋ค. ๊ท์น์ด ๋ฐ๋๋ฉด ์บ์๋ฅผ ๋ค์ ์์ฑํฉ๋๋ค.
์ด ๋ฐฉ๋ฒ์ ๊ต๋ ์ฑ์ ์ข์ ๊ธฐ๋ณธ๊ฐ์ ๋๋ค: ์๋ทฐ๋ ๋น ๋ฅด๊ฒ ์ ์ง๋์ง๋ง ํจํด์ ํธ์งํ ํ ๊ณณ์ด ๋จ์ ์์ต๋๋ค.
์ค์ฉ์ ์ธ ํ ์ด๋ธ ์ธํธ:
- schedule: ์์ ์/๋ฆฌ์์ค, ์๊ฐ๋, ๋ก์ปฌ ์์ ์๊ฐ, ์ง์ ์๊ฐ, ๋ฐ๋ณต ๊ท์น
- occurrence:
start_at timestamptz,end_at timestamptz์ ์ํ๋ฅผ ํฌํจํ ํ์ฅ๋ ์ธ์คํด์ค - exception: "์ด ๋ ์ง๋ ๊ฑด๋๋" ๋๋ "์ด ๋ ์ง๋ ๋ค๋ฆ" ํ์์
- override: ํน์ ๋ฐ์์ ๋ํ ์์ (๋ณ๊ฒฝ๋ ์์ ์๊ฐ, ๊ต๋ ๊ต์ฒด, ์ทจ์ ํ๋๊ทธ)
- (์ ํ) schedule_cache_state: ๋ง์ง๋ง ์์ฑ๋ ๋ฒ์๋ก ๋ค์์ ์ฑ์์ผ ํ ๋ฒ์๋ฅผ ์ ์ ์์
์บ๋ฆฐ๋ ๋ฒ์ ์ฟผ๋ฆฌ์ฉ ์ธ๋ฑ์ค:
- occurrence:
btree (resource_id, start_at)๋ฐ ์ข ์ขbtree (resource_id, end_at) - ๋ฒ์ ์ค์ฒฉ(overlaps) ์ฟผ๋ฆฌ๊ฐ ๋ง๋ค๋ฉด:
tstzrange(start_at, end_at)์์ฑ ์ปฌ๋ผ๊ณผgist์ธ๋ฑ์ค
๊ท์น์ ์ทจ์ฝํ๊ฒ ๋ง๋ค์ง ์๊ณ ๋ฐ๋ณต ๊ท์น ํํํ๊ธฐ
๋ฐ๋ณต ์ค์ผ์ค์ ๊ท์น์ด ์ง๋์น๊ฒ ๋ณต์กํ๊ฑฐ๋ ์ ์ฐํ๊ฑฐ๋ ์ฟผ๋ฆฌ ๋ถ๊ฐ๋ฅํ ๋ธ๋กญ์ผ๋ก ์ ์ฅ๋ ๋ ๊นจ์ง๋๋ค. ์ข์ ๊ท์น ํ์์ ์ฑ์์ ๊ฒ์ฆํ ์ ์๊ณ ํ์ด ๋น ๋ฅด๊ฒ ์ค๋ช ํ ์ ์๋ ๊ฒ์ ๋๋ค.
๋ ๊ฐ์ง ์ผ๋ฐ์ ์ ๊ทผ:
- ์ค์ ๋ก ์ง์ํ๋ ํจํด์ ๋ํด ๊ฐ๋จํ ์ปค์คํ ํ๋๋ฅผ ์ฌ์ฉ(์ฃผ๊ฐ ๊ต๋, ์๊ฐ ์ฒญ๊ตฌ์ผ ๋ฑ)
- ๋ง์ ์กฐํฉ์ ์ง์ํ๊ฑฐ๋ ์บ๋ฆฐ๋๋ฅผ ๊ฐ์ ธ์ค๊ณ ๋ด๋ณด๋ด์ผ ํ๋ฉด iCalendar ์คํ์ผ(RRULE) ์ฌ์ฉ
์ค์ฉ์ ์ธ ์ ์ถฉ์: ์ ํ๋ ์ต์ ์ ํ์ฉํ๊ณ ์ปฌ๋ผ์ ์ ์ฅํ๋ RRULE ๋ฌธ์์ด์ ๊ตํ์ฉ์ผ๋ก๋ง ์ทจ๊ธํ์ธ์.
์: ์ฃผ๊ฐ ๊ต๋ ๊ท์น์ ๋ค์ ํ๋๋ก ํํํ ์ ์์ต๋๋ค:
freq(daily/weekly/monthly)์interval(๋งค Nํ)byweekday(0-6 ๋ฐฐ์ด ๋๋ ๋นํธ๋ง์คํฌ)- ์๊ฐ ๊ท์น์ ์ํ ์ ํ์
bymonthday(1-31) - ์ฌ์ฉ์๊ฐ ์ ํํ
starts_at_local(๋ก์ปฌ ๋ ์ง+์๊ฐ)๊ณผtzid - ์ ํ์
until_date๋๋count(๋ ๊ฐ์ง๋ฅผ ๋ชจ๋ ์ง์ํ์ง ์๋ ๊ฒ์ ๊ถ์ฅ)
๊ฒฝ๊ณ๋ **์ง์ ์๊ฐ(duration)**์ ์ ์ฅํ๋ ๊ฒ์ด ์ข์ต๋๋ค(์: 8์๊ฐ) โ ๊ฐ ๋ฐ์์ ์ข ๋ฃ ํ์์คํฌํ๋ฅผ ๋งค๋ฒ ์ ์ฅํ๋ ๋์ . ์ง์ ์๊ฐ์ ์๊ณ๊ฐ ์ด๋ํด๋ ์์ ์ ์ ๋๋ค. ๋ฐ์๋ณ ์ข ๋ฃ ์๊ฐ์: ์์ + ์ง์ ์๊ฐ์ผ๋ก ๊ณ์ฐํ ์ ์์ต๋๋ค.
๊ท์น์ ํ์ฅํ ๋๋ ์์ ํ๊ณ ํ์ ๋ ๋ฒ์๋ก ํ์ธ์:
window_start์window_end๋ด์์๋ง ํ์ฅํฉ๋๋ค.- ๋ฐค์ ์ด๋ฒคํธ๋ฅผ ์ํด ์์ ๋ฒํผ(์: 1์ผ)๋ฅผ ์ถ๊ฐํฉ๋๋ค.
- ์ต๋ ์ธ์คํด์ค ์(์: 500) ์ดํ ์ค๋จํฉ๋๋ค.
- ์์ฑ ์ ์ ํ๋ณด๋ฅผ ๋จผ์ ํํฐ๋ง(์:
tzid,freq, ์์ ๋ ์ง)ํฉ๋๋ค.
๋จ๊ณ๋ณ: DST ์์ ํ ๋ฐ๋ณต ์ค์ผ์ค ๊ตฌ์ถํ๊ธฐ
์ ๋ขฐํ ์ ์๋ ํจํด์: ๊ฐ ๋ฐ์์ ๋จผ์ ๋ก์ปฌ ์บ๋ฆฐ๋ ์๋(๋ ์ง + ๋ก์ปฌ ์๊ฐ + ์ฅ์์ ์๊ฐ๋)๋ก ์ทจ๊ธํ๊ณ , ์ ๋ ฌ, ์ถฉ๋ ๊ฒ์ฌ ๋๋ ํ์๊ฐ ํ์ํ ๋๋ง ์ธ์คํดํธ๋ก ๋ณํํ๋ ๊ฒ์ ๋๋ค.
1) UTC ์ถ์ธก์ด ์๋ ๋ก์ปฌ ์๋๋ฅผ ์ ์ฅํ์ธ์
์ค์ผ์ค์ ์์น ์๊ฐ๋(IANA ์ด๋ฆ, ์: America/New_York)์ ๋ก์ปฌ ์์ ์๊ฐ(์: 09:00)์ ์ ์ฅํ์ธ์. ์ด ๋ก์ปฌ ์๊ฐ์ ๋น์ฆ๋์ค๊ฐ ์๋ฏธํ๋ ๋ฐ์ด๋ฉฐ DST๊ฐ ๋ฐ๋์ด๋ ์ ์ง๋ฉ๋๋ค.
๋ํ ์ง์ ์๊ฐ๊ณผ ๋ช ํํ ๊ฒฝ๊ณ(์์ ๋ ์ง์ ์ข ๋ฃ ๋ ์ง ๋๋ ๋ฐ๋ณต ํ์)๋ฅผ ์ ์ฅํ์ธ์. ๊ฒฝ๊ณ๋ "๋ฌดํ ํ์ฅ" ๋ฒ๊ทธ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
2) ์์ธ์ ์ค๋ฒ๋ผ์ด๋๋ฅผ ๋ณ๋๋ก ๋ชจ๋ธ๋งํ์ธ์
๊ฑด๋๋ธ ๋ ์ง์ ๋ณ๊ฒฝ๋ ๋ฐ์์ ์ํ ๋ ๊ฐ์ ์์ ํ
์ด๋ธ์ ์ฌ์ฉํ์ธ์. schedule_id + local_date๋ก ํค๋ฅผ ์ง์ ํ๋ฉด ์๋ ๋ฐ๋ณต๊ณผ ์ ํํ ๋งค์นญํ ์ ์์ต๋๋ค.
์ค์ฉ์ ๊ตฌ์กฐ ์:
-- core schedule
-- tz is the location time zone
-- start_time is local wall-clock time
schedule(id, tz text, start_date date, end_date date, start_time time, duration_mins int, by_dow int[])
schedule_skip(schedule_id, local_date date)
schedule_override(schedule_id, local_date date, new_start_time time, new_duration_mins int)
3) ์์ฒญ๋ ์๋์ฐ ์์์๋ง ํ์ฅํ์ธ์
๋ ๋๋งํ ๋ฒ์(์ฃผ, ์ ๋ฑ)์ ๋ก์ปฌ ๋ ์ง ํ๋ณด๋ง ์์ฑํฉ๋๋ค. ์์ผ๋ก ํํฐ๋งํ ๋ค ๊ฑด๋๋ฐ๊ธฐ์ ์ค๋ฒ๋ผ์ด๋๋ฅผ ์ ์ฉํ์ธ์.
WITH days AS (
SELECT d::date AS local_date
FROM generate_series($1::date, $2::date, interval '1 day') d
), base AS (
SELECT s.id, s.tz, days.local_date,
make_timestamp(extract(year from days.local_date)::int,
extract(month from days.local_date)::int,
extract(day from days.local_date)::int,
extract(hour from s.start_time)::int,
extract(minute from s.start_time)::int, 0) AS local_start
FROM schedule s
JOIN days ON days.local_date BETWEEN s.start_date AND s.end_date
WHERE extract(dow from days.local_date)::int = ANY (s.by_dow)
)
SELECT b.id,
(b.local_start AT TIME ZONE b.tz) AS start_utc
FROM base b
LEFT JOIN schedule_skip sk
ON sk.schedule_id = b.id AND sk.local_date = b.local_date
WHERE sk.schedule_id IS NULL;
4) ๋ณํ์ ๋งจ ๋ง์ง๋ง์, ๋ทฐ์ด์ฉ์ผ๋ก๋ง ํ์ธ์
์ ๋ ฌ, ์ถฉ๋ ๊ฒ์ฌ, ์์ฝ์๋ start_utc๋ฅผ timestamptz๋ก ์ ์งํ์ธ์. ํ์ํ ๋๋ง ๋ทฐ์ด์ ์๊ฐ๋๋ก ๋ณํํ๋ฉด DST ๋๋ผ์์ ํผํ๊ณ ์บ๋ฆฐ๋ ๋ทฐ๋ฅผ ์ผ๊ด๋๊ฒ ์ ์งํ ์ ์์ต๋๋ค.
์ฌ๋ฐ๋ฅธ ์บ๋ฆฐ๋ ๋ทฐ๋ฅผ ์์ฑํ๋ ์ฟผ๋ฆฌ ํจํด
์บ๋ฆฐ๋ ํ๋ฉด์ ๋ณดํต ๋ฒ์ ์ฟผ๋ฆฌ์
๋๋ค: โfrom_ts์ to_ts ์ฌ์ด์ ๋ชจ๋ ๊ฒ์ ๋ณด์ฌ์ค.โ ์์ ํ ํจํด์:
- ํด๋น ์๋์ฐ์ ํ๋ณด๋ง ํ์ฅํฉ๋๋ค.
- ์์ธ/์ค๋ฒ๋ผ์ด๋๋ฅผ ์ ์ฉํฉ๋๋ค.
- ์ต์ข
ํ์
start_at์end_at์timestamptz๋ก ์ถ๋ ฅํฉ๋๋ค.
generate_series๋ก ์ผ๊ฐ ๋๋ ์ฃผ๊ฐ ํ์ฅ
๊ฐ๋จํ ์ฃผ๊ฐ ๊ท์น(์: "๋งค์ฃผ ์~๊ธ ๋ก์ปฌ ์ค์ 9์")์๋ ์ค์ผ์ค์ ์๊ฐ๋์์ ๋ก์ปฌ ๋ ์ง๋ฅผ ์์ฑํ ๋ค์, ๊ฐ ๋ก์ปฌ ๋ ์ง + ๋ก์ปฌ ์๊ฐ์ ์ธ์คํดํธ๋ก ๋ณํํ์ธ์.
-- Inputs: :from_ts, :to_ts are timestamptz
-- rule.tz is an IANA zone like 'America/New_York'
WITH bounds AS (
SELECT
(:from_ts AT TIME ZONE rule.tz)::date AS from_local_date,
(:to_ts AT TIME ZONE rule.tz)::date AS to_local_date
FROM rule
WHERE rule.id = :rule_id
), days AS (
SELECT d::date AS local_date
FROM bounds, generate_series(from_local_date, to_local_date, interval '1 day') AS g(d)
)
SELECT
(local_date + rule.start_local_time) AT TIME ZONE rule.tz AS start_at,
(local_date + rule.end_local_time) AT TIME ZONE rule.tz AS end_at
FROM rule
JOIN days ON true
WHERE EXTRACT(ISODOW FROM local_date) = ANY(rule.by_isodow);
์ด ๋ฐฉ๋ฒ์ ๋ฐ์๋ง๋ค timestamptz๋ก ๋ณํํ๋ฏ๋ก DST ๋ณํ๊ฐ ํด๋น ๋ ์ง์ ์ฌ๋ฐ๋ฅด๊ฒ ์ ์ฉ๋ฉ๋๋ค.
"n๋ฒ์งธ ์์ผ" ๊ฐ์ ๋ณต์กํ ๊ท์น์๋ ์ฌ๊ท CTE
๊ท์น์ด "n๋ฒ์งธ ์์ผ"์ด๋ ๊ฐญ, ์ปค์คํ
๊ฐ๊ฒฉ์ ์์กดํ๋ฉด ์ฌ๊ท CTE๋ก ๋ค์ ๋ฐ์์ ๋ฐ๋ณต ์์ฑํด to_ts๋ฅผ ์ง๋ ๋๊น์ง ๋ง๋ค ์ ์์ต๋๋ค. ๋ฐ๋์ ์๋์ฐ์ ๊ณ ์ ํ์ฌ ๋ฌดํ ๋ฃจํ๋ฅผ ๋ฐฉ์งํ์ธ์.
ํ๋ณด ํ์ ์ป์ผ๋ฉด (rule_id, start_at) ๋๋ (rule_id, local_date) ๊ฐ์ ๋ก์ปฌ ํค๋ก ์์ธ์ ์ทจ์๋ฅผ ์กฐ์ธํด ์ ์ฉํ์ธ์. ์ทจ์ ๋ ์ฝ๋๊ฐ ์์ผ๋ฉด ํ์ ์ ๊ฑฐํ๊ณ , ์ค๋ฒ๋ผ์ด๋๊ฐ ์์ผ๋ฉด start_at/end_at์ ์ค๋ฒ๋ผ์ด๋ ๊ฐ์ผ๋ก ๊ต์ฒดํฉ๋๋ค.
์ฑ๋ฅ ๊ด๋ จ ํจํด:
- ์ด๊ธฐ์ ๋ฒ์๋ฅผ ์ ํํ์ธ์: ๊ท์น์ ๋จผ์ ํํฐ๋งํ ๋ค
[from_ts, to_ts)๋ด์์๋ง ํ์ฅํฉ๋๋ค. - ์์ธ/์ค๋ฒ๋ผ์ด๋ ํ
์ด๋ธ์
(rule_id, start_at)๋๋(rule_id, local_date)์ ์ธ๋ฑ์คํ์ธ์. - ์๋ทฐ๋ฅผ ์ํด ์๋ ์น๋ฅผ ํ์ฅํ์ง ๋ง์ธ์.
- ๊ท์น์ด ๋ฐ๋ ๋ ๊น๋ํ๊ฒ ๋ฌดํจํํ ์ ์๋ค๋ฉด ํ์ฅ๋ ๋ฐ์์ ์บ์ํ์ธ์.
์์ธ์ ์ค๋ฒ๋ผ์ด๋๋ฅผ ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ๊ธฐ
๋ฐ๋ณต ์ค์ผ์ค์ ์์ ํ๊ฒ ๊นจ์ง ์ ์์ด์ผ ์ค์ฉ์ ์ ๋๋ค. ์์ฝ๊ณผ ๊ต๋ ์ฑ์์ โ์ ์โ ์ฃผ๋ ๊ธฐ๋ณธ ๊ท์น์ด๊ณ , ๋๋จธ์ง๋ ์์ธ์ ๋๋ค: ๊ณตํด์ผ, ์ทจ์, ์ด๋๋ ์ฝ์, ์ง์ ๊ต์ฒด ๋ฑ. ์์ธ๋ฅผ ๋์ค์ ๋ง๋ถ์ด๋ฉด ์บ๋ฆฐ๋ ๋ทฐ๊ฐ ์ด๊ธ๋๊ฑฐ๋ ์ค๋ณต์ด ์๊น๋๋ค.
์ธ ๊ฐ์ง ๊ฐ๋ ์ ๋ถ๋ฆฌํ์ธ์:
- ๊ธฐ๋ณธ ์ค์ผ์ค(๋ฐ๋ณต ๊ท์น๊ณผ ๊ทธ ์๊ฐ๋)
- ๊ฑด๋๋ฐ๊ธฐ(๋ฐ์ํ์ง ๋ง์์ผ ํ ๋ ์ง/์ธ์คํด์ค)
- ์ค๋ฒ๋ผ์ด๋(๋ฐ์์ ์กด์ฌํ์ง๋ง ์ธ๋ถ๊ฐ ๋ณ๊ฒฝ๋จ)
๊ณ ์ ๋ ์ฐ์ ์์ ์ฌ์ฉ
ํ ๊ฐ์ง ์์๋ฅผ ์ ํ๊ณ ์ผ๊ด๋๊ฒ ์ ์งํ์ธ์. ์ผ๋ฐ์ ์ธ ์ ํ:
- ๊ธฐ๋ณธ ๋ฐ๋ณต์์ ํ๋ณด ์์ฑ
- ์ค๋ฒ๋ผ์ด๋ ์ ์ฉ(์์ฑ๋ ๊ฒ์ ๋์ฒด)
- ๊ฑด๋๋ฐ๊ธฐ ์ ์ฉ(์จ๊น)
์ฌ์ฉ์์๊ฒ ํ ๋ฌธ์ฅ์ผ๋ก ์ค๋ช ํ๊ธฐ ์ฌ์ด ๊ท์น์ด์ด์ผ ํฉ๋๋ค.
์ค๋ฒ๋ผ์ด๋๊ฐ ์ธ์คํด์ค๋ฅผ ๋์ฒดํ ๋ ์ค๋ณต ๋ฐฉ์ง
์ค๋ณต์ ์ฟผ๋ฆฌ๊ฐ ์์ฑ๋ ๋ฐ์๊ณผ ์ค๋ฒ๋ผ์ด๋ ํ์ ๋ ๋ค ๋ฐํํ ๋ ์์ฃผ ๋ฐ์ํฉ๋๋ค. ์์ ์ ํค๋ก ๋ฐฉ์งํ์ธ์:
- ๊ฐ ์์ฑ๋ ์ธ์คํด์ค์
(schedule_id, local_date, start_time, tzid)๊ฐ์ ์์ ํค๋ฅผ ๋ถ์ฌํ์ธ์. - ์ค๋ฒ๋ผ์ด๋ ํ์ ์ด ํค๋ฅผ "์๋ ๋ฐ์ ํค"๋ก ์ ์ฅํ์ธ์.
- ๊ธฐ๋ณธ ๋ฐ์๋น ํ๋์ ์ค๋ฒ๋ผ์ด๋๋ง ์กด์ฌํ๋๋ก ๊ณ ์ ์ ์ฝ์ ์ถ๊ฐํ์ธ์.
๊ทธ๋ฐ ๋ค์ ์ฟผ๋ฆฌ์์ ๋งค์นญ๋๋ ์ค๋ฒ๋ผ์ด๋๊ฐ ์๋ ์์ฑ๋ ๋ฐ์์ ์ ์ธํ๊ณ ์ค๋ฒ๋ผ์ด๋ ํ์ ํฉ์น๋ฉด ์ค๋ณต์ ํผํ ์ ์์ต๋๋ค.
๊ฐ์ฌ ๊ฐ๋ฅ์ฑ ์ ์ง
์์ธ๋ ๋ถ์์ด ๋ฐ์ํ๊ธฐ ์ฌ์ด ๊ณณ์
๋๋ค("๋๊ฐ ๋ด ๊ต๋๋ฅผ ๋ฐ๊ฟจ์ง?"). skips์ overrides์ ๊ธฐ๋ณธ ๊ฐ์ฌ ํ๋(created_by, created_at, updated_by, updated_at, ์ ํ์ ์ด์ )๋ฅผ ์ถ๊ฐํ์ธ์.
ํ ์๊ฐ ์ค์ฐจ ๋ฒ๊ทธ๋ฅผ ์ผ์ผํค๋ ํํ ์ค์
๋๋ถ๋ถ์ ํ ์๊ฐ ๋ฒ๊ทธ๋ ์ธ์คํดํธ(UTC ํ์๋ผ์ธ์ ์ )์ ๋ก์ปฌ ์๊ณ ์ฝ๊ธฐ(์: ๋ด์์ ๋งค์ฃผ ์์์ผ 09:00)๋ฅผ ํผ๋ํ๋ ๋ฐ์ ์ต๋๋ค.
์ ํ์ ์ธ ์ค์๋ ๋ก์ปฌ ๋ฒฝ์๊ณ ๊ท์น์ timestamptz๋ก ์ ์ฅํ๋ ๊ฒ์
๋๋ค. "๋ด์์ ์์์ผ ์ค์ 9์"๋ฅผ ๋จ์ผ timestamptz๋ก ์ ์ฅํ๋ฉด ์ด๋ฏธ ํน์ ๋ ์ง(๋ฐ ๊ทธ๋์ DST ์ํ)๋ฅผ ์ ํํ ์
์ด ๋ฉ๋๋ค. ์ดํ ๋ฏธ๋์ ์์์ผ์ ์์ฑํ ๋ ์๋ ์๋("ํญ์ ๋ก์ปฌ 09:00")๋ ์ฌ๋ผ์ง๋๋ค.
๋ ๋ค๋ฅธ ๋น๋ฒํ ์์ธ์ -05:00 ๊ฐ์ ๊ณ ์ UTC ์คํ์
์ ์์กดํ๋ ๊ฒ์
๋๋ค. ์คํ์
์ DST ๊ท์น์ ํฌํจํ์ง ์์ต๋๋ค. IANA ์กด ์ด๋ฆ(์: America/New_York)์ ์ ์ฅํ๊ณ PostgreSQL์ด ๊ฐ ๋ ์ง์ ๋ง๋ ๊ท์น์ ์ ์ฉํ๊ฒ ํ์ธ์.
๋ณํ ์์ ์ ์กฐ์ฌํ์ธ์. ๋ฐ๋ณต ์์ฑ ์ค์ ๋๋ฌด ์ผ์ฐ UTC๋ก ๋ณํํ๋ฉด DST ์คํ์ ์ ๊ณ ์ ํด ๋งค ๋ฐ์์ ์ ์ฉํ ์ ์์ต๋๋ค. ๋ ์์ ํ ํจํด์: ๋ฐ์์ ๋ก์ปฌ(๋ ์ง + ๋ก์ปฌ ์๊ฐ + ์กด)์ผ๋ก ์์ฑํ ๋ค ๊ฐ ๋ฐ์์ ์ธ์คํดํธ๋ก ๋ณํํ๋ ๊ฒ์ ๋๋ค.
์์ฃผ ๋ฐ๋ณต๋๋ ์ค์ ๋ชฉ๋ก:
- ๋ฐ๋ณต ๋ก์ปฌ ์๊ฐ๋๋ฅผ ์ ์ฅํด์ผ ํ ๋
timestamptz๋ฅผ ์ฌ์ฉํจ(์ด๋ด ๋๋time+tzid+ ๊ท์น์ด ํ์) - IANA ์กด์ด ์๋๋ผ ์คํ์ ๋ง ์ ์ฅํจ
- ๋ฐ๋ณต ์์ฑ ์ค์ ๋ณํ์ ์ํํจ์ด ์๋๋ผ ๋ง์ง๋ง์ ๋ณํํจ
- ๋ฌดํํ ํ์ฅ๋๋ ๋ฐ๋ณต์ ํ๋ํ ์๊ฐ ์๋์ฐ ์์ด ํ์ฅํจ
- DST ์์ ์ฃผ์ ์ข ๋ฃ ์ฃผ๋ฅผ ํ ์คํธํ์ง ์์
๋๋ถ๋ถ์ ๋ฌธ์ ๋ฅผ ์ก๋ ๊ฐ๋จํ ํ ์คํธ: DST๊ฐ ์๋ ์กด์ ๊ณจ๋ผ ์ฃผ๊ฐ 09:00 ๊ต๋๋ฅผ ๋ง๋ค๊ณ DST ๋ณ๊ฒฝ์ ํฌํจํ ๋ ๋ฌ์ง๋ฆฌ ์บ๋ฆฐ๋๋ฅผ ๋ ๋๋งํ์ธ์. ๊ฐ ์ธ์คํด์ค๊ฐ ๋ก์ปฌ ๊ธฐ์ค์ผ๋ก ๋งค๋ฒ 09:00์ผ๋ก ๋ณด์ด๋์ง ํ์ธํ์ธ์(๊ธฐ์ด๊ฐ ๋๋ UTC ์ธ์คํดํธ๋ ๋ฌ๋ผ์ง๋๋ค).
์ถ์ ์ ์ ํ์ธํ ๋น ๋ฅธ ์ฒดํฌ๋ฆฌ์คํธ
์ถ์ ์ ์ ๊ธฐ๋ณธ์ ์ ๊ฒํ์ธ์:
- ๋ชจ๋ ์ค์ผ์ค์ด ๋ช ๋ช ๋ ์๊ฐ๋์ ์ฐ๊ณ๋์ด ์๋๊ฐ(์ค์ผ์ค ์์ฒด์ ์ ์ฅ)?
- IANA ์กด ID(์:
America/New_York)๋ฅผ ์ ์ฅํ๊ณ ์๋๊ฐ, ์์ ์คํ์ ์ด ์๋๊ฐ? - ๋ฐ๋ณต ํ์ฅ์ ์์ฒญ๋ ๋ฒ์ ๋ด์์๋ง ์ด๋ฃจ์ด์ง๋๊ฐ?
- ์์ธ์ ์ค๋ฒ๋ผ์ด๋์ ๋จ์ผ ๋ฌธ์ํ๋ ์ฐ์ ์์๊ฐ ์๋๊ฐ?
- DST ๋ณ๊ฒฝ ์ฃผ์ ์ค์ผ์ค ์๊ฐ๋์ ๋ค๋ฅธ ์๊ฐ๋์ ๋ทฐ์ด๋ฅผ ํ ์คํธํ๋๊ฐ?
ํ์ค์ ์ธ ๋๋ผ์ด๋ฐ์ ํ๋ ํด๋ณด์ธ์: Europe/Berlin์ ๋งค์ฃผ 09:00 ๊ต๋๊ฐ ์๊ณ ๋งค๋์ ๋ America/Los_Angeles์์ ๋ด
๋๋ค. ๊ฐ ์ฃผ๋ง๋ค ๊ต๋๊ฐ ๋ฒ ๋ฅผ๋ฆฐ ์๊ฐ์ผ๋ก 09:00์ผ๋ก ์ ์ง๋๋์ง, ๊ฐ ์ง์ญ์ DST๊ฐ ๋ค๋ฅด๊ฒ ๋ฐ๋์ด๋ ์ ์ง๋๋์ง ํ์ธํ์ธ์.
์์: ๊ณตํด์ผ๊ณผ DST ๋ณ๊ฒฝ์ด ํฌํจ๋ ์ฃผ๊ฐ ์ง์ ๊ต๋
์์ ํด๋ฆฌ๋์ด ๋งค์ฃผ ์์์ผ 09:00~17:00 America/New_York ํ์ง ์๊ฐ์ผ๋ก ๋ฐ๋ณต ๊ต๋๋ฅผ ์ด์ํฉ๋๋ค. ํ ์ฃผ์ ์์์ผ์ ๊ณตํด์ผ์ด๋ผ ๋ฌธ์ ๋ซ์ต๋๋ค. ํ ์ง์์ 2์ฃผ๊ฐ ์ ๋ฝ์ผ๋ก ์ด๋ ์ค์ด์ง๋ง ์ค์ผ์ค์ ์ง์์ ์์น๊ฐ ์๋๋ผ ํด๋ฆฌ๋์ ๋ฒฝ์๊ณ์ ๋ฌถ์ฌ ์์ด์ผ ํฉ๋๋ค.
์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๊ฒ ํ๋ ค๋ฉด:
- ์์ผ = ์์์ผ, ๋ก์ปฌ ์๊ฐ = 09:00~17:00 ๊ฐ์ ๋ก์ปฌ ๋ ์ง์ ๊ณ ์ ๋ ๋ฐ๋ณต ๊ท์น์ ์ ์ฅํ์ธ์.
- ์ค์ผ์ค ์๊ฐ๋(
America/New_York)๋ฅผ ์ ์ฅํ์ธ์. - ๊ท์น์ ๋ช ํํ ๊ธฐ์ค์ ์ด ๋๋๋ก ์ ํจ ์์ ๋ ์ง๋ฅผ ์ ์ฅํ์ธ์.
- ๊ณตํด์ผ ์์์ผ์ ์ทจ์ํ๋ ์์ธ(๋ฐ ์ผํ์ฑ ๋ณ๊ฒฝ์ ์ํ ์ค๋ฒ๋ผ์ด๋)๋ฅผ ์ ์ฅํ์ธ์.
์ด์ DST ๋ณ๊ฒฝ์ ํฌํจํ๋ 2์ฃผ ๋ฒ์๋ฅผ ๋ ๋๋งํ๋ฉด, ์ฟผ๋ฆฌ๋ ํด๋น ๋ก์ปฌ ๋ ์ง ๋ฒ์์ ์์์ผ๋ค์ ์์ฑํ๊ณ ํด๋ฆฌ๋์ ๋ก์ปฌ ์๊ฐ์ ๋ถ์ธ ๋ค ๊ฐ ๋ฐ์์ ์ ๋ ์ธ์คํดํธ(timestamptz)๋ก ๋ณํํฉ๋๋ค. ๋ณํ์ด ๋ฐ์๋ง๋ค ์ผ์ด๋๋ฏ๋ก DST๋ ์ฌ๋ฐ๋ฅธ ๋ ์ง์ ์ฒ๋ฆฌ๋ฉ๋๋ค.
์๋ก ๋ค๋ฅธ ๋ทฐ์ด๋ ๋์ผํ ์ธ์คํดํธ์ ๋ํด ์๋ก ๋ค๋ฅธ ๋ก์ปฌ ์๊ฐ์ ๋ด ๋๋ค:
- ๋ก์ค์ค์ ค๋ ์ค์ ๋งค๋์ ๋ ์๊ณ์ ๋ ์ด๋ฅธ ์๊ฐ์ผ๋ก ๋ด ๋๋ค.
- ๋ฒ ๋ฅผ๋ฆฐ์ ์๋ ์ด๋ ์ค์ธ ์ง์์ ๋ ๋ฆ์ ์๊ฐ์ผ๋ก ๋ด ๋๋ค.
๊ทธ๋ผ์๋ ํด๋ฆฌ๋์ ์ํ ๊ฒ์ ์ป์ต๋๋ค: ๋งค์ฃผ ๊ณตํด์ผ์ด ์๋ ์์์ผ๋ง๋ค ๋ด์ ์๊ฐ์ผ๋ก 09:00~17:00.
๋ค์ ๋จ๊ณ: ๊ตฌํ, ํ ์คํธ, ์ ์ง๋ณด์์ฑ ํ๋ณด
์๊ฐ ์ ๊ทผ ๋ฐฉ์์ ์กฐ๊ธฐ์ ๊ณ ์ ํ์ธ์: ๊ท์น๋ง ์ ์ฅํ ์ง, ๋ฐ์๋ง ์ ์ฅํ ์ง, ์๋๋ฉด ํ์ด๋ธ๋ฆฌ๋์ผ์ง ๊ฒฐ์ ํ์ธ์. ๋ง์ ์์ฝยท๊ต๋ ์ ํ์๋ ํ์ด๋ธ๋ฆฌ๋๊ฐ ์ ๋ง์ต๋๋ค: ๊ท์น์ ์ง์ค์ ๊ทผ์์ผ๋ก ๋๊ณ ํ์ํ๋ฉด ๋กค๋ง ์บ์๋ฅผ ์ ์ฅํ๋ฉฐ ์์ธ์ ์ค๋ฒ๋ผ์ด๋๋ ๊ตฌ์ฒด์ ํ์ผ๋ก ์ ์ฅํฉ๋๋ค.
ํ ๊ณณ์ "์๊ฐ ๊ณ์ฝ(time contract)"์ ๋ฌธ์ํํ์ธ์: ๋ฌด์์ด ์ธ์คํดํธ์ธ์ง, ๋ฌด์์ด ๋ก์ปฌ ๋ฒฝ์๊ณ์ธ์ง, ๊ฐ ๊ฐ์ ์ด๋ ์ปฌ๋ผ์ ์ ์ฅํ๋์ง. ์ด๋ ๊ฒ ํ๋ฉด ํ ์๋ํฌ์ธํธ๋ ๋ก์ปฌ ์๊ฐ์ ๋ฐํํ๊ณ ๋ค๋ฅธ ์๋ํฌ์ธํธ๋ UTC๋ฅผ ๋ฐํํ๋ ์ํฉ์ ๋ฐฉ์งํ ์ ์์ต๋๋ค.
๋ฐ๋ณต ์์ฑ ๋ก์ง์ ํ๋์ ๋ชจ๋๋ก ์ ์งํ์ธ์. ๊ทธ๋์ผ "๋ก์ปฌ ์ค์ 9์"๋ฅผ ํด์ํ๋ ๋ฐฉ๋ฒ์ ๋ฐ๊ฟ ๋ ํ ๊ณณ๋ง ์ ๋ฐ์ดํธํ๋ฉด ๋ฉ๋๋ค.
๋ชจ๋ ๊ฒ์ ์์ผ๋ก ์ฝ๋ฉํ์ง ์๊ณ ์ค์ผ์ค๋ง ๋๊ตฌ๋ฅผ ๋ง๋ค๊ณ ์๋ค๋ฉด AppMaster (appmaster.io)์ ์ด๋ฐ ์์ ์ ์ค์ฉ์ ์ธ ์ ํ์ ๋๋ค: Data Designer์์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๋ชจ๋ธ๋งํ๊ณ , ์๊ฐ์ ๋น์ฆ๋์ค ํ๋ก์ธ์ค์์ ๋ฐ๋ณต๊ณผ ์์ธ ๋ก์ง์ ๊ตฌ์ฑํ๋ฉด ์ค์ ๋ก ์์ฑ ๊ฐ๋ฅํ ๋ฐฑ์๋์ ์ฑ ์ฝ๋๋ฅผ ์ป์ ์ ์์ต๋๋ค.


