EUV ์ค๋น ๋ด๋ถ ์ค์ผ์ด ํ์ฐ๋๋ฉด particle์ด reticle ๋๋ reticle stage(RS)์ ์ ์ ๋ ์ ์์ต๋๋ค. ์ด๋ก ์ธํด reticle์ scanner์ loadingํ๊ธฐ ์ ์ํํ๋ RBI(Reticle Backside Inspection) ๊ฒ์ฌ์์ fail์ด ๋ฐ์ํ๊ณ , reticle loading์ด ์งํ๋์ง ๋ชปํ๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํฉ๋๋ค.
๋ฐ๋ผ์ reticle backside ์ค์ผ๊ณผ ๊ด๋ จ๋ ๊ฒ์ฌ ํ ์คํธ ๋ฐ ์ด๋ฏธ์ง๋ฅผ ์์ ์ ์ผ๋ก ์์งํ๊ณ , ๋ฐ์ ์์ ๊ธฐ์ค์ผ๋ก ์ฐ๊ฒฐํด ๋ถ์ ๊ฐ๋ฅํ ํํ๋ก ๋ณด๊ดํ ์ ์๋ ์์คํ ์ด ํ์ํฉ๋๋ค.
RUBI ํ ์คํธ์ RUIP ์ด๋ฏธ์ง๋ฅผ ์์ง ๋ฐ ๋งค์นญํ์ฌ reticle backside ์ค์ผ ๋ถ์ ๋ฐ์ดํฐ๋ฅผ ๊ตฌ์ถํฉ๋๋ค. ํนํ RBI fail ์์ธ particle์ ๋ฐ์ ์์ ๊ณผ ๊ด๋ จ ์ด๋ฏธ์ง๋ฅผ ์ถ์ ํ ์ ์๋๋ก ํ ์คํธ ๊ฒ์ฌ ๊ฒฐ๊ณผ์ ์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ฅผ 1:1๋ก ์ฐ๊ฒฐํ๊ณ , ๋ณํ๋ PNG ๊ฒฐ๊ณผ๋ฌผ์ ๋ถ์ ์๋ฒ ๊ฒฝ๋ก์ ์ ๋ก๋ํ๋ ๋ฐฐ์น ํ์ดํ๋ผ์ธ์ ๊ตฌํํฉ๋๋ค.
๋ณธ ์์คํ ์ reticle ์ค์ผ ์์ธ ๋ถ์ ์๊ณ ๋ฆฌ์ฆ ์์ฒด๊ฐ ์๋๋ผ, ๋ถ์์ ํ์ํ ๊ฒ์ฌ ํ ์คํธ์ ์ด๋ฏธ์ง evidence๋ฅผ ์ ํฉ์ฑ ์๊ฒ ์ฐ๊ฒฐํ๋ ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ์ ๋๋ค. ๊ตฌํ ์ ์ ํํ ์ ์์๋ ์ฃผ์ ๊ธฐ์ ์ ๋ถ๊ธฐ์ ๊ณผ ํ์ฌ ์ ํ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
| ๋ถ๊ธฐ์ | ์ ํ ๊ฐ๋ฅ ๋ฐฉ์ | ํ์ฌ ์ ํ | ์ ํ ์ฌ์ |
|---|---|---|---|
| ์ฒ๋ฆฌ ๊ธฐ์ค | ์ด๋ฏธ์ง ๊ธฐ์ค, ํ ์คํธ ๊ธฐ์ค, ํ ์คํธ+์ด๋ฏธ์ง ํตํฉ ์ฒ๋ฆฌ | COMBINED ํ
์คํธ ๊ธฐ์ค ํตํฉ ์ฒ๋ฆฌ |
RBI ๊ฒ์ฌ ๊ฒฐ๊ณผ ํ ์คํธ๊ฐ ๊ธฐ์ค ๋ฐ์ดํฐ์ด๊ณ , ์ด๋ฏธ์ง๋ ๋ถ์ ๊ทผ๊ฑฐ ์๋ฃ๋ก ์ฐ๊ฒฐ๋๋ ๊ตฌ์กฐ๊ฐ ์ ํฉํฉ๋๋ค. |
| ๋งค์นญ ๋ฐฉ์ | ํ์ผ๋ช ๊ธฐ์ค, ์๊ฐ ๊ธฐ์ค, reticle ID/๊ฒ์ฌ ID ๊ธฐ์ค, ์๋ ๋งค์นญ | ํ์ผ๋ช
prefix์ timestamp ๊ธฐ๋ฐ ์๋ ๋งค์นญ |
ํ์ฌ ์ ๋ ฅ ๋ฐ์ดํฐ์์ ๊ณตํต์ผ๋ก ํ๋ณด ๊ฐ๋ฅํ ์๋ณ์๊ฐ ํ์ผ๋ช prefix์ ์์ฑ ์๊ฐ์ ๋๋ค. |
| ๋งค์นญ ์๊ฐ ๋ฒ์ | ๋์ผ ์๊ฐ๋ง ํ์ฉ, 1๋ถ ์ด๋ด, 5๋ถ ์ด๋ด, 10๋ถ ์ด์, ๊ฐ์ฅ ๊ฐ๊น์ด ํ์ผ ๋ฌด์กฐ๊ฑด ๋งค์นญ | 5๋ถ ์ด๋ด ์ต๊ทผ์ ์ด๋ฏธ์ง 1๊ฐ | ๋๋ฌด ์ข์ผ๋ฉด ์ ์ ๋ฐ์ดํฐ๊ฐ ๋๋ฝ๋๊ณ , ๋๋ฌด ๋์ผ๋ฉด ์๋ชป๋ ์ด๋ฏธ์ง๊ฐ ์ฐ๊ฒฐ๋ ์ ์์ด 5๋ถ์ ๊ธฐ์ค์ผ๋ก ๋ก๋๋ค. |
| ๋งค์นญ ์คํจ ์ฒ๋ฆฌ | ์ ์ฒด skip, ํ ์คํธ๋ง ์ ์ฅ, ๋ฏธ๋งค์นญ ์ํ ์ ์ฅ, ์๋ฌ ํ ์ฌ์๋ | COMBINED์์๋ ํ
์คํธ๋ง ์ ์ฅ |
ํ ์คํธ ๊ฒ์ฌ ๊ฒฐ๊ณผ๋ ๋ถ์์ ๊ธฐ์ค ๋ฐ์ดํฐ์ด๋ฏ๋ก ์ด๋ฏธ์ง๊ฐ ์์ด๋ ๋ณด์กดํฉ๋๋ค. |
| ์ค๋ณต ์ฒ๋ฆฌ | ๋งค๋ฒ ๋ณํ/์ ๋ก๋, ๊ธฐ์กด ๊ฒฐ๊ณผ skip, ํด์ ๋น๊ต, DB ์ํ๊ฐ ๊ธฐ์ค ์ฌ์ฒ๋ฆฌ | ์๋ฒ PNG ์กด์ฌ ์ skip, ๋ก์ปฌ PNG ์กด์ฌ ์ ์ฌ์ฌ์ฉ | ๋ฐ๋ณต ์คํ ์ ๋ถํ์ํ ์ด๋ฏธ์ง ๋ณํ๊ณผ ์ ๋ก๋ ๋น์ฉ์ ์ค์ ๋๋ค. |
| ์๋ฃ ๊ธฐ์ค | DB ์ ์ฅ ์ฑ๊ณต, PNG ๋ณํ ์ฑ๊ณต, ์๋ฒ ์ ๋ก๋ ์ฑ๊ณต, ์๋ณธ ์ญ์ ์ฑ๊ณต | ์๋ฒ ์ ๋ก๋ ์ฑ๊ณต ํ DB ์ ์ฅ ๋ฐ ์๋ณธ ์ญ์ | ๋ถ์ ์๋ฒ์ ๊ฒฐ๊ณผ ์ด๋ฏธ์ง๊ฐ ์๋ ์ํ์์ ์๋ฃ ์ฒ๋ฆฌ๋๋ ๋ฌธ์ ๋ฅผ ์ค์ ๋๋ค. |
| ์๋ณธ ํ์ผ ์ฒ๋ฆฌ | ์๋ณธ ์ ์ง, ์ฑ๊ณต ํ ์ญ์ , archive ์ด๋, ์คํจ ํ์ผ ๋ณ๋ ๋ณด๊ด | ์ฒ๋ฆฌ ์ฑ๊ณต ํ FTP ์๋ณธ ์ญ์ | ์ค๋ณต ์ฒ๋ฆฌ๋ฅผ ์ค์ด๊ณ ์ ๋ ฅ ๊ฒฝ๋ก๋ฅผ ์ ๋ฆฌํฉ๋๋ค. |
| ๋ ์ง ๋ฒ์ | ์ ๋ ฅ์ผ๋ง ์ฒ๋ฆฌ, ์ ๋ +์ ๋ ฅ์ผ ์ฒ๋ฆฌ, ์ ํ N์ผ ์ฒ๋ฆฌ, ๋ง์ง๋ง ์ฒ๋ฆฌ ์์ ์ดํ ์ฒ๋ฆฌ | ์ ๋ +์ ๋ ฅ์ผ 2์ผ ์ฒ๋ฆฌ | ์์ ์ ํ์ ์์ฑ๋ ํ ์คํธ์ ์ด๋ฏธ์ง์ ๋งค์นญ ๋๋ฝ์ ์ค์ ๋๋ค. |
์ด ํ๋ก์ ํธ๋ FTP ์๋ฒ์ RUBI ํ
์คํธ์ RUIP ์ด๋ฏธ์ง๋ฅผ ์์งํด ์ฒ๋ฆฌํ๋ reticle ์ค์ผ ๋ถ์์ฉ ๋ฐฐ์น์
๋๋ค.
RUBI: ํ ์คํธ ํ์ผ์ ํ์ฑํด SQLite์ ๋ฒํฌ ์ธ์ํธํฉ๋๋ค.RUPI: ์ด๋ฏธ์ง์ ํ ์คํธ๋ฅผ ๋งค์นญํด PNG๋ก ๋ณํํ๊ณ FTPrbi/ruip/.../*.png๋ก ์ ๋ก๋ํฉ๋๋ค.COMBINED: ํ ์คํธ๋ฅผ ๊ธฐ์ค์ผ๋ก ์ด๋ฏธ์ง๊น์ง ๊ฐ์ด ์ฒ๋ฆฌํ๋ ํตํฉ ๋ชจ๋์ ๋๋ค.
ํ์ฌ ์ด์ ๊ธฐ๋ณธ๊ฐ์ COMBINED ๊ธฐ์ค์
๋๋ค. ์
๋ ฅ์ผ ํ๋๋ฅผ ๋ฐ์ผ๋ฉด ๋ด๋ถ์ ์ผ๋ก ์ ๋ + ์
๋ ฅ์ผ ๋ ๋ ์ง๋ฅผ ํจ๊ป ์ฒ๋ฆฌํฉ๋๋ค.
ER_DOSE_RAW ๋ฐฐ์น๋ mbeat.er_data_raw์ dose warning ๋ก๊ทธ๋ฅผ ํ์ฑํด prism_common.er_dose_raw_parsed์ ์ ์ฌํ๋ฉฐ, ์์ง ์๋ฃ ํ prism_common.de_trend_die_yield_daily ์ผ๋ณ DIE Yield ์๋จธ๋ฆฌ ํ
์ด๋ธ์ ๊ฐฑ์ ํฉ๋๋ค. parsed ํ
์ด๋ธ์๋ eq_name, code, code_occur_time, title, contents์ contents์์ ์ค์ ๋ก ํ์ํ exposure_handle, action_handle, lot_id, lot_name, lot_seq, wafer_seq, de_err, n_slit, use_yn์ ์ ์ฅํฉ๋๋ค. ์กฐํ ๋์ code๋ DW-3411, DW-3425, DW-343A, DW-343B, LO-0050, LO-0051, LO-0052, LO-0061, LO-8166, LO-8167, KE-9103, KE-9104์ด๋ฉฐ, ์ฝ๋ ๊ฐ์ DB์ ์ ์ฅ๋ ์๋ณธ ํ์ ๊ทธ๋๋ก ๋น๊ตํฉ๋๋ค.
๋ฐฐ์น๋ code_occur_time ๊ธฐ๊ฐ ์กฐ๊ฑด์ผ๋ก ์กฐํํ ํ๋ณด๋ฅผ ํ ๋ฒ์ ๋ฉ๋ชจ๋ฆฌ๋ก ์ฌ๋ฆฌ์ง ์๊ณ , chunk ๋จ์๋ก ์ฝ์ด์ ํ์ฑ ํ ๋ฐ๋ก COPY ์ ์ฌํฉ๋๋ค. ํํฐ์
์ ์ฌ๋ ๊ณตํต copy_insert_to_partition_table์ ์ฌ์ฉํ๋ฉฐ, ์ ์ฌ ์ ์ DataFrame ์ปฌ๋ผ์ ํ
์ด๋ธ์ ๋ฌผ๋ฆฌ ์ปฌ๋ผ ์์์ ๋์ผํ๊ฒ ์ ๋ ฌํ ๋ค COPY ... FROM STDIN WITH CSV HEADER๋ฅผ ์คํํฉ๋๋ค. ํ์ฌ ๊ธฐ๋ณธ chunk ํฌ๊ธฐ๋ ER_DOSE_RAW ๋ฐ ER_DOSE_EUV ๋ฐฐ์น ๋ชจ๋ 30000์ด๋ฉฐ ์คํ ์ ์กฐ์ ํ ์ ์์ต๋๋ค. ์กฐํ๋ SQLAlchemy ์๋ฒ์ฌ์ด๋ ์ปค์(stream_results=True, max_row_buffer=chunk_size) ๊ธฐ๋ฐ ์คํธ๋ฆฌ๋ฐ์ผ๋ก ์ํ๋์ง๋ง, ์ค์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ chunk ํฌ๊ธฐ์ raw contents ํฌ๊ธฐ์ ์ํฅ์ ๋ฐ์ผ๋ฏ๋ก ์ด์ ํ๊ฒฝ์ ๋ง๊ฒ ์กฐ์ ํด์ผ ํฉ๋๋ค. ์ฒญํฌ ๋จ์๋ก ์ฒ๋ฆฌ๋๋๋ผ๋ ์ค๋น(eq_name)๋ณ๋ก ์ด์ ์ ํ์ฑํ lot_seq์ wafer_seq๋ฅผ ๊ธฐ์ตํ์ฌ ์ง์ ์ ์ฉํฉ๋๋ค. ER_DOSE_RAW์ ์ ์ฌ worker 1๊ฐ๋ฅผ ์ฌ์ฉํด ์ด์ ์ฒญํฌ์ COPY์ ๋ค์ ์ฒญํฌ์ ์กฐํยทํ์ฑ์ ๊ฒน์ณ ์คํํ๋ฉฐ, ๋๊ธฐ ์ค์ธ DataFrame์ ์ต๋ 1๊ฐ๋ก ์ ํํฉ๋๋ค. ์ด ๋ณ๊ฒฝ์ ์ด์ ์ค์ธก ๊ฒฐ๊ณผ๋ DB ์คํธ๋ฆฌ๋ฐ ๋ฐ RAW ์ฑ๋ฅ ๊ฐ์ ๋ฌธ์์ ๊ธฐ๋กํฉ๋๋ค.
ER_DOSE_RAW์ ER_DOSE_EUV์ processor ๊ธฐ๋ณธ ์คํ์ ์ต๊ทผ 2์ผ lookback ๋ชจ๋์
๋๋ค. ์คํ์ผ ๊ธฐ์ค ์ค๋ ํฌํจ ์ต๊ทผ 2์ผ์ ๋ ์ง๋ณ๋ก ๊ฒ์ฌํ๊ณ , ๋จผ์ ์์ฒ raw์ parsed์ ์ ์ฒด ๊ฑด์๋ฅผ ๋น๊ตํฉ๋๋ค. ๋ ๋ฐฐ์น ๋ชจ๋ ์ ์ฒด ๊ฑด์๊ฐ ๋ค๋ฅด๊ณ parsed ๊ฑด์๊ฐ 0๋ณด๋ค ํด ๋๋ง ์์ฒ์์ (eq_name, code, code_occur_time)์ด ๊ฐ์ ํ์ ์ค๋ณต ์ ๊ฑฐํ ๊ฑด์๋ฅผ ํ ๋ฒ ๋ ๊ณ์ฐํฉ๋๋ค. ์ด ๊ฑด์๊ฐ parsed ๊ฑด์์ ๊ฐ์ผ๋ฉด ์ค๋ณต์ผ๋ก ์ธํ ์ฐจ์ด์ด๋ฏ๋ก ์คํตํ๊ณ , ์ฌ์ ํ ๋ค๋ฅด๊ฑฐ๋ parsed ๊ฑด์๊ฐ 0์ด๋ฉด ํด๋น ๋ ์ง parsed ํํฐ์
์ TRUNCATEํ ๋ค ์์ฒ raw๋ฅผ ์ฒ์๋ถํฐ ๋ค์ ํ์ฑํด ์ ์ฌํฉ๋๋ค. ER_DOSE_EUV_TARGET_DATE๋ฅผ ๋ช
์ํ๋ฉด ํด๋น ๋ ์ง 1์ผ๋ง ๊ฐ์ ๋ฐฉ์์ผ๋ก ๊ฒ์ฌํ๊ณ , ER_DOSE_START_TIME/ER_DOSE_END_TIME๋ฅผ ๋ช
์ํ๋ฉด count ๋น๊ต ์์ด ์ง์ ํ ์๊ฐ ๋ฒ์๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. EUV source count๋ root cause ํ์ฑ ๋์์ธ contents๋ง ์ธ์ด parsed count์ ๋น๊ตํฉ๋๋ค.
DW ๋ก๊ทธ์์ exposure_handle์ด ๊ฐ์ ์ค๋น์ ์ด์ ๊ฐ๋ณด๋ค 1000 ์ด์ ์ปค์ง๋ฉด ํ
์คํธ์ท์ฑ row๋ก ๋ณด๊ณ ์ ์ฅ์ ํ๋ use_yn='N'์ผ๋ก ํ์ํฉ๋๋ค. ์ผ๋ฐ ๋ถ์์์๋ use_yn='Y' ์กฐ๊ฑด์ ์ฌ์ฉํ๋ฉด ๋๊ณ , row ์์ฒด๋ ์ ์ฅ๋๋ฏ๋ก raw count์ parsed count ๋น๊ต๊ฐ ๊ณ์ ์ด๊ธ๋๋ ๋ฌธ์ ๋ฅผ ํผํ ์ ์์ต๋๋ค.
ER_DOSE_EUV๋ mbeat.er_data_raw_euv ๊ธฐ๋ฐ root cause ๊ฒฐ๊ณผ์ฉ ์คํ์
๋๋ค. ๋์ ๊ฒฐ๊ณผ๋ prism_common.er_dose_euv_parsed์ ์ ์ฅํ๋ฉฐ, er_line, belong, type์ ์ ์ฅํ์ง ์์ต๋๋ค. contents์์ dose_error_detected_in_file, exposure_id, time, root_cause์ ๊ฐ์ข
EUV metric ์ปฌ๋ผ์ ํ์ฑํด ์ ์ฌํฉ๋๋ค. ์ปฌ๋ผ๋ช
์ ์๋ฌธ์ snake_case ๊ธฐ์ค์ผ๋ก ๊ณต๋ฐฑ, ., -, <, =๋ฅผ _๋ก ์นํํ๋ฉฐ, ํ์ ์ปฌ๋ผ์ root_cause_code๋ง ์ ์ฅํฉ๋๋ค. ํ์ฑ ๋ฐ ์ ์ฌ๊ฐ ์๋ฃ๋๋ฉด prism_common.de_trend_root_cause_daily ์๋จธ๋ฆฌ ํ
์ด๋ธ์ ์ผ๋ณ/์ค๋น๋ณ/์์ธ๋ณ ๋ฐ์ ๋น๋(frequency)๋ฅผ ์๋ UPSERT ํฉ๋๋ค.
์์ธ ์คํค๋ง์ ํ์ฑ ๊ท์น์ ER_DOSE_ERROR.md๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
ftp_batch/
โโโ app/
โ โโโ batch_runner.py
โโโ common/
โ โโโ date_utils.py
โ โโโ path_utils.py
โโโ config/
โ โโโ local_test_settings.py
โโโ infra/
โ โโโ db_manager.py
โ โโโ ftp_scanner.py
โโโ matching/
โ โโโ image_text_matcher.py
โโโ processors/
โโโ rubi_processor.py
โโโ rupi_processor.py
batch_main/
โโโ main.py
airflow_modules/
โโโ ftp_batch_jobs.py
dags/
โโโ ftp_batch_hourly_dag.py
main.py
test.py
init_db.py
local_ftp_server.py
IMAGE_TEXT_MATCHING.md
/RUBI/<YYYYMMDD>์ค์บ- ํ์ผ๋ณ ๋ค์ด๋ก๋
- ํ
์คํธ ํ์ฑ ํ
DataFrame์์ฑ - SQLite ๋ฒํฌ ์ธ์ํธ
- commit ์ฑ๊ณต ์ FTP ์๋ณธ ์ญ์
/RUIP/<YYYYMMDD>์ด๋ฏธ์ง ์ค์บ/RUBI/<YYYYMMDD>ํ ์คํธ ํ๋ณด ์กฐํ- ์ด๋ฏธ์ง ๊ธฐ์ค์ผ๋ก ๊ฐ๊น์ด ํ ์คํธ ๋งค์นญ
- ๋ก์ปฌ PNG ์ค๋น
- ๋ง์ง๋ง์ ์ ๋ก๋ ํ๋ฅผ ์์ฐจ ์ ๋ก๋
์ ๋ + ์ ๋ ฅ์ผ์/RUBI์/RUIP๋ฅผ ๋ชจ๋ ๋จผ์ ๋ค์ด๋ก๋- ํ ์คํธ ํ์ผ์ ์๊ฐ์์ผ๋ก ํ์ฑ
- ํ ์คํธ๋ณด๋ค ๋ฆ์ง ์๊ณ 5๋ถ ์ด๋ด์ธ ๊ฐ์ฅ ๊ฐ๊น์ด ์ด๋ฏธ์ง 1๊ฐ๋ฅผ 1:1 ๋งค์นญ
- ๋งค์นญ ์ด๋ฏธ์ง๊ฐ ์์ผ๋ฉด PNG ์ค๋น ํ ์ ๋ก๋ ํ์ ๋ฑ๋ก
- ๋งค์นญ ์๋ ํ ์คํธ๋ ํ ์คํธ๋ง DB ์ ์ฅ
- ๋ง์ง๋ง ์ ๋ก๋ ๋จ๊ณ์์ ์ฑ๊ณตํ ํญ๋ชฉ๋ง DB finalize ํ ํ ์คํธ/์ด๋ฏธ์ง FTP ์๋ณธ ์ญ์
์์น: /Users/parkjunho/PycharmProjects/PythonStudy/ftp_batch/app/batch_runner.py
RUBI,RUPI,COMBINED์คํ ๋ถ๊ธฐ์ ๋ + ์ ๋ ฅ์ผ๋ ๋ ์ง ์ฒ๋ฆฌCOMBINED์์ ๋ก์ปฌ PNG 3์ผ ๋ณด๊ด cleanup- ์ ๋ก๋ ํ ์ ์ด
์์น: /Users/parkjunho/PycharmProjects/PythonStudy/ftp_batch/infra/ftp_scanner.py
- ๋ ์ง ํด๋ ์ค์บ
- ๋ค์ด๋ก๋/์ ๋ก๋
- ์๊ฒฉ ์กด์ฌ ์ฌ๋ถ์ ํฌ๊ธฐ ๊ฒ์ฆ
- FTP ์๋ณธ ์ญ์
ํ์ฌ scan()์ ๋ ์ง ํด๋ ๋ฐ๋ก ์๋ ํ์ผ๋ง ์กฐํํ๊ณ ์ฌ๊ท ์ค์บ์ ํ์ง ์์ต๋๋ค.
์์น: /Users/parkjunho/PycharmProjects/PythonStudy/ftp_batch/infra/db_manager.py
select(query, params=None, connection=None)bulk_insert_df(table_name, df, connection=None)execute(query, params=None, connection=None)transaction()
์กฐํ๋ pandas.read_sql_query, ์ธ์ํธ๋ DataFrame -> sqlite3.executemany ๊ธฐ๋ฐ ๋ฒํฌ ์ธ์ํธ์
๋๋ค.
์์น: /Users/parkjunho/PycharmProjects/PythonStudy/ftp_batch/processors/rubi_processor.py
- ํ ์คํธ ๋์ฝ๋ฉ
- ๋ผ์ธ ํ์ฑ
rubi_ingest์ฉDataFrame์์ฑ
์์น: /Users/parkjunho/PycharmProjects/PythonStudy/ftp_batch/processors/rupi_processor.py
- TIF -> PNG ๋ณํ
rupi_ingestupsert/finalize- ๋ก์ปฌ PNG ๊ฒฝ๋ก ์์ฑ
์์น: /Users/parkjunho/PycharmProjects/PythonStudy/ftp_batch/matching/image_text_matcher.py
- ํ์ผ๋ช
์์
prefix, timestamp ์ถ์ถ - ํ ์คํธ ๊ธฐ์ค ์ต๊ทผ์ ์ด๋ฏธ์ง ์ ํ
- ์ด๋ฏธ์ง ๊ธฐ์ค ์ต๊ทผ์ ํ ์คํธ ์ ํ
RUIP -> rbi/ruip/.../*.png๊ฒฝ๋ก ๋ณํ
์ด์์ฉ ๊ณตํต ์ง์
์ ์ main.py ์
๋๋ค. ์ค์ ๋ถ๊ธฐ ๋ก์ง์ batch_main/main.py์ ๋๊ณ , ๋ฃจํธ main.py๋ ์์ ์คํ ๋ํผ๋ก ์ ์งํฉ๋๋ค.
BATCH_TARGET ๊ฐ์ ๋ฐ๋ผ RBI ๋ฐฐ์น์ ER Dose ๋ฐฐ์น๋ฅผ ๋ถ๊ธฐํฉ๋๋ค.
๋จผ์ ํ๋ก์ ํธ ๋ฃจํธ๋ก ์ด๋ํฉ๋๋ค.
cd /Users/parkjunho/PycharmProjects/PythonStudyRBI ์คํ:
BATCH_TARGET=RBI \
RBI_INPUT_DATE=2026-05-31 \
RBI_PARSER=COMBINED \
.venv/bin/python main.pyER_DOSE_RAW ์คํ:
ER_DOSE_DB_DSN='postgresql://user:password@host:5432/dbname' \
.venv/bin/python main.py --date 2026-05-31 --parser ER_DOSE_RAW๋๋ er_dose.properties ์ DB ์ฐ๊ฒฐ์ ๋ฃ๊ณ ์คํํ ์ ์์ต๋๋ค.
ER_DOSE_DB_DSN=postgresql://user:password@host:5432/dbnameER_DOSE_EUV๋ ER_DOSE_RAW์ ๋ณ๋ ์คํ์ผ๋ก ๋์ํฉ๋๋ค.
ํ์ ํ๊ฒฝ๋ณ์:
BATCH_TARGET:RBI,ER_DOSE_RAW,ER_DOSE_EUVRBI_INPUT_DATE: RBI ๊ธฐ์ค ๋ ์ง,YYYY-MM-DDER_DOSE_DB_DSN๋๋DATABASE_URL: PostgreSQL DSN- ๋๋ ํ๋ก์ ํธ ๋ฃจํธ
er_dose.propertiesํ์ผ์ER_DOSE_DB_DSN
์ ํ ํ๊ฒฝ๋ณ์:
RBI_PARSER:RUBI,RUPI,COMBINED, ๊ธฐ๋ณธ๊ฐCOMBINEDER_DOSE_RAW_TARGET_DATE: ER Dose raw ๋์ ๋ ์ง,YYYY-MM-DDER_DOSE_EUV_TARGET_DATE: ER Dose EUV ๋์ ๋ ์ง,YYYY-MM-DDER_DOSE_CHUNK_SIZE: ER Dose raw/euv fetch chunk ํฌ๊ธฐER_DOSE_LOOKBACK_DAYS:ER_DOSE_RAW๊ธฐ๋ณธ lookback ์ผ์, ๊ธฐ๋ณธ๊ฐ2INPUT_DATE:RBI_INPUT_DATE๋์ฒด๊ฐER_DOSE_TARGET_DATE: raw ๋ ๊ฑฐ์ ๋์ ๋ ์ง ์ด๋ฆTARGET_DATE:ER_DOSE_TARGET_DATE๋ ๊ฑฐ์ ๋์ฒด๊ฐSTART_TIME:ER_DOSE_START_TIME๋์ฒด๊ฐEND_TIME:ER_DOSE_END_TIME๋์ฒด๊ฐER_DOSE_START_TIME,ER_DOSE_END_TIME: ๊ธฐ์กด ์๊ฐ ๋ฒ์ ์ง์ ์ง์ ๋ฐฉ์๋ ๊ณ์ ์ง์. ๋ ๊ฐ์ ๋ฐ๋์ ํจ๊ป ์ง์ ํด์ผ ํจ
๋ก์ปฌ ํจํค์ง ์ค์น:
mkdir -p .vendor
pip3 install --target .vendor SQLAlchemy psycopg2-binarysitecustomize.py ๊ฐ .vendor ๋ฅผ ์๋์ผ๋ก sys.path ์ ์ถ๊ฐํ๋ฏ๋ก ๋ณ๋ PYTHONPATH ์ค์ ์์ด ์คํํ ์ ์์ต๋๋ค.
์คํ ๊ท์น:
main.py --date <YYYY-MM-DD> --parser RUBI|RUPI|COMBINED์ด๋ฉด FTP ๊ธฐ๋ฐ RBI ๋ฐฐ์น๋ฅผ ์คํํฉ๋๋ค.main.py --date <YYYY-MM-DD> --parser ER_DOSE_RAW์ด๋ฉด ํด๋น ํ๋ฃจ์ ER RAW ๋ก๊ทธ ํ์ฑ ๋ฐฐ์น๋ฅผ ์คํํฉ๋๋ค.main.py --date <YYYY-MM-DD> --parser ER_DOSE_EUV์ด๋ฉด EUV root cause ํ์ฑ ๋ฐฐ์น๋ฅผ ์คํํฉ๋๋ค.- ๋ด๋ถ์ ์ผ๋ก
ER_DOSE_RAW๋ER_DOSE_RAW_TARGET_DATE,ER_DOSE_EUV๋ER_DOSE_EUV_TARGET_DATE๋ฅผ ์ฌ์ฉํฉ๋๋ค. - raw/euv processor ๋ชจ๋ ๋์ ๋ ์ง ๊ธฐ์ค์ผ๋ก ํ๋ฃจ ๋ฒ์๋ฅผ ๊ณ์ฐํฉ๋๋ค.
BATCH_TARGET=ER_DOSE_RAW๊ฐ ํ์ฌ raw ๋ฐฐ์น์ ๊ธฐ๋ณธ ์ด๋ฆ์ ๋๋ค. ๋ ๊ฑฐ์ER_DOSE๋ ๊ณ์ ์ง์ํฉ๋๋ค.BATCH_TARGET=ER_DOSE_RAW๋๋BATCH_TARGET=ER_DOSE_EUV๋ฅผ ํ๊ฒฝ๋ณ์๋ง์ผ๋ก ์คํํ๊ณ ๋ ์ง ์ธ์๋ฅผ ์ฃผ์ง ์์ผ๋ฉด ์ต๊ทผ 2์ผ lookback + ๋ ์ง๋ณ count ๋น๊ต ๊ธฐ๋ฐ ์ฌ์ ์ฌ ์ ๋ต์ด ์ ์ฉ๋ฉ๋๋ค. ๋ ๋ฐฐ์น ๋ชจ๋ ์ ์ฒด count๊ฐ ๋ค๋ฅผ ๋๋ง ๊ณ ์ ์ด๋ฒคํธ count๋ฅผ ์ถ๊ฐ๋ก ๋น๊ตํฉ๋๋ค.- ์ธ์ ์์ด
main.py๋ฅผ ์คํํ๋ฉด ๊ธฐ์กด๊ณผ ๋์ผํ๊ฒ ํ๊ฒฝ๋ณ์ ๊ธฐ๋ฐ ์คํ์ ๋๋ค.
/Users/parkjunho/PycharmProjects/PythonStudy/.venv/bin/python \
/Users/parkjunho/PycharmProjects/PythonStudy/init_db.py/Users/parkjunho/PycharmProjects/PythonStudy/.venv/bin/python \
/Users/parkjunho/PycharmProjects/PythonStudy/local_ftp_server.pyRUBI
/Users/parkjunho/PycharmProjects/PythonStudy/.venv/bin/python \
/Users/parkjunho/PycharmProjects/PythonStudy/test.py \
--input-date 2026-04-11 \
--parser RUBIRUPI
/Users/parkjunho/PycharmProjects/PythonStudy/.venv/bin/python \
/Users/parkjunho/PycharmProjects/PythonStudy/test.py \
--input-date 2026-04-11 \
--parser RUPICOMBINED
/Users/parkjunho/PycharmProjects/PythonStudy/.venv/bin/python \
/Users/parkjunho/PycharmProjects/PythonStudy/test.py \
--input-date 2026-04-11 \
--parser COMBINEDER_DOSE_RAW
ER_DOSE_DB_DSN='postgresql://user:password@host:5432/dbname' \
/Users/parkjunho/PycharmProjects/PythonStudy/.venv/bin/python \
/Users/parkjunho/PycharmProjects/PythonStudy/main.py \
--date 2026-04-11 \
--parser ER_DOSE_RAWER_DOSE_EUV
ER_DOSE_DB_DSN='postgresql://user:password@host:5432/dbname' \
/Users/parkjunho/PycharmProjects/PythonStudy/.venv/bin/python \
/Users/parkjunho/PycharmProjects/PythonStudy/main.py \
--date 2026-04-11 \
--parser ER_DOSE_EUV์ง์ ER Dose ์คํ ์คํฌ๋ฆฝํธ๋ฅผ ์ฌ์ฉํ ์๋ ์์ต๋๋ค.
ER_DOSE_RAW๋ฅผ ๋ ์ง ์์ด ์คํํ๋ฉด ์ต๊ทผ 2์ผ lookback ๋ชจ๋๋ก ๋์ํฉ๋๋ค.
python3 -m er_dose.run_er_dose_batch \
--parser ER_DOSE_RAW \
--dsn 'postgresql://user:password@host:5432/dbname'python3 -m er_dose.run_er_dose_batch \
--date 2026-04-11 \
--parser ER_DOSE_RAW \
--dsn 'postgresql://user:password@host:5432/dbname'python3 -m er_dose.run_er_dose_batch \
--date 2026-04-11 \
--parser ER_DOSE_EUV \
--dsn 'postgresql://user:password@host:5432/dbname'๊ธฐ์กด ์๊ฐ ๋ฒ์ ์ง์ ์ง์ ๋ฐฉ์๋ ๊ณ์ ์ง์ํฉ๋๋ค.
python3 -m er_dose.run_er_dose_batch \
--start-time 2026-04-11T00:00:00 \
--end-time 2026-04-12T00:00:00 \
--dsn 'postgresql://user:password@host:5432/dbname'- DAG: /Users/parkjunho/PycharmProjects/PythonStudy/dags/ftp_batch_hourly_dag.py
- ๋ํผ: /Users/parkjunho/PycharmProjects/PythonStudy/airflow_modules/ftp_batch_jobs.py
- ์ค์ผ์ค: ๋งค์๊ฐ ์ ๊ฐ
- ๊ธฐ๋ณธ ์คํ ๋ชจ๋:
COMBINED
์์น: /Users/parkjunho/PycharmProjects/PythonStudy/ftp_batch/config/local_test_settings.py
์ฃผ์ ๊ฐ:
CLIENT_FTP_ROOT_PATH = "/RUIP"TEXT_FTP_ROOT_PATH = "/RUBI"SERVER_FTP_ROOT_PATH = "/rbi"LOCAL_WORK_DIRLOCAL_DB_PATHRUPI_SCALE_PERCENT
RUBI๋ DB commit ์ฑ๊ณต ์ ์๋ FTP ์๋ณธ์ ์ญ์ ํ์ง ์์ต๋๋ค.COMBINED์์ ๋งค์นญ๋ ํญ๋ชฉ์ ์ ๋ก๋ ์ฑ๊ณต ํ DB commit, ๊ทธ ๋ค์ FTP ์๋ณธ ์ญ์ ์์๋ก ์ฒ๋ฆฌํฉ๋๋ค.- ๋ก์ปฌ raw
txt/tif๋ scratch ํ์ผ์ด๋ผ ์ฒ๋ฆฌ ํ ์ฆ์ ์ญ์ ํฉ๋๋ค. - ๋ก์ปฌ
png๋ ์ฌ์ ๋ก๋ ์บ์๋ก 3์ผ ์ ์งํ๊ณ , ๋ฐฐ์น ์์ ์ 3์ผ ์ง๋ ํ์ผ๋ง ์ ๋ฆฌํฉ๋๋ค.
commit ์ฑ๊ณต ํ FTP delete ์คํจ์ฌ์๋ ํ๋ ์์ง ์์ต๋๋ค.- DB๋ SQLite ๊ธฐ์ค์ ๋๋ค.
scan()์ ๋ ์ง ํด๋ ๋ฐ๋ก ์๋ ํ์ผ๋ง ์ฝ๊ณ ์ฌ๊ท ์ค์บ์ ์ง์ํ์ง ์์ต๋๋ค.
.env๊ธฐ๋ฐ ์ค์ ๋ก๋ฉON CONFLICT DO NOTHING๊ธฐ๋ฐ ์ค๋ณต ์ฒ๋ฆฌ ์ ์ฑ ๋ณ๊ฒฝ- FTP ์ฌ๊ท ๋๋ ํ ๋ฆฌ ์ญ์ ์ ํธ
00:00 ~ 01:59์ ๋ ๋ง ์ฒ๋ฆฌํ๋ ์๊ฐ ๋ถ๊ธฐ- PostgreSQL ์ ํ
์์ธํ ๋งค์นญ ๊ท์น์ /Users/parkjunho/PycharmProjects/PythonStudy/IMAGE_TEXT_MATCHING.md ๋ฅผ ์ฐธ๊ณ ํ๋ฉด ๋ฉ๋๋ค.