Skip to content

Commit f0a77e2

Browse files
committed
Merge remote-tracking branch 'origin/chore/add-welcomer-guide-doc'
2 parents 1c8e84a + c4ccdd9 commit f0a77e2

9 files changed

Lines changed: 128 additions & 107 deletions

File tree

README.md

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,77 @@
1-
# React + TypeScript + Vite
2-
3-
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4-
5-
Currently, two official plugins are available:
6-
7-
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
8-
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9-
10-
## Expanding the ESLint configuration
11-
12-
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
13-
14-
```js
15-
export default tseslint.config({
16-
extends: [
17-
// Remove ...tseslint.configs.recommended and replace with this
18-
...tseslint.configs.recommendedTypeChecked,
19-
// Alternatively, use this for stricter rules
20-
...tseslint.configs.strictTypeChecked,
21-
// Optionally, add this for stylistic rules
22-
...tseslint.configs.stylisticTypeChecked,
23-
],
24-
languageOptions: {
25-
// other options...
26-
parserOptions: {
27-
project: ['./tsconfig.node.json', './tsconfig.app.json'],
28-
tsconfigRootDir: import.meta.dirname,
29-
},
30-
},
31-
})
1+
# PyCon Korea Frontend (2025 - )
2+
3+
2025년 이후부터 PyCon Korea 사이트들의 모노레포입니다.
4+
5+
## 구성
6+
7+
- `apps/pyconkr-2025` — 2025 행사 사이트
8+
- `apps/pyconkr-2026` — 2026 행사 사이트
9+
- `apps/pyconkr-admin` — 관리자 페이지
10+
- `apps/pyconkr-participant-portal` — 참가자 포털
11+
- `packages/common`, `packages/shop` — 앱들이 공유하는 코드
12+
- `dotenv/` — 모든 앱이 공유하는 환경변수 파일
13+
14+
## 요구 사항
15+
16+
- Node.js 22+
17+
- pnpm (`package.json``packageManager` 필드 버전. `corepack enable`로 자동 설치 가능)
18+
- 첫 실행 시 mkcert가 로컬 CA를 시스템 신뢰 저장소에 자동 설치합니다 (관리자 비밀번호 요구될 수 있음)
19+
20+
## 설치
21+
22+
```bash
23+
pnpm install
3224
```
3325

34-
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
35-
36-
```js
37-
// eslint.config.js
38-
import reactX from 'eslint-plugin-react-x'
39-
import reactDom from 'eslint-plugin-react-dom'
40-
41-
export default tseslint.config({
42-
plugins: {
43-
// Add the react-x and react-dom plugins
44-
'react-x': reactX,
45-
'react-dom': reactDom,
46-
},
47-
rules: {
48-
// other rules...
49-
// Enable its recommended typescript rules
50-
...reactX.configs['recommended-typescript'].rules,
51-
...reactDom.configs.recommended.rules,
52-
},
53-
})
26+
## 환경변수
27+
28+
기본값은 `dotenv/.env.development`(원격 dev 백엔드)와 `dotenv/.env.production`에 들어 있고, 그대로 둬도 dev는 동작합니다.
29+
30+
|| 설명 |
31+
|---|---|
32+
| `VITE_PYCONKR_BACKEND_API_DOMAIN` | 백엔드 API 도메인. dev 서버에서는 vite proxy(`/v1`, `/api`)의 target으로 쓰이고, prod 빌드에서는 브라우저가 직접 호출합니다. |
33+
| `VITE_PYCONKR_BACKEND_CSRF_COOKIE_NAME` | 백엔드 CSRF 토큰 쿠키 이름. 환경(prod / dev / local)별로 prefix가 달라서 분리되어 있습니다. |
34+
| `VITE_PYCONKR_FRONTEND_DOMAIN` | 프론트엔드의 외부 도메인. 관리자 페이지의 외부 링크 생성 등에 사용됩니다. |
35+
| `VITE_PYCONKR_SHOP_IMP_ACCOUNT_ID` | PortOne(아임포트) 가맹점 식별자. 결제 모듈 초기화에 사용됩니다. |
36+
37+
로컬에서 값을 덮어쓰고 싶다면 **`dotenv/.env.development.local`**(gitignored)을 만들어 사용하세요. 예: 로컬에서 직접 띄운 백엔드를 쓰고 싶을 때 —
38+
39+
```bash
40+
VITE_PYCONKR_BACKEND_API_DOMAIN=http://localhost:8000
41+
VITE_PYCONKR_BACKEND_CSRF_COOKIE_NAME=LOCAL_PYCONKR_BACKEND_csrftoken
5442
```
43+
44+
## 개발 서버 실행
45+
46+
각 앱은 `https://localhost:<port>`로 뜹니다. 포트는 vite가 비어 있는 것을 자동 선택 (보통 5173부터).
47+
48+
```bash
49+
pnpm dev:@apps/pyconkr-2025
50+
pnpm dev:@apps/pyconkr-2026
51+
pnpm dev:@apps/pyconkr-admin
52+
pnpm dev:@apps/pyconkr-participant-portal
53+
```
54+
55+
백엔드 호출은 vite proxy(`/v1`, `/api`)로 forward되므로 별도 `/etc/hosts` 설정은 필요 없습니다. CORS와 쿠키(`Secure`, `Domain` 속성)도 proxy 단에서 자동으로 처리합니다.
56+
57+
## 빌드 / 프리뷰
58+
59+
```bash
60+
pnpm build:@apps/pyconkr-2025
61+
pnpm preview:@apps/pyconkr-2025
62+
```
63+
64+
다른 앱도 동일한 패턴 (`build:@apps/<app>`, `preview:@apps/<app>`).
65+
66+
## 린트 / 포맷
67+
68+
```bash
69+
pnpm lint
70+
pnpm format # 자동 수정
71+
pnpm format:check # 검사만
72+
```
73+
74+
## 자주 마주치는 이슈
75+
76+
- **TS 에러가 IDE에 떠 있는데 빌드/dev는 잘 됨**: 패키지 버전 변경 후 `node_modules/.pnpm/`에 orphan이 남아 IDE TS 서비스가 헷갈리는 경우입니다. `rm -rf node_modules && pnpm install` 후 VS Code의 TypeScript 서버를 재시작하세요.
77+
- **mkcert 인증서 오류**: `mkcert -install`을 한 번 직접 실행해보세요.

apps/pyconkr-2025/src/main.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ const queryClient = new QueryClient({
4545
}),
4646
});
4747

48-
const backendApiDomainEnv: string = import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
49-
const backendApiDomain = backendApiDomainEnv.startsWith("http://") ? "" : backendApiDomainEnv;
48+
// dev 서버에서는 vite proxy(/v1, /api)로 백엔드 호출 → relative URL 사용 (same-origin이라 CORS/쿠키 문제 회피)
49+
const backendApiDomain = import.meta.env.DEV ? "" : import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
5050

5151
const CommonOptions: ContextOptions = {
5252
language: "ko",

apps/pyconkr-2025/vite.config.mts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@ import svgr from "vite-plugin-svgr";
1010
export default defineConfig(({ mode }) => {
1111
const env = loadEnv(mode, path.resolve(__dirname, "../../dotenv"), "");
1212
const backendApiDomain = env.VITE_PYCONKR_BACKEND_API_DOMAIN ?? "";
13-
// 로컬 HTTP 백엔드면 http://localhost 로 서빙 + /v1, /api 를 proxy (mixed-content 회피 & CSRF 쿠키 동일 origin)
14-
const isLocalHttpBackend = backendApiDomain.startsWith("http://");
15-
const host = isLocalHttpBackend ? "localhost" : "local.dev.pycon.kr";
13+
14+
// 백엔드 응답 쿠키의 Domain 속성(예: pycon.kr) 제거 — localhost origin에서 브라우저가 저장 가능하도록.
15+
const proxyOptions = {
16+
target: backendApiDomain,
17+
changeOrigin: true,
18+
cookieDomainRewrite: "",
19+
headers: { "X-Frontend-Domain": "2025.pycon.kr" },
20+
};
1621

1722
return {
1823
base: "/",
1924
envDir: "../../dotenv",
20-
plugins: [react(), mdx(), ...(isLocalHttpBackend ? [] : [mkcert({ hosts: [host] })]), svgr()],
25+
plugins: [react(), mdx(), mkcert({ hosts: ["localhost"] }), svgr()],
2126
resolve: {
2227
alias: {
2328
"@frontend/common": path.resolve(__dirname, "../../packages/common/src"),
@@ -26,14 +31,11 @@ export default defineConfig(({ mode }) => {
2631
},
2732
},
2833
server: {
29-
host,
30-
allowedHosts: [host],
31-
proxy: isLocalHttpBackend
32-
? {
33-
"/v1": { target: backendApiDomain, changeOrigin: true },
34-
"/api": { target: backendApiDomain, changeOrigin: true },
35-
}
36-
: undefined,
34+
host: "localhost",
35+
proxy: {
36+
"/v1": proxyOptions,
37+
"/api": proxyOptions,
38+
},
3739
},
3840
};
3941
});

apps/pyconkr-2026/src/main.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ const queryClient = new QueryClient({
4545
}),
4646
});
4747

48-
const backendApiDomainEnv: string = import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
49-
const backendApiDomain = backendApiDomainEnv.startsWith("http://") ? "" : backendApiDomainEnv;
48+
// dev 서버에서는 vite proxy(/v1, /api)로 백엔드 호출 → relative URL 사용 (same-origin이라 CORS/쿠키 문제 회피)
49+
const backendApiDomain = import.meta.env.DEV ? "" : import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
5050

5151
const CommonOptions: ContextOptions = {
5252
language: "ko",

apps/pyconkr-2026/vite.config.mts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,19 @@ import svgr from "vite-plugin-svgr";
1010
export default defineConfig(({ mode }) => {
1111
const env = loadEnv(mode, path.resolve(__dirname, "../../dotenv"), "");
1212
const backendApiDomain = env.VITE_PYCONKR_BACKEND_API_DOMAIN ?? "";
13-
// 로컬 HTTP 백엔드면 http://localhost 로 서빙 + /v1, /api 를 proxy (mixed-content 회피 & CSRF 쿠키 동일 origin)
14-
const isLocalHttpBackend = backendApiDomain.startsWith("http://");
15-
const host = isLocalHttpBackend ? "localhost" : "local.dev.pycon.kr";
13+
14+
// 백엔드 응답 쿠키의 Domain 속성(예: pycon.kr) 제거 — localhost origin에서 브라우저가 저장 가능하도록.
15+
const proxyOptions = {
16+
target: backendApiDomain,
17+
changeOrigin: true,
18+
cookieDomainRewrite: "",
19+
headers: { "X-Frontend-Domain": "2026.pycon.kr" },
20+
};
1621

1722
return {
1823
base: "/",
1924
envDir: "../../dotenv",
20-
plugins: [react(), mdx(), ...(isLocalHttpBackend ? [] : [mkcert({ hosts: [host] })]), svgr()],
25+
plugins: [react(), mdx(), mkcert({ hosts: ["localhost"] }), svgr()],
2126
resolve: {
2227
alias: {
2328
"@frontend/common": path.resolve(__dirname, "../../packages/common/src"),
@@ -26,14 +31,11 @@ export default defineConfig(({ mode }) => {
2631
},
2732
},
2833
server: {
29-
host,
30-
allowedHosts: [host],
31-
proxy: isLocalHttpBackend
32-
? {
33-
"/v1": { target: backendApiDomain, changeOrigin: true },
34-
"/api": { target: backendApiDomain, changeOrigin: true },
35-
}
36-
: undefined,
34+
host: "localhost",
35+
proxy: {
36+
"/v1": proxyOptions,
37+
"/api": proxyOptions,
38+
},
3739
},
3840
};
3941
});

apps/pyconkr-admin/src/main.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ const queryClient = new QueryClient({
3737
}),
3838
});
3939

40-
const backendApiDomainEnv: string = import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
41-
const backendApiDomain = backendApiDomainEnv.startsWith("http://") ? "" : backendApiDomainEnv;
40+
// dev 서버에서는 vite proxy(/v1, /api)로 백엔드 호출 → relative URL 사용 (same-origin이라 CORS/쿠키 문제 회피)
41+
const backendApiDomain = import.meta.env.DEV ? "" : import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
4242

4343
const CommonOptions: ContextOptions = {
4444
debug: true,

apps/pyconkr-admin/vite.config.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ import svgr from "vite-plugin-svgr";
1010
export default defineConfig(({ mode }) => {
1111
const env = loadEnv(mode, path.resolve(__dirname, "../../dotenv"), "");
1212
const backendApiDomain = env.VITE_PYCONKR_BACKEND_API_DOMAIN ?? "";
13-
// 로컬 HTTP 백엔드면 http://localhost 로 서빙 + /v1, /api 를 proxy (mixed-content 회피 & CSRF 쿠키 동일 origin)
14-
const isLocalHttpBackend = backendApiDomain.startsWith("http://");
15-
const host = isLocalHttpBackend ? "localhost" : "local.dev.pycon.kr";
13+
14+
// 백엔드 응답 쿠키의 Domain 속성(예: pycon.kr) 제거 — localhost origin에서 브라우저가 저장 가능하도록.
15+
const proxyOptions = { target: backendApiDomain, changeOrigin: true, cookieDomainRewrite: "" };
1616

1717
return {
1818
base: "/",
1919
envDir: "../../dotenv",
20-
plugins: [react(), mdx(), ...(isLocalHttpBackend ? [] : [mkcert({ hosts: [host] })]), svgr()],
20+
plugins: [react(), mdx(), mkcert({ hosts: ["localhost"] }), svgr()],
2121
resolve: {
2222
alias: {
2323
"@frontend/common": path.resolve(__dirname, "../../packages/common/src"),
@@ -26,14 +26,11 @@ export default defineConfig(({ mode }) => {
2626
},
2727
},
2828
server: {
29-
host,
30-
allowedHosts: [host],
31-
proxy: isLocalHttpBackend
32-
? {
33-
"/v1": { target: backendApiDomain, changeOrigin: true },
34-
"/api": { target: backendApiDomain, changeOrigin: true },
35-
}
36-
: undefined,
29+
host: "localhost",
30+
proxy: {
31+
"/v1": proxyOptions,
32+
"/api": proxyOptions,
33+
},
3734
},
3835
};
3936
});

apps/pyconkr-participant-portal/src/main.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ const queryClient = new QueryClient({
3535

3636
const muiTheme = createTheme();
3737

38-
const backendApiDomainEnv: string = import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
39-
const backendApiDomain = backendApiDomainEnv.startsWith("http://") ? "" : backendApiDomainEnv;
38+
// dev 서버에서는 vite proxy(/v1, /api)로 백엔드 호출 → relative URL 사용 (same-origin이라 CORS/쿠키 문제 회피)
39+
const backendApiDomain = import.meta.env.DEV ? "" : import.meta.env.VITE_PYCONKR_BACKEND_API_DOMAIN;
4040

4141
const CommonOptions: ContextOptions = {
4242
language: "ko",

apps/pyconkr-participant-portal/vite.config.mts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ import svgr from "vite-plugin-svgr";
1010
export default defineConfig(({ mode }) => {
1111
const env = loadEnv(mode, path.resolve(__dirname, "../../dotenv"), "");
1212
const backendApiDomain = env.VITE_PYCONKR_BACKEND_API_DOMAIN ?? "";
13-
// 로컬 HTTP 백엔드면 http://localhost 로 서빙 + /v1, /api 를 proxy (mixed-content 회피 & CSRF 쿠키 동일 origin)
14-
const isLocalHttpBackend = backendApiDomain.startsWith("http://");
15-
const host = isLocalHttpBackend ? "localhost" : "local.dev.pycon.kr";
13+
14+
// 백엔드 응답 쿠키의 Domain 속성(예: pycon.kr) 제거 — localhost origin에서 브라우저가 저장 가능하도록.
15+
const proxyOptions = { target: backendApiDomain, changeOrigin: true, cookieDomainRewrite: "" };
1616

1717
return {
1818
base: "/",
1919
envDir: "../../dotenv",
20-
plugins: [react(), mdx(), ...(isLocalHttpBackend ? [] : [mkcert({ hosts: [host] })]), svgr()],
20+
plugins: [react(), mdx(), mkcert({ hosts: ["localhost"] }), svgr()],
2121
resolve: {
2222
alias: {
2323
"@frontend/common": path.resolve(__dirname, "../../packages/common/src"),
@@ -26,14 +26,11 @@ export default defineConfig(({ mode }) => {
2626
},
2727
},
2828
server: {
29-
host,
30-
allowedHosts: [host],
31-
proxy: isLocalHttpBackend
32-
? {
33-
"/v1": { target: backendApiDomain, changeOrigin: true },
34-
"/api": { target: backendApiDomain, changeOrigin: true },
35-
}
36-
: undefined,
29+
host: "localhost",
30+
proxy: {
31+
"/v1": proxyOptions,
32+
"/api": proxyOptions,
33+
},
3734
},
3835
};
3936
});

0 commit comments

Comments
 (0)