์์ ์๋ํ ์ธ๋ณด์ด์ค/๋ณด๊ณ ์ ์์ฑ Flask ๊ธฐ๋ฐ ์น ์ฑ ๋ง๋ค๊ธฐ
์์ ์๋ํ Flask ๊ธฐ๋ฐ ์น ์ฑ์ผ๋ก ์์ ๋ฐ์ดํฐ๋ฅผ ์ฆ์ ์ธ๋ณด์ด์ค์ ์๋ ๋ณด๊ณ ์๋ก ๋ณํํ์ธ์. ์ ๋ก๋, ํธ์ง, ๋ฏธ๋ฆฌ๋ณด๊ธฐ, PDF ์ถ๋ ฅ๊น์ง ๊ฐํธํ๊ฒ ์ฒ๋ฆฌํฉ๋๋ค.
์์ ์๋ํ ์น ์ฑ์ ์๊ฐ ๋ฐ ํ์์ฑ
๋์งํธ ์ํฌํ๋ก์ฐ์์ ์์ (Excel)์ ์ฌ์ ํ ๋ฐ์ดํฐ ๊ด๋ฆฌ์ ํต์ฌ ๋๊ตฌ์ ๋๋ค. ๊ทธ๋ฌ๋ ๋ฐ์ดํฐ๋ฅผ ์ ํํ๋ ๋ณด๊ณ ์, ์ธ๋ณด์ด์ค, ๊ณ์ฝ์ ๋ฑ ์๊ฐ์ ๋ฌธ์๋ก ๋ณํํ๋ ๊ณผ์ ์ ๋ฐ๋ณต์ ์ด๊ณ ์๊ฐ์ด ๋ง์ด ์์๋ฉ๋๋ค. ๋ํ ์๋ ๋ณต์ฌ/๋ถ์ฌ๋ฃ๊ธฐ ๊ณผ์ ์ ์ค๋ฅ ๋ฐ์ ์ํ ๋ํ ๋์ต๋๋ค. ์ด๋ ํ์ํ ๊ฒ์ ์๋ํ ๋ฐฉ๋ฒ์ ๋๋ค.
์๋ ์ฝ๋๋ ๋ฐ๋ก ์ด ์ง๋ฃจํ๊ณ ๋นํจ์จ์ ์ธ ๊ฐ๊ทน์ ๋ฉ์ฐ๋ ํด๋ฒ์ด ๋ ์ ์์ต๋๋ค. ํ์ด์ฌ์ ํ์ฉํด์ Flask, Pandas,๋ผ๋ ์กฐํฉ์ ํ์ฉํ์ฌ, ์์ ํ์ผ์ ์ ๋ก๋ํ๋ ๊ฒ๋ง์ผ๋ก ํ์คํ๋ ์น ๊ธฐ๋ฐ ๋ฌธ์๋ฅผ ์ฆ์ ์์ฑ, ํธ์ง, ์ถ๋ ฅ(PDF)๊น์ง ๊ฐ๋ฅํ๊ฒ ๋ง๋๋ ๊ฒฝ๋ ์ํฐํ๋ผ์ด์ฆ ์๋ํ ๋ฐฉ๋ฒ์ ๋๋ค.
๋ณธ ๊ธ์์๋ ์ด ์ฝ๋์ ๊ธฐ์ ์ ๊ตฌ์กฐ, ๊ตฌํ ์๋ฆฌ, ๋น์ฆ๋์ค์ ๊ฐ์น๋ฅผ ์์๋ณด๊ณ ๋ค๋ฃจ์ด ๋ณด๊ฒ ์ต๋๋ค.
์๋ํ ์์ ์๋ ์์ ๋ณํ์ ์๋ฆฌ
์ด ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์ ์์์ ์๋์ผ๋ก ์์ฑํ๋ ํต์ฌ ๋ฐฉ๋ฒ์ Python์ ์ค์ฌ์ผ๋ก ํ ์ธ ๊ฐ์ง ์ฃผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํ์ฉํ๋ ๊ฒ์ ๋๋ค.
1. ์น ํ๋ ์์ํฌ: Flask (๋ง์ดํฌ๋ก ํ๋ ์์ํฌ ํ์ฉ)
Flask๋ Django์ ๋ฌ๋ฆฌ ํ์์ ์ธ ๊ธฐ๋ฅ๋ง ์ ๊ณตํ๋ ๋ง์ดํฌ๋ก ์น ํ๋ ์์ํฌ(Micro Web Framework)์ ๋๋ค. Flask๋ฅผ ์ ํํ ์ด์ ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- ๊ฒฝ๋์ฑ ๋ฐ ์๋: ์ธ๋ณด์ด์ค ์์ฑ ์ฑ์ฒ๋ผ ํน์ ๋ชฉ์ ์ ์ํ ์๊ท๋ชจ ํ๋ก์ ํธ์ ๊ฐ์ฅ ์ ํฉํ๋ฉฐ, ๋ถํ์ํ ๊ธฐ๋ฅ ์ค๋ฒํค๋๊ฐ ์์ด ์คํ ์๋๊ฐ ๋น ๋ฆ ๋๋ค.
- ์ ์ฐ์ฑ: ๊ฐ๋ฐ์๊ฐ ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(Pandas, Openpyxl ๋ฑ)๋ฅผ ์์ ๋กญ๊ฒ ํตํฉํ ์ ์์ต๋๋ค.
- ๋ชจ๋์ฑ: ๋ผ์ฐํธ(@app.route), ํ ํ๋ฆฟ(render_template), ์ธ์ ๊ด๋ฆฌ ๋ฑ ํต์ฌ ๊ธฐ๋ฅ์ด ๋ช ํํ๊ฒ ๋ถ๋ฆฌ๋์ด ์์ด ์ ์ง๋ณด์๊ฐ ์ฉ์ดํฉ๋๋ค.
2. ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์ง: Pandas (์์ ์ฒ๋ฆฌ ๋ฐฉ๋ฒ)
Pandas๋ ํ์ด์ฌ์์ ๋ฐ์ดํฐ ์กฐ์ ๋ฐ ๋ถ์์ ์ํ ์ฌ์ค์์ ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค.
- DataFrame์ ์๋ ฅ: ์์ ํ์ผ์ pd.read_excel(BytesIO(file_data))๋ฅผ ํตํด DataFrame์ด๋ผ๋ 2์ฐจ์ ํ ์ด๋ธ ๊ตฌ์กฐ๋ก ์ฆ์ ๋ณํํฉ๋๋ค. ์ด๋ ๋ฐ์ดํฐ์ ํ๊ณผ ์ด ์ ๊ทผ์ ๋งค์ฐ ์ง๊ด์ ์ด๊ณ ํจ์จ์ ์ผ๋ก ๋ง๋ญ๋๋ค.
- ๋ฐ์ดํฐ ์ ์ฒ๋ฆฌ: ์ฝ๋์์ df.fillna(''), df.astype(str), df.dropna(how='all') ๋ฑ์ ์ฌ์ฉํ์ฌ ์์ ์ ๋น ๊ฐ(NaN), ๋ฐ์ดํฐ ํ์ ๋ถ์ผ์น ๋ฌธ์ ๋ฅผ ์ฌ์ ์ ์ฒ๋ฆฌํจ์ผ๋ก์จ, "Garbage In, Garbage Out"์ ๋ฐฉ์งํ๊ณ ์ถ๋ ฅ ๋ฌธ์์ ํ์ง์ ๋ณด์ฅํฉ๋๋ค.
3. ํ์ผ ์ ์ถ๋ ฅ ๋ฐ ๋ฐฐํฌ: Openpyxl ์ PyInstaller
- openpyxl: Pandas๊ฐ .xlsx ํฌ๋งท์ ์์ ํ์ผ์ ์ฝ๊ณ ์ฐ๋ ๋ฐ ํ์ํ ์์ง์ ๋๋ค. ์ฝ๋๋ ํ์ผ์ ๋ฐ์ด๋๋ฆฌ ํํ๋ก ์ฝ์ด ๋ค์ด๋ฏ๋ก, ์ด ์์กด์ฑ์ด ํ์์ ์ ๋๋ค.
- PyInstaller: ํ์ด์ฌ ํ๊ฒฝ์ด ์๋ ๊ณณ์์ ์คํํ ์ ์๋๋ก ์ฑ ์ ์ฒด๋ฅผ ๋จ์ผ ์คํ ํ์ผ(.exe)๋ก ๋ฌถ์ด์ฃผ๋ ๋๊ตฌ์ ๋๋ค. ์ด๋ ์ํฐํ๋ผ์ด์ฆ ํ๊ฒฝ์์ ๋ฐฐํฌ ๋ฐ ์ฌ์ฉ ํธ์์ฑ์ ์ ๊ณตํฉ๋๋ค
์ปดํ์ผ ๋ช ๋ น์ด
pyinstaller--onefile--nameInvoiceApp--add-data"templates;templates"--add-data"static;static"--collect-allopenpyxlapp.py

์์ ๋ฐ์ดํฐ์ ๋ ผ๋ฆฌ์ ํ๋ฆ ๋ฐ ๋ฌธ์ ๋ณํ ๋ฐฉ๋ฒ
์๋ ์ฝ๋๋ ์์ ๋ฐ์ดํฐ๋ฅผ "๋จ์ํ ์ฝ๋ ๊ฒ"์ ๋์ด, ํ ํ๋ฆฟ์ ๊ตฌ๋์ํค๋ ๋์ ๋ณ์๋ก ํ์ฉํ๋ ๋ฐ ์์ต๋๋ค.
1. ๋ฐ์ดํฐ ์ถ์ถ๊ณผ ์ฝ๋ํ (Code Mapping)
์์ ํ์ผ์ด ์ ๋ก๋๋๋ฉด, ์๋ฒ๋ ํ์ผ์ ์ฝ๊ณ ๋ค์๊ณผ ๊ฐ์ ๋ ผ๋ฆฌ์ ์ถ๋ก ์ ์ํํฉ๋๋ค.
| ์์ ์ด (์ถ์ ) | ์ฉ๋ | Python ๋ณ์ ์ ์ฅ ์์น |
| A์ด (์ธ๋ฑ์ค 0) | ์ฝ๋(Code): INVOICE_NO, SELLER, TOTAL_AMT ๋ฑ ํค ๊ฐ | code_values ๋์ ๋๋ฆฌ์ ํค |
| B์ด (์ธ๋ฑ์ค 1) | ์ค๋ช (Description): ์ฝ๋์ ๋ํ ๋ถ๊ฐ ์ค๋ช | code_values[code]['description'] |
| C์ด (์ธ๋ฑ์ค 2) | ๊ฐ(Value): ํ ํ๋ฆฟ์ ์ฝ์ ๋ ์ค์ ๋ฐ์ดํฐ | code_values[code]['value'] |
- ์ฝ๋๋ XL_ ์ ๋์ฌ๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฌํ ์์ ์ฝ๋๋ฅผ ํ ํ๋ฆฟ ๋ณ์๋ก ํํํ(template_data['XL_' + code] = data.get('value'))ํฉ๋๋ค. ์ด ๋ฐฉ์์ ์์ ์ ํน์ ์ ์ ํ ๋น๋ ๊ฐ์ ๋ฌธ์ ๋ด์ ํน์ ์์น์ ์ ํํ๊ฒ ๋งคํํ ์ ์๊ฒ ํด์ค๋๋ค.
์:
์์ ํ์ผ ๋ด์ฉ
| 20 | Documentary Credit Number | 508434578 |
์์ ํ ํ๋ฆฟ ์ ์ฉ
h2 Invoice:{{XL_20}} /h2
์ถ๋ ฅ
Invoice:508434578
2. ํ ํ๋ฆฟ ์์ง (Jinja2)์ ์ญํ
render_template(TEMPLATE_MAP[template_key], get_template_data()) ํธ์ถ์ Jinja2 ํ ํ๋ฆฟ ์์ง์ ํ์ฑํํฉ๋๋ค.
- ๋์ ๋ด์ฉ ์ฝ์ : Jinja2๋ HTML ํ ํ๋ฆฟ ํ์ผ์์ {{ ๋ณ์๋ช }} ํํ์ ํ๋ ์ด์คํ๋๋ฅผ ์ฐพ์ get_template_data()์์ ์ ๊ณต๋ ์ค์ ๋ฐ์ดํฐ ๊ฐ์ผ๋ก ๋์ฒดํฉ๋๋ค. ์๋ฅผ ๋ค์ด, {{ XL_10 }}์ ์์ ์ ์ฝ๋ 10๋ฒ ์ ์ ์๋ ๊ฐ์ผ๋ก ์ฑ์์ง๋๋ค.
- ๋ฐ๋ณต๋ฌธ ์ฒ๋ฆฌ (์์ดํ ๋ชฉ๋ก): ์์ ์ ํ ๋ฐ์ดํฐ๊ฐ ๋ง์ ๊ฒฝ์ฐ(์: ํ๋ชฉ ๋ชฉ๋ก), Jinja2์ {% for item in items %} ๋ฃจํ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐ์ดํฐํ๋ ์์ ๋ ์ฝ๋๋ฅผ ํ ์ด๋ธ ํ์ผ๋ก ์๋ ์์ฑํฉ๋๋ค. ์ด๋ก์จ ๋ฐ์ดํฐ์ ์๊ณผ ๊ด๊ณ์์ด ๋ฌธ์๋ฅผ ์๋ฒฝํ๊ฒ ๊ตฌ์ฑํ ์ ์์ต๋๋ค.
3. ์ด ๊ธ์ก ๊ณ์ฐ ๋ฐ ํ์ํ
get_template_data ํจ์ ๋ด๋ถ์์ df['Amount'].astype(float).sum():,.2f} EUR๋ฅผ ํตํด ์ด ๊ธ์ก์ ๊ณ์ฐํ๊ณ ์์ต๋๋ค.
- ๊ฐ๋ ฅํ ํ์ํ: ๋จ์ํ ํฉ๊ณ๋ง ๊ตฌํ๋ ๊ฒ์ด ์๋๋ผ, :.2f๋ฅผ ํตํด ์์์ ๋์งธ ์๋ฆฌ๊น์ง ํ์ํ๊ณ , ,๋ฅผ ํตํด ์ฒ ๋จ์ ๊ตฌ๋ถ ๊ธฐํธ๋ฅผ ์ถ๊ฐํ๋ฉฐ, ํตํ ๊ธฐํธ(EUR)๊น์ง ๋ถ์ฌ ๋น์ฆ๋์ค ๋ฌธ์ ํ์ค์ ๋ง๋ ์ต์ข ์ถ๋ ฅ๊ฐ์ ๋ง๋ญ๋๋ค.
๋ฌธ์ ๊ด๋ฆฌ ๋ฐ ์ฌ์ฉ์ ๊ฒฝํ (UX) ์ต์ ํ
์ด ์ฑ์ ๋จ์ํ ๋ณํ์ ๋์ด, ์ค์ ์ ๋ฌด ํ๊ฒฝ์์ ์ฌ์ฉ์๊ฐ ๋ฌธ์๋ฅผ ๊ด๋ฆฌํ๊ณ ํ์ฉํ๋ ๋ฐ ์ค์ ์ ๋ ๊ธฐ๋ฅ๋ค์ ํฌํจํ๊ณ ์์ต๋๋ค.
1. ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ํ ๊ด๋ฆฌ (์ธ์ ๊ณผ ํ์คํ ๋ฆฌ)
์ฝ๋๋ ์ธ์ (Session)์ ์ฌ์ฉํ์ฌ ์ฌ์ฉ์ ์ํ๋ฅผ ์์์ ์ผ๋ก ๊ด๋ฆฌํฉ๋๋ค.
- session['excel_file']: ์ ๋ก๋๋ ์์ ๋ฐ์ดํฐ ํ์ผ๋ช (๋์คํฌ ์ ์ฅ)์ ๊ธฐ์ตํฉ๋๋ค.
- session['current_preview_file']: ํ์ฌ ํ๋ฉด์ ํ์๋๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ HTML ํ์ผ๋ช ์ ๊ธฐ์ตํฉ๋๋ค.
- session['preview_history']: ์ฌ์ฉ์๊ฐ ์ฌ๋ฌ ํ ํ๋ฆฟ์ ๋ก๋ํ๊ฑฐ๋ ์ด์ /๋ค์ ๋ฒํผ์ ๋๋ ์ ๋์ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๊ธฐ๋ก์ ์ ์ฅํฉ๋๋ค.
์ด ํ์คํ ๋ฆฌ ๊ธฐ๋ฅ์ ํตํด ์ฌ์ฉ์๋ ์ฌ๋ฌ ํ ํ๋ฆฟ ๊ฐ์ ์ ํ์ ์์ ๋กญ๊ฒ ๋๋๋ฆฌ๊ฑฐ๋ ์์ผ๋ก ๋์๊ฐ ์ ์์ต๋๋ค.
2. ํธ์ง ๋ด์ฉ ์ ์ง ๋ฐ ์ ์ฅ (save_edited)
๊ฐ์ฅ ์ค์ํ UX ๊ธฐ๋ฅ ์ค ํ๋๋ ํธ์ง ๊ฐ๋ฅ ๋ฏธ๋ฆฌ๋ณด๊ธฐ(ContentEditable)์ ์์ ๋ด์ฉ ์ ์ง ๊ธฐ๋ฅ์ ๋๋ค.
- contenteditable="true": iframe ๋ด๋ถ์ HTML์ ๋ก๋ํ๋ ๋์ , ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ฅผ Div ํ๊ทธ๋ก ๊ฐ์ธ๊ณ ์ด ์์ฑ์ ๋ถ์ฌํ์ฌ ์ฌ์ฉ์๊ฐ ๋ธ๋ผ์ฐ์ ์์ ์ง์ ํ ์คํธ๋ฅผ ์์ ํ ์ ์๊ฒ ํฉ๋๋ค.
- session['edited_file']: ์ฌ์ฉ์๊ฐ '์ ์ฅ' ๋ฒํผ์ ๋๋ฌ ์์ ํ HTML์ด ๋์คํฌ์ ๋ณ๋ ํ์ผ๋ก ์ ์ฅ๋ฉ๋๋ค. ์ดํ ๊ฐ์ ํ ํ๋ฆฟ์ ๋ค์ ๋ก๋ํ ๋, ์ฝ๋๋ ๋ ๋๋ง์ ๋ค์ ํ์ง ์๊ณ ์ด ํธ์ง๋ ํ์ผ์ ๋ถ๋ฌ์ ์์ ๋ด์ฉ์ ์ ์งํฉ๋๋ค.
3. PDF ์ถ๋ ฅ ๋ฐฉ๋ฒ
์ฌ์ฉ์ ์์ฒญ์ ๋ฐ๋ผ printPreview() ํจ์๋ PDF ์ ์ฅ ๊ธฐ๋ฅ์ ๋์ ํ๋๋ก ์์ ๋์์ต๋๋ค.
- ๋ธ๋ผ์ฐ์ ์ธ์ API ํ์ฉ: window.open()์ ํตํด ํ ํ๋ฆฟ HTML์ ์ ์ฐฝ์ ๋ก๋ํ๊ณ , printWindow.print()๋ฅผ ํธ์ถํ์ฌ ๋ธ๋ผ์ฐ์ ์ ๊ธฐ๋ณธ ์ธ์ ๋ํ ์์๋ฅผ ๋์๋๋ค.
- PDF ์ถ๋ ฅ: ์ฌ์ฉ์๋ ์ธ์ ๋์(Destination)์ "PDF๋ก ์ ์ฅ(Save as PDF)"์ผ๋ก ์ ํํจ์ผ๋ก์จ, ๋ธ๋ผ์ฐ์ ์์ง์ด ์ ๊ณตํ๋ CSS ๋ฐ ์ธ์ ์คํ์ผ์ด ์๋ฒฝํ๊ฒ ์ ์ฉ๋ PDF ๋ฌธ์๋ฅผ ์ป์ ์ ์์ต๋๋ค. ์ด๋ ์๋ฒ์์ PDF ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ๋ณํํ๋ ๊ฒ๋ณด๋ค ํจ์ฌ ๋น ๋ฅด๊ณ ์์ ์ ์ด๋ฉฐ, ๋ ๋๋ง ์ ํ๋๊ฐ ๋์ต๋๋ค.
๋น์ฆ๋์ค ๊ฐ์น ๋ฐ ํ์ฅ์ฑ
์ด์ ๊ฐ์ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ ๋จ์ํ ๊ธฐ์ ํ๋ก์ ํธ๋ฅผ ๋์ด, ์ค์๊ธฐ์ (SME) ๋ฐ ๊ฐ์ธ ์ฌ์ ์(Freelancer)์๊ฒ ์ค์ง์ ์ธ ๋น์ฆ๋์ค ํจ์จ์ฑ์ ์ ๊ณตํฉ๋๋ค.
1. ์์ฐ์ฑ ๋ฐ ๋น์ฉ ์ ๊ฐ
- ์๊ฐ๋น ์์ฐ์ฑ ์ฆ๊ฐ (TPO): ๋งค๋ฒ ์๋์ผ๋ก ๋ฌธ์๋ฅผ ์์ฑํ๋ ์๊ฐ์ ์ ์ฝํ์ฌ, ์ง์์ด ํต์ฌ ์ ๋ฌด(๋ถ์, ์์ ๋ฑ)์ ์ง์คํ ์ ์๋๋ก ํฉ๋๋ค.
- ํ ํ๋ฆฟ ์ฌ์ฌ์ฉ: ๋ค์ํ ํ ํ๋ฆฟ ์ต์ (Standard, Report, Memo ๋ฑ 10๊ฐ)์ ์ ๊ณตํ์ฌ, ๋์ผํ ์์ ๋ฐ์ดํฐ๋ฅผ ์ฌ๋ฌ ๋ชฉ์ ์ ๋ฌธ์๋ก ์ฆ์ ์ ํํ ์ ์์ต๋๋ค.
2. ๋ฐ์ดํฐ ๊ฑฐ๋ฒ๋์ค ๋ฐ ์ค๋ฅ ๊ฐ์
- ๋ฐ์ดํฐ ์ถ์ฒ ๋จ์ผํ: ๋ชจ๋ ๋ฌธ์๊ฐ ํ๋์ ์์ ํ์ผ์์ ์์๋๋ฏ๋ก, ๋ฐ์ดํฐ์ ์ผ๊ด์ฑ(Data Consistency)์ด ์ ์ง๋ฉ๋๋ค.
- ์๋ ๊ฒ์ฆ: Pandas๊ฐ ๋ฐ์ดํฐ ํ์ ์ค๋ฅ๋ฅผ ์๋์ผ๋ก ์ฒ๋ฆฌํ๊ณ , ์ดํฉ ๊ณ์ฐ์ ์ ํํ ์ํํจ์ผ๋ก์จ ์๋ ๊ณ์ฐ๊ณผ ์์ ์ค๋ฅ๋ฅผ 0%๋ก ์ค์ผ ์ ์์ต๋๋ค.
3. ํ์ฅ ๊ฐ๋ฅ์ฑ (Microservices ๊ตฌ์กฐ)
Flask ์ฑ์ ๋ง์ดํฌ๋ก์๋น์ค(Microservices) ์ํคํ ์ฒ๋ก ํ์ฅํ๊ธฐ ์ฉ์ดํฉ๋๋ค.
- API ๋ถ๋ฆฌ: ํ์ฌ์ /upload, /load_template ๋ผ์ฐํธ๋ฅผ RESTful API๋ก ๋ถ๋ฆฌํ์ฌ ๋ค๋ฅธ ์์คํ (์: CRM, ERP)๊ณผ ํตํฉํ ์ ์์ต๋๋ค.
- ๋น๋๊ธฐ ์ฒ๋ฆฌ: ๋์ฉ๋ ์์ ํ์ผ ์ฒ๋ฆฌ ์, upload ๊ธฐ๋ฅ์ Celery์ ๊ฐ์ ๋น๋๊ธฐ ์์ ํ์ ๋๊ฒจ ์ฌ์ฉ์ ๊ฒฝํ์ ๊ฐ์ ํ ์ ์์ต๋๋ค.
ํ๋ก๊ทธ๋จ ์ฌ์ฉ ๋ฐฉ๋ฒ
ํ๋ก์ ํธ ๋๋ ํฐ๋ฆฌ ๊ตฌ์กฐ(Project Directory Structure)project/
โโโapp.py
โโโstatic/
โโโโimg/
โโโโsin.jpg
โโโtemplates/
โโโinvoice.html
ํ์ด์ฌ ํ์ผ index. html ํ์ผ
HTML ๋ฐ์ดํฐ ๋งคํ ํ ์ด๋ธ
| Code | Variable | Description | Template Call |
|---|---|---|---|
| 40A | XL_40A | Form of Documentary Credit | {{ XL_40A }} |
| 20 | XL_20 | Documentary Credit Number | {{ XL_20 }} |
| 31C | XL_31C | Date of Issue | {{ XL_31C }} |
| 40E | XL_40E | Applicable Rules | {{ XL_40E }} |
| 31D | XL_31D | Date and Place of Expiry | {{ XL_31D }} |
| 50 | XL_50 | Applicant | {{ XL_50 }} |
| 59 | XL_59 | Beneficiary | {{ XL_59 }} |
| 32B | XL_32B | Currency, Amount | {{ XL_32B }} |
| 39A | XL_39A | Tolerance | {{ XL_39A }} |
| 41a | XL_41a | Available With | {{ XL_41a }} |
| 42P | XL_42P | Negotiation Details | {{ XL_42P }} |
| 43P | XL_43P | Partial Shipments | {{ XL_43P }} |
| 43T | XL_43T | Transhipment | {{ XL_43T }} |
| 44E | XL_44E | Port of Loading | {{ XL_44E }} |
| 44F | XL_44F | Port of Discharge | {{ XL_44F }} |
| 44C | XL_44C | Latest Shipment Date | {{ XL_44C }} |
| 45A | XL_45A | Goods Description | {{ XL_45A }} |
| 46A | XL_46A | Documents Required | {{ XL_46A }} |
| 47A | XL_47A | Additional Conditions | {{ XL_47A }} |
| 49G | XL_49G | Special Payment Conditions | {{ XL_49G }} |
| 71D | XL_71D | Charges | {{ XL_71D }} |
| 48 | XL_48 | Period for Presentation | {{ XL_48 }} |
| 49 | XL_49 | Confirmation Instructions | {{ XL_49 }} |
| 78 | XL_78 | Instructions to Bank | {{ XL_78 }} |
| 72Z | XL_72Z | Sender to Receiver Info | {{ XL_72Z }} |
ํ์ด์ฌ ๊ธฐ๋ฐ ์๋ํ์ ๊ฐ์น
์ต๊ทผ Python์ ์ํ๊ณ๋ ๋จ์ํ ์คํฌ๋ฆฝํ ์ ๋์ด, ์ค์ ๋น์ฆ๋์ค ๋ฌธ์ ํด๊ฒฐ์ ์ํ ๋ ๋ฆฝ์ ์ธ ์ํํธ์จ์ด ์๋ฃจ์ ์ผ๋ก ๋ฐ์ ํ์์ ๋ณด์ฌ์ค๋๋ค.
์ด Flask ์ธ๋ณด์ด์ค ์ฑ์ ์์ ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ํจ์จ์ฑ, ๋ฌธ์ ์์ฑ์ ์ ํ์ฑ, ๊ทธ๋ฆฌ๊ณ ๋ฐฐํฌ์ ํธ๋ฆฌ์ฑ์ ๊ฒฐํฉํ์ฌ ๊ธฐ์ ๋ฐ ๊ฐ์ธ์ ๋ฌธ์ ์์ ์ ๊ฐ์ ํฉ๋๋ค. ํนํ PyInstaller๋ฅผ ํตํ ๋จ์ผ ํ์ผ ๋ฐฐํฌ ๋ฅ๋ ฅ์ IT ์ง์์ด ๋ถ์กฑํ ์ฌ์ฉ์์๊ฒ๋ ์ ๊ทผ์ฑ์ ๋์ฌ, ์๋ํ ๊ธฐ์ ์ ๋ณดํธํ๋ฅผ ์ด๋ ์ ์์ต๋๋ค.
์์ ์๋ํ ์น ์ฑ์ ์ด๋ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ๋๋์?
์ด ์น ์ฑ์ Python ๊ธฐ๋ฐ์ผ๋ก Flask, Pandas, Openpyxl, Jinja2 ๋ฑ์ ํ์ฉํฉ๋๋ค. Flask๋ ๊ฒฝ๋ ๋ง์ดํฌ๋ก ํ๋ ์์ํฌ๋ก ์น ์๋ฒ์ ๋ผ์ฐํ ์ ๋ด๋นํ๊ณ , Pandas๋ ์์ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฝ๊ณ ์ฒ๋ฆฌํ๋ฉฐ, Openpyxl์ ์์ ํ์ผ ์ ์ถ๋ ฅ์ ์ง์ํ๊ณ , Jinja2๋ HTML ํ ํ๋ฆฟ์ ๋ฐ์ดํฐ๋ฅผ ๋์ ์ผ๋ก ์ฝ์ ํ๋ ์ญํ ์ ํฉ๋๋ค.
์์ ๋ฐ์ดํฐ๋ฅผ ์น ๋ฌธ์๋ก ๋ณํํ๋ ๊ณผ์ ์ ์ด๋ป๊ฒ ์ด๋ฃจ์ด์ง๋์?
์ ๋ก๋๋ ์์ ํ์ผ์ Pandas DataFrame์ผ๋ก ๋ณํ๋์ด ๊ฐ ์ด๊ณผ ํ์ด Python ๋ณ์์ ๋งคํ๋ฉ๋๋ค. ์ฝ๋์ ๊ฐ, ์ค๋ช ๋ฑ์ ๋์ ๋๋ฆฌ ๊ตฌ์กฐ๋ก ๊ด๋ฆฌ๋๋ฉฐ, Jinja2 ํ ํ๋ฆฟ ์์ง์ ํตํด HTML ๋ฌธ์ ๋ด {{ ๋ณ์ }} ์์น์ ์ค์ ๋ฐ์ดํฐ๊ฐ ์ฝ์ ๋ฉ๋๋ค. ๋ฐ๋ณต๋๋ ๋ชฉ๋ก์ {% for %} ๋ฃจํ๋ฅผ ํตํด ์๋์ผ๋ก ํ ์ด๋ธ ํ์ผ๋ก ์์ฑ๋๋ฉฐ, ์ด ๊ธ์ก ๊ณ์ฐ๊ณผ ํตํ ํ์ํ๊น์ง ์๋ ์ฒ๋ฆฌ๋ฉ๋๋ค.
์ฌ์ฉ์๊ฐ ์์ ํ ๋ด์ฉ์ด๋ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ํ๋ ์ด๋ป๊ฒ ๊ด๋ฆฌ๋๋์?
์ฑ์ ์ธ์ (Session)์ ์ฌ์ฉํ์ฌ ์ ๋ก๋๋ ์์ ํ์ผ, ํ์ฌ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ์ผ, ์ด์ /๋ค์ ํ์คํ ๋ฆฌ ๋ฑ์ ๊ด๋ฆฌํฉ๋๋ค. contenteditable ์์ฑ์ ํ์ฉํ์ฌ ๋ธ๋ผ์ฐ์ ์์ ์ง์ ์์ ํ ์ ์๊ณ , '์ ์ฅ' ๋ฒํผ์ ๋๋ฅด๋ฉด ์์ ๋ HTML์ด ๋ณ๋ ํ์ผ๋ก ์ ์ฅ๋์ด ์ฌ๋ก๋ ์ ํธ์ง ๋ด์ฉ์ด ์ ์ง๋ฉ๋๋ค.
PDF ์ถ๋ ฅ์ ์ด๋ป๊ฒ ๊ตฌํ๋๋์?
์ฌ์ฉ์๊ฐ ๋ธ๋ผ์ฐ์ ์์ '์ธ์' ๊ธฐ๋ฅ์ ํธ์ถํ๋ฉด, ์ ์ฐฝ์ HTML ํ ํ๋ฆฟ์ ๋ก๋ํ๊ณ printWindow.print()๋ก ๋ธ๋ผ์ฐ์ ์ธ์ ๋ํ์์๋ฅผ ์คํํฉ๋๋ค. ์ฌ์ฉ์๊ฐ 'PDF๋ก ์ ์ฅ'์ ์ ํํ๋ฉด CSS ์คํ์ผ์ด ์ ์ฉ๋ ๊ณ ํ์ง PDF ๋ฌธ์๋ฅผ ์ฆ์ ์ป์ ์ ์์ผ๋ฉฐ, ์๋ฒ์์ PDF ๋ณํ์ ์ฒ๋ฆฌํ ํ์๊ฐ ์์ด ๋น ๋ฅด๊ณ ์์ ์ ์ ๋๋ค.
์ด ์๋ํ ์ฑ์ ๋น์ฆ๋์ค์ ์ฅ์ ์ ๋ฌด์์ธ๊ฐ์?
์ค์๊ธฐ์ ๊ณผ ๊ฐ์ธ ์ฌ์ ์๋ ๋ฌธ์ ์์ฑ ์๊ฐ์ ํฌ๊ฒ ์ ์ฝํ ์ ์์ผ๋ฉฐ, ๋ฐ์ดํฐ ์ผ๊ด์ฑ๊ณผ ์ ํ์ฑ์ด ์ ์ง๋ฉ๋๋ค. ํ ํ๋ฆฟ ์ฌ์ฌ์ฉ์ด ๊ฐ๋ฅํ๊ณ , ์ค๋ฅ ๋ฐ์๋ฅ ์ด ๋ฎ์ ๋น์ฉ๊ณผ ์ธ์ ์์์ ์ ๊ฐํฉ๋๋ค. ๋ํ Flask ๊ธฐ๋ฐ์ ๋ง์ดํฌ๋ก์๋น์ค ๊ตฌ์กฐ๋ก ํ์ฅ ๊ฐ๋ฅํ๋ฉฐ, ๋ค๋ฅธ ์์คํ ๊ณผ์ ์ฐ๋๋ ์ฉ์ดํฉ๋๋ค.
https://everydayhub.tistory.com/1150
https://everydayhub.tistory.com/1154