1. ๊ฐ์
๋ณธ ๋ฌธ์์์๋ Legacy Web๊ณผ Mobile์ ๋ชจ๋ ธ๋ ํฌ ํ๋ก์ ํธ๋ก ํตํฉํ๋ ์ค๊ณ์ ์ ํ ์ ๋ต์ ์ ์ํฉ๋๋ค.
2. ํ์ฌ ์ํฉ & ๋ฌธ์ ์
๊ธฐ์ ์คํ
- Next.js 12.3.6 + JavaScript(ES6)
- MobX 6.5.0, Material-UI v4
- React Query v3, Axios, npm
์ฃผ์ ๋ฌธ์
- ๊ฐ๋ฐ ํ๊ฒฝ ๋ณต์ก
- Express ๊ธฐ๋ฐ ์ปค์คํ ์๋ฒ(500+์ค), API ํ๋ก์ ์ค๋ณต
- ํ๊ฒฝ ๋ณ์ ๊ด๋ฆฌ ๋์ด๋ ๋์
- ํด๋ ๊ตฌ์กฐ ๋นํ์คํ
- v1/v2 ํผ์ฌ, Atomic Design ์ผ๋ถ ์ ์ฉ
- ์ปดํฌ๋ํธ ์ฌ์ฌ์ฉ์ฑ ๋ฎ์
- ์ฝ๋ ๋ฐ ์์กด์ฑ ์ค๋ณต
- ๋์ผ ๋ก์ง·UI๋ฅผ ๋ ํ๋ก์ ํธ์ ์ค๋ณต ๊ตฌํ
- ์์กด์ฑ 100% ์ค๋ณต ์ค์น
- ๊ธฐ์ ๋ถ์ฑ
- Next.js 12, React 17, MUI v4 ๋ฑ ๊ตฌ๋ฒ์
- JavaScript → TypeScript ํ์
๋๋ณด๊ธฐ
# ๋ฌธ์ ์ ์ ๋ํ ์์ธํ ์ค๋ช
Express ๊ธฐ๋ฐ ์ปค์คํ ์๋ฒ(500+์ค), API ํ๋ก์ ์ค๋ณต
// server/index.js (27-50ํ)
server.post("/api/v2/*/upload", upload.single("file"), async (req, res) => {
// ๋์ผํ ํค๋ ์ฒ๋ฆฌ ๋ก์ง์ด 10๋ฒ ์ด์ ๋ฐ๋ณต๋จ
const headers = { ...req.headers };
delete headers["content-length"];
delete headers.host;
// ...
});
// server/index.js (52-86ํ) - ๊ฑฐ์ ๋์ผํ ์ฝ๋ ํจํด
server.post("/api/v2/*", async (req, res) => {
// ๋์ผํ ํค๋ ์ฒ๋ฆฌ ๋ก์ง ๋ฐ๋ณต
const headers = { ...req.headers };
delete headers["content-length"];
delete headers.host;
// ...
});
- server/index.js: 985์ค์ ๊ฑฐ๋ํ ํ์ผ
- ๋์ผํ ํค๋ ์ฒ๋ฆฌ ๋ก์ง์ด 10๋ฒ ์ด์ ๋ฐ๋ณต
- API ํ๋ก์ ๋ก์ง ์ค๋ณต (axiosUrl, axiosFileUrl)
ํ๊ฒฝ ๋ณ์ ๊ด๋ฆฌ ๋์ด๋ ๋์
// Dockerfile์์ 22๊ฐ์ ํ๊ฒฝ๋ณ์ ARG/ENV ์ ์
ARG ENV_ALB_URL
ARG ENV_ALB_PORT
ARG ENV_API_VERSION
// ... 22๊ฐ ๋ณ์
// server/server.utils.js - ํ๊ฒฝ๋ณ ๋ถ๊ธฐ ๋ก์ง
const axiosUrl = (req) => {
return process.env.NODE_ENV === "local" ?
`${process.env.ENV_LOCAL_API_HOST}:${process.env.ENV_LOCAL_API_PORT}${req.url}`:
process.env.NODE_ENV === "development" ?
`${process.env.ENV_DEV_API_HOST}:${process.env.ENV_DEV_API_PORT}${req.url}` :
`${process.env.ENV_ALB_URL}:${process.env.ENV_ALB_PORT}${req.url}`;
};
- Dockerfile์ 22๊ฐ ์ด์์ ํ๊ฒฝ๋ณ์ ์ ์
- ํ๊ฒฝ๋ณ ๋ถ๊ธฐ ๋ก์ง์ด ์ฌ๋ฌ ํ์ผ์ ๋ถ์ฐ
๋์ผํ ํ์ด์ง์์ v1/v2 ์ปดํฌ๋ํธ ํผ์ฌ
// pages/inventory/center/search/product/index.js (69์ค)
import MuiTableSelectOneV2 from "/components/common/MuiTable/MuiTableSelectOneV2"; // V2 ์ฌ์ฉ
import MuiTableTitle from "/components/common/MuiTable/MuiTableTitle"; // V1 ์ฌ์ฉ
import MuiTableWrapper from "/components/common/MuiTable/MuiTableWrapper"; // V1 ์ฌ์ฉ
import AgGrid from "/components/common/AgGrid"; // V1 ์ฌ์ฉ
// 1163์ค์์ V2 ์ปดํฌ๋ํธ ์ฌ์ฉ
<MuiTableSelectOneV2
name={"userSelectConnectSubAccountListSelect"}
columns={USER_SELECT_CONNECT_SUB_ACCOUNT_LIST_SELECT_COLUMNS}
// V2 ๋ฐฉ์์ props
/>
// ํ์ง๋ง ๋์ผ ํ์ด์ง์์ V1 ์ปดํฌ๋ํธ๋ ์ฌ์ฉ
<MuiTableTitle titleText={getLang("WD000183")} /> // V1 ๋ฐฉ์
<MuiTableWrapper> // V1 ๋ฐฉ์
- components/common/ (v1) + components/v2/ ํผ์ฌ
- v1, v2 ์ปดํฌ๋ํธ์ ์ฐจ์ด์ ํ์ ์ ๊ฐ๋ฐ ์๊ฐ ์์
- ์คํ์ผ๋ง ๋ฐฉ์ ๋ฐ props ๊ตฌ์กฐ ๋ค๋ฆ → ์ผ๊ด์ฑ ์๋ UX
์ปดํฌ๋ํธ ์ฌ์ฌ์ฉ์ฑ ๋ฎ์
components/common/MuiTable/
โโโ MuiTable/ # ๊ธฐ๋ณธ ํ
์ด๋ธ
โโโ MuiTable2/ # ๊ธฐ๋ณธ ํ
์ด๋ธ ๋ณํ
โโโ MuiTableSelectOne/ # V1 ๋จ์ผ ์ ํ
โโโ MuiTableSelectOneV2/ # V2 ๋จ์ผ ์ ํ
โโโ MuiTableForSelectedRows/ # V1 ์ ํ๋ ํ ํ์
โโโ MuiTableForSelectedRowsV2/ # V2 ์ ํ๋ ํ ํ์
โโโ MuiTableSelectV2/ # V2 ๋ค์ค ์ ํ
โโโ MuiCustomTable/ # ์ปค์คํ
ํ
์ด๋ธ
โโโ MuiTableExpand/ # ํ์ฅ ๊ฐ๋ฅ ํ
์ด๋ธ
โโโ MuiTableWithpaging/ # ํ์ด์ง ํฌํจ ํ
์ด๋ธ
โโโ ... 15๊ฐ ๋
- 25๊ฐ ์ด์์ ํ ์ด๋ธ ์ปดํฌ๋ํธ - ๊ธฐ๋ณธ ๊ธฐ๋ฅ์ด ๊ฐ์๋ฐ๋ ๋ถ๊ตฌํ๊ณ ์ค๋ณต ๊ตฌํ
- 7๊ฐ์ ๋ชจ๋ฌ ์ปดํฌ๋ํธ: Modal, MuiTableClickModal, CommonAlertModal ๋ฑ ์ ์ฌ ๊ธฐ๋ฅ ์ค๋ณต
- ๊ณตํตํ ์์ด ํ์ด์ง๋ณ๋ก ์ปดํฌ๋ํธ ์ฝ๋๋ฅผ ๋ณต์ฌ ๋ถ์ฌ๋ฃ๊ธฐํ์ฌ ์ฌ์ฉ
3. ๋ชจ๋ ธ๋ ํฌ ์ ํ ํ์์ฑ
- ํตํฉ ๊ฐ๋ฐ ํ๊ฒฝ
- ๋จ์ผ ์ ์ฅ์·๊ฐ๋ฐ ์๋ฒ → Turbo ๋ณ๋ ฌ ๋น๋ & Hot Reload ์ต์ ํ
- ์ฝ๋ ์ฌ์ฌ์ฉ ๊ทน๋ํ
- @repo/ui, @repo/shared, @repo/react-query ๋ฑ ํจํค์งํ
- ์ต์ ์คํ ์ ์ฉ
- Next.js 15 App Router, TypeScript, Zustand, TanStack Query v5, Zod
- DX ํฅ์
- ESLint/Prettier/Husky/Lint-staged ๋์
- ํตํฉ ์คํฌ๋ฆฝํธ: pnpm dev:web, pnpm dev:admin
| AS-IS | TO-BE | ์ ํ ์ด์ / ๊ธฐ๋ ํจ๊ณผ |
| JavaScript | TypeScript | ํ์ ์์ ์ฑ ํ๋ณด, ๋๊ท๋ชจ ์ฝ๋๋ฒ ์ด์ค ์ ์ง๋ณด์ ์ฉ์ด, ๋ฐํ์ ์ค๋ฅ ์ฌ์ ๋ฐฉ์ง |
| Next.js 12 + Page Router | Next.js 15 + App Router | Next.js 12๋ ์ฅ๊ธฐ ์ง์ ์ข ๋ฃ ์์ , App Router๋ก ์ฑ๋ฅ·๋ฐ์ดํฐ ํจ์นญ ๋ฐฉ์ ๊ฐ์ |
| Material-UI v4 | ์ปค์คํ ๋์์ธ ์์คํ | MUI v4๋ ์ ์ง๋ณด์ ์ค๋จ, ๋์์ธ ์ผ๊ด์ฑ ๊ฐํ ๋ฐ ๋ถํ์ํ ์์กด์ฑ ์ ๊ฑฐ๋ก ๋ฒ๋ค ์ฌ์ด์ฆ ๊ฐ์ |
| MobX | Zustand | MobX TS ์ง์ ๋ฏธํก, ๊ฒฝ๋·๊ฐ๋จํ API ์ ๊ณต, TypeScript ์นํ์ |
| React Query v3 | TanStack Query v5 | v3๋ Maintenance Mode, ์ต์ ๋ฒ์ ์์ ์บ์ฑ·๋๊ธฐํ ์ฑ๋ฅ ๋ฐ DevTool ๊ฐ์ |
| npm | pnpm | ๋์คํฌ ๊ณต๊ฐ ์ ์ฝ, ์ค์น ์๋ ํฅ์, ๋ชจ๋ ธ๋ ํฌ ํ๊ฒฝ ์ต์ ํ |
| npm run build | Turbo build | ๋น๋ ์บ์ฑ·๋ณ๋ ฌ ์ฒ๋ฆฌ ์ง์, ์ฆ๋ถ ๋น๋๋ก ๋น๋ ์๊ฐ ๋จ์ถ |
4. ์ ์ง์ ๋ฐฐํฌ ๋ฐ ๋ผ์ฐํ ์ ๋ต
ECS ์๋น์ค ๊ตฌ์ฑ
ECS Cluster: (์๋น์ค๋ช
)-cluster
โโโ (์๋น์ค๋ช
)-web-service (NEW) - ๋ชจ๋
ธ๋ ํฌ Web App
โโโ (์๋น์ค๋ช
)-mobile-service (NEW) - ๋ชจ๋
ธ๋ ํฌ Mobile App
โโโ (์๋น์ค๋ช
)-admin-ui-service (NEW) - ๋ชจ๋
ธ๋ ํฌ Admin App
โโโ (์๋น์ค๋ช
)-ui-service (LEGACY) - ๋ ๊ฑฐ์ Web
โโโ (์๋น์ค๋ช
)-mobile-ui-service (LEGACY) - ๋ ๊ฑฐ์ Mobile
ALB ๋ผ์ฐํ ๊ท์น
Application Load Balancer
โโโ Listener :443 (HTTPS)
โ โโโ Path /* → (์๋น์ค๋ช
)-ui-service (Legacy Web)
โ โโโ Path /v2/* → (์๋น์ค๋ช
)-web-service (Monorepo Web)
โ
โโโ Listener :8443 (HTTPS)
โ โโโ Path /* → (์๋น์ค๋ช
)-mobile-ui-service (Legacy Mobile)
โ โโโ Path /v2/* → (์๋น์ค๋ช
)-mobile-service (Monorepo Mobile)
โ
โโโ Listener :9443 (HTTPS)
โโโ Path /* → (์๋น์ค๋ช
)-admin-ui-service (Monorepo Admin)
์ ํ ๋ฐฉ์
- ๊ธฐ์กด ๊ฒฝ๋ก(/) ์์ฒญ → ๋ ๊ฑฐ์ ์๋น์ค๋ก ๋ผ์ฐํ
- ์ ๊ท ๊ฐ๋ฐ ํ์ด์ง(/v2/*) ์์ฒญ → ์ ๊ท web-service, mobile-service๋ก ๋ผ์ฐํ
- Admin ์๋น์ค๋ ๋ ๋ฆฝ ํฌํธ(9443)์์ ์ ๊ท ๋ชจ๋ ธ๋ ํฌ ๋ฒ์ ์ด์
๋ชฉ์
- ์ ๊ท ๊ฐ๋ฐ๋ ํ์ด์ง๋ /v2/* ๊ฒฝ๋ก๋ฅผ ํตํด ์ ๊ณต
- ๊ธฐ์กด ์๋น์ค์ ์ ๊ท ์๋น์ค ๋์ ์ด์ํ์ฌ ์์ ์ ์ธ ๋ง์ด๊ทธ๋ ์ด์ ๊ฐ๋ฅ
- ๊ธฐ๋ฅ๋ณ/ํ์ด์ง๋ณ ์ ์ง์ ์ ํ์ผ๋ก ๋ฆฌ์คํฌ ์ต์ํ
- ์ต์ข ์ ์ผ๋ก / ๊ฒฝ๋ก๋ฅผ ์ ๊ท ํ๊ฒฝ์ผ๋ก ์ ํ
5. ์๋ก์ด ์ํคํ ์ฒ
(์๋น์ค๋ช
)_frontend/
โโโ apps/
โ โโโ admin/ # ๊ด๋ฆฌ์ ์๋น์ค
โ โโโ mobile/ # Mobile
โ โโโ web/ # Web
โโโ packages/
โ โโโ ui/ # ๋์์ธ ์์คํ
โ โโโ shared/ # ๋น์ฆ๋์ค ๋ก์ง
โ โโโ react-query/
โ โโโ zustand/
โ โโโ zod/
โ โโโ configs/
โ โโโ eslint-config/
- packages ๊ด๋ฆฌ(ํจํค์งํ)๋ฅผ ํตํด ์ฝ๋ ์ฌ์ฌ์ฉ ๊ทน๋ํ
6. ๋ง์ด๊ทธ๋ ์ด์ ๋จ๊ณ
Phase 1: ๊ธฐ๋ฐ ๊ตฌ์กฐ ๊ตฌ์ถ (pnpm, Turbo, ๊ณตํต ํจํค์ง, CI/CD)
Phase 2: UI ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ตฌ์ถ (TS ์ ํ, Atomic Design, Storybook, ๋์์ธ ํ ํฐ)
Phase 3: Web, Mobile App ๋ง์ด๊ทธ๋ ์ด์ (์ปค์คํ ์๋ฒ ์ ๊ฑฐ, ๋ฐ์ํ·์ฑ๋ฅ ์ต์ ํ)
Phase 4: ์ด์ ์ต์ ํ (๋ฒ๋ค ์ต์ ํ, ๋ชจ๋ํฐ๋ง·๋ก๊ทธ ํตํฉ, ๋ฌธ์ํ)
7. ๊ธฐ๋ ํจ๊ณผ
๊ฐ๋ฐ ์์ฐ์ฑ
- ๋ณ๋ ฌ ๋น๋ ๋ฐ Turbo ์บ์๋ก ๋น๋ ์๊ฐ 60~70% ๋จ์ถ
- ๊ณตํต ์ฝ๋ 90% ์ด์ ์ฌ์ฌ์ฉ, ์์ ·๋ฐฐํฌ ํ์ ์ ๋ฐ์ผ๋ก ๊ฐ์
์ฝ๋ ํ์ง
- ํ์ ์์ ์ฑ·์๋์์ฑ·์์ ํ ๋ฆฌํฉํ ๋ง
- ESLint + Prettier๋ก ์คํ์ผ ์ผ๊ด์ฑ ํ๋ณด
์ด์ ํจ์จ์ฑ
- ๋ณ๊ฒฝ๋ ์ฑ๋ง ๋ฐฐํฌ
UI/UX ๊ฐ์
- 2.0 ๋์์ธ ์์คํ ๋์
'Front-end' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| Express ์ปค์คํ ์๋ฒ๋ฅผ Next.js API Routes๋ก ๋ง์ด๊ทธ๋ ์ด์ ํ๊ธฐ (0) | 2026.02.01 |
|---|---|
| Next.js ๋น๋ ์ต์ ํ : Babel โ SWC ์ ํ (1) | 2025.08.17 |
| Next.js ์ด๊ธฐ ๋ ๋๋ง ์ ๋ค๊ตญ์ด ๋ฌธ๊ตฌ๊ฐ ๋น์ด ๋ณด์ด๋ ๋ฌธ์ ํด๊ฒฐํ๊ธฐ (1) | 2025.06.15 |
| useState์ ๋น๋๊ธฐ์ฑ (0) | 2025.04.13 |
| React key prop๊ณผ ์ํ ์ด๊ธฐํ (0) | 2025.02.23 |