5.5 KB ยท ์ˆ˜์ • 2026-06-10 01:39
๋ชฉ์ฐจ

๐Ÿ—‚ ์ƒ์„ธ ๋‚ด์—ญ

์ฃผ์ œ๋ณ„ ์ƒ์„ธ ๋‚ด์šฉ. ๋ชฉ์ฐจ(์ฃผ์ œ ์ƒ‰์ธ)์˜ ๋ฒˆํ˜ธ์™€ ๋Œ€์‘. ํ™•์ •/์ง„ํ–‰์ค‘/๋ฏธ๊ฒฐ์„ ๊ตฌ๋ถ„ํ•œ๋‹ค.

A. ์ธํ”„๋ผ ยท ํ™˜๊ฒฝ

ํ™˜๊ฒฝ ํฌํŠธ ์•ฑ ๋ธŒ๋žœ์น˜ ๋„๋ฉ”์ธ RDS
์šด์˜ 8000 pfs deploy-live pfs.poin.co.kr poin-dbinstance
ํ…Œ์ŠคํŠธ 8001 pfs-test master pfs-test.poin.co.kr poin-dbinstance-test
- EC2 i-03225ba8bc12a929e / EIP 13.209.147.168 / SG sg-00426f1b66795f5f9 / DB pfs user admin.
- .env: /home/ubuntu/env/pfs-{live,test}.env. ์šด์˜ service pfs-live.uwsgi.service.
- nginx ์„ค์ •์€ git ์™ธ ์„œ๋ฒ„ํŒŒ์ผ โ†’ reload๋กœ ์ฆ‰์‹œ ๋ฐ˜์˜(deploy ๋ถˆํ•„์š”).
๋ฐฐํฌ ๋ฉ”์ปค๋‹ˆ์ฆ˜ [ํ™•์ •]: push โ†’ GitHub Actions(deploy.yml) โ†’ SSM send-command โ†’ git fetch+reset --hard origin/<branch> + ๋ฐฐํฌ์Šคํฌ๋ฆฝ. master๋Š” pfs-test ๋””๋ ‰ํ„ฐ๋ฆฌ, deploy-live๋Š” pfs ๋””๋ ‰ํ„ฐ๋ฆฌ. ์šด์˜ ๋ฐฐํฌ์Šคํฌ๋ฆฝ์€ systemctl restart pfs-live.uwsgi.service(๊ณผ๊ฑฐ pgrep+kill-HUP ์ค‘๋ณต์ธ์Šคํ„ด์Šค ๋ฒ„๊ทธ ์ˆ˜์ •๋จ).
## B. ์ž‘์—… ์ฒด๊ณ„
3๋‹จ๊ณ„ ์‹œ์Šคํ…œ [ํ™•์ •]
- โ‘  ์ง„๋‹จ โ€” ์ฑ„ํ‹ฐ๊ฐ€ ์›์ธ์„ ์ฝ”๋“œ/์บ์‹œ/๋ฐฐํฌ/DB ์ค‘ ์–ด๋””์ธ์ง€ ํ™•์ •. ํ•„์š”์‹œ MCP ์ฆ‰์„ ํ™•์ธ. ๋ถˆํ™•์‹ค์„ฑ 0์œผ๋กœ ๋งŒ๋“  ๋’ค ๋‹ค์Œ ๋‹จ๊ณ„.
- โ‘ก ์œ„์ž„ โ€” ์ •ํ™•ํ•œ ์œ„์น˜+before/after .md ์ž‘์„ฑ โ†’ ์ฝ”๋””์—๊ฒŒ ํฐ ๋ฌถ์Œ ํ•œ ๋ฒˆ์—. ๊ฒ€์ฆ ๋๋‚œ ๋ณ€๊ฒฝ๋งŒ ๋ฌถ์Œ์—(๋ฏธ๊ฒ€์ฆ ์ถ”์ธก ๊ธˆ์ง€).
- โ‘ข ๋ถ„๋ฆฌ โ€” ๋Œ€๋Ÿ‰์‚ญ์ œยท์šด์˜๋ฐฐํฌยทDB๋ณ€๊ฒฝยท๊ถŒํ•œ๋ณ€๊ฒฝ์€ ๋ฌถ์Œ์—์„œ ๋นผ์„œ ๋ณ„๋„ ์Šน์ธ.
์ฑ„ํ‹ฐ MCP ์ง์ ‘ vs ์ฝ”๋”” ์œ„์ž„ [ํ™•์ •] โ€” ์ฑ„ํ‹ฐ ์ง์ ‘(MCP)์€ ์ฆ์ƒ๋ณ„๋กœ ์™„ํ™”: ์ง„๋‹จยท๋‹จ๊ฑดํ™•์ธ์€ ์ฑ„ํ‹ฐ, ๋Œ€๋Ÿ‰๋ฉ€ํ‹ฐํŒŒ์ผ ์ˆ˜์ •์€ ์ฝ”๋””. ํฐ ๋ฌถ์Œ์ผ์ˆ˜๋ก ํšจ์œจโ†‘ ํ†ต์ œ๋ ฅโ†“ โ†’ ๊ฒ€์ฆ์œผ๋กœ ์ƒ์‡„. (MCP ์“ฐ๊ธฐ ์ž‘์—…์€ ์ด๋ฒˆ ์„ธ์…˜์—์„œ ์—ฌ๋Ÿฌ ์ฐจ๋ก€ ํƒ€์ž„์•„์›ƒ โ€” ๋Œ€๋Ÿ‰ ํŽธ์ง‘์€ ์ฝ”๋”” ์˜์—ญ).
## C. estimate v2
QA #1~5 [์ปค๋ฐ‹ํ™•์ธ] (commit 5ee6663 ๋“ฑ) โ€” ํ’ˆ๋ชฉ์œ ํ˜•/๋น„๊ณ /๋‹จ๊ฐ€ ํ•ญ์ƒ ์ž…๋ ฅ ํ™œ์„ฑํ™”(_isNew ์กฐ๊ฑด ์ œ๊ฑฐ), cell-name resize:none/overflow:hidden, size-summary contenteditable ๊ณ ์ •.
QA #6~9 [์ปค๋ฐ‹ํ™•์ธ] (commit 7be87f5) โ€” cat-sel focus/click ์‹œ keyword='' ๊ฐ•์ œ๋กœ ์ „์ฒด๋ชฉ๋ก, ๊ธฐ๋ณธ ๋งˆ์ง„ 15.5โ†’10, menu_catalog ๋ฉ”๋‰ด๋ช… ๋ณ€๊ฒฝ, company.margin_rate ์ปด๋Ÿผ ์ถ”๊ฐ€.
์ „์ฒด๋งˆ์ง„ ์ž๋™๋ฐ˜์˜ [์ปค๋ฐ‹ํ™•์ธ] (commit f6126d3) โ€” site-search SQL์— company_no/company_member_no/company_margin_rate ์ถ”๊ฐ€. pickSite์—์„œ ์„ ํƒ ์—…์ฒด margin_rate๋ฅผ ์ „์ฒด๋งˆ์ง„ ์ž๋™ ๋ฐ˜์˜(์—†์œผ๋ฉด 10), ์ž๋™/์ˆ˜๋™ ๋ฐฐ์ง€. ์‚ฌ์šฉ์ž ์ˆ˜์ • ์‹œ ์ˆ˜๋™ ์ „ํ™˜. ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์‹œ ์ €์žฅ๊ฐ’=์ˆ˜๋™.
## D. ์—…์ฒด ๊ด€๋ฆฌ ยท ๊ถŒํ•œ
์—…์ฒด ๊ด€๋ฆฌ ํŽ˜์ด์ง€ [์ปค๋ฐ‹ํ™•์ธ] (commit 424c099) โ€” /admin/company-permission ์ œ๋ชฉยท๋ฉ”๋‰ด๋ช… "์—…์ฒด ๊ด€๋ฆฌ"๋กœ. company_dao.update_company_margin_rate / user_admin_service.set_company_margin_rate / PUT /api/admin/company/<id>/margin-rate. ์ขŒ:์—…์ฒด๋ชฉ๋ก ์šฐ:์ƒ์„ธ+๋งˆ์ง„์œจ+๊ถŒํ•œ๋งคํŠธ๋ฆญ์Šค. company/search๊ฐ€ a.* ๋ฐ˜ํ™˜ โ†’ margin_rate ์ž๋™ ํฌํ•จ.
> ๊ฒ€์ฆ ์ผํ™”(์ค‘์š”): "๋งˆ์ง„์œจ์ด ์ „์ฒด ์ ์šฉ๋œ๋‹ค"๋Š” ์ฆ์ƒ์€ ์ง„๋‹จ ๊ฒฐ๊ณผ ๋ฐฑ์—”๋“œยทDBยท๋ฐฐํฌ ๋ชจ๋‘ ์ •์ƒ, ์‹ค์ œ ์›์ธ์€ ๋ธŒ๋ผ์šฐ์ € ์บ์‹œ์˜€์Œ. DB์—์„œ ๋‹จ๊ฑด UPDATE affected=1 ์ฆ๋ช… ์™„๋ฃŒ.
## E. ์šด์˜ ๋ฐฐํฌ
์šด์˜ RDS ์Šคํ‚ค๋งˆ ์ง„๋‹จ [์ง„๋‹จ์™„๋ฃŒ 2026-05-22] โ€” ์šด์˜์— ๋ถ€์กฑํ•œ ๊ฒƒ์€ ๋‹จ 2๊ฐ€์ง€: company.margin_rate ์ปด๋Ÿผ(์—†์Œ), menu_catalog ๋ฉ”๋‰ด๋ช…(์—…์ฒด ๊ถŒํ•œโ†’์—…์ฒด ๊ด€๋ฆฌ). estimate ์ปด๋Ÿผ(estimate_div ๋“ฑ)ยทPatch#32 ํ…Œ์ด๋ธ”(menu_catalog ๋“ฑ 4๊ฐœ)ยทdispatchยทestimate_detail_subยทESTIMATE_DIV common_code๋Š” ์ด๋ฏธ ์šด์˜ ์กด์žฌ. masterโ†’deploy-live ๋ณ‘ํ•ฉ ์ถฉ๋Œ 0(merge-tree ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ™•์ธ).
์šด์˜ ๋ฐฐํฌ ์ ˆ์ฐจ [์ง€์‹œ๋ฌธ์ž‘์„ฑ] โ€” ์ˆœ์„œ: โ‘  ์šด์˜RDS SQL(margin_rate ์ปด๋Ÿผ append+๋ฉ”๋‰ด๋ช…) โ†’ โ‘ก deploy-live ๋ณ‘ํ•ฉยทpush(์ž๋™๋ฐฐํฌ) โ†’ โ‘ข ๊ฒ€์ฆ. ์ด์œ : ์ปด๋Ÿผ ๋จผ์ € ์ถ”๊ฐ€ํ•ด์•ผ ๊ตฌ์ฝ”๋“œ ๋ฌด์ค‘๋‹จ(๋ฏธ์ฐธ์กฐ). ALTER ๋ฝ ์ฃผ์˜: lock_wait_timeout=10, ์‹คํŒจ์‹œ uWSGI ์ค‘๋‹จ fallback.
## F. ๋””๋ฒ„๊น… ํ•™์Šต
- ์—‘์…€/PDF 0KB [ํ•ด๊ฒฐ de4605a] โ€” Content-Disposition ํ•œ๊ธ€ ํŒŒ์ผ๋ช… โ†’ werkzeug latin1 ์ธ์ฝ”๋”ฉ ์‹คํŒจ โ†’ 200+0bytes. safe_ascii๊ฐ€ c.isalnum()๋งŒ ๋ดค์œผ๋‚˜ Python3๋Š” ํ•œ๊ธ€๋„ True. ์ˆ˜์ •: (ord(c)<128 and c.isalnum()) or c in '-.'. ๊ตํ›ˆ: uWSGI ๋””๋ฒ„๊ทธ๋Š” journalctl -u ๋จผ์ €. 200+0bytes=ํ—ค๋” ์ธ์ฝ”๋”ฉ ์‹คํŒจ ์˜์‹ฌ.
- send_file(BytesIO) ํ˜ธํ™˜์„ฑ [ํ™•์ •] โ€” uWSGI wsgi.file_wrapper ์ถฉ๋Œ. make_response(buf.getvalue())+ํ—ค๋” ์ง์ ‘ ์‚ฌ์šฉ.
- ๋กœ๋”ฉ ์ตœ์ ํ™” [ํ•ด๊ฒฐ 5bbaf87] โ€” nginx gzip(css/js/json/svg) 1.76MBโ†’0.45MB. base.html ์™ธ๋ถ€ SDK(Daum/Kakao) ๋™๊ธฐ๋กœ๋“œ ์ œ๊ฑฐ. ์šด์˜ ๋ฏธ์ ์šฉ(ํ…Œ์ŠคํŠธ๋งŒ).
- ์ˆ˜์ •ํ•ด๋„ ๋ฐ˜์˜์•ˆ๋จ [ํ™•์ •] โ€” โ‘ ์„œ๋ฒ„ํŒŒ์ผ grep โ‘กgit pull ๊ถŒํ•œ/safe.directory โ‘ขuWSGI ์žฌ์‹œ์ž‘ โ‘ฃ๋ธŒ๋ผ์šฐ์ € ์‹œํฌ๋ฆฟ โ‘คview-source. JS ์—๋Ÿฌ๋Š” ํ›„์† ์ฝ”๋“œ ์ „์ฒด ์ฐจ๋‹จ.
## G. ์ฝ”๋”ฉ ๊ทœ์•ฝ (์š”์•ฝ)
- ํŒŒ์ผ ๋‹ค์šด๋กœ๋“œ: send_file(BytesIO) ร— โ†’ make_response(getvalue())+ํ—ค๋”. ํ•œ๊ธ€ํŒŒ์ผ๋ช… RFC5987 + ASCIIํ•„ํ„ฐ ord(c)<128.
- args["key"] ร— โ†’ args.get("key",""). SELECT a.*+๋ช…์‹œ์ปด๋Ÿผ ์ค‘๋ณต ร— โ†’ ๋ณ„์นญ(AS).
- JS: ์‹ ๊ทœ API URL apiURL(), ๋ฒ„ํŠผ์ƒ‰ !important, ์ด๋ฒคํŠธ๋Š” $(document).ready ๋‚ด/์œ„์ž„, ready try/catch.
- REST: POST /api// ยท PUT/DELETE/GET /api// ยท GET .../list ๋˜๋Š” POST .../search. estimate GET={estimateMaster, estimateDetailList}.

H. ๊ฒฌ์  ๊ตฌ์กฐ ๋ณต์‚ฌ ์„ค๊ณ„ โ†’ design-estimate-copy.md๋กœ ๋ถ„๋ฆฌ(2026-06-10). ์ง„ํ–‰ ์ƒํƒœ๋Š” handoff "์ง„ํ–‰ ์ค‘".