This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
|
||||
### 2.1 프로젝트 구조 (통합)
|
||||
|
||||
**단일 앱 구조** (소규모 프로젝트 최적화):
|
||||
**단일 앱 구조** (공개 사이트 + 관리자까지 하나의 ASP.NET Core 앱):
|
||||
|
||||
```
|
||||
TaxBaik.Domain 클래스 라이브러리 (엔티티, 인터페이스, enum)
|
||||
@@ -32,7 +32,7 @@ TaxBaik.Web ASP.NET Core 앱 (포트 5001)
|
||||
|
||||
**경로:**
|
||||
- 홈페이지: `/taxbaik` (Razor Pages)
|
||||
- 관리자: `/taxbaik/admin` (Blazor)
|
||||
- 관리자: `/taxbaik/admin` (Blazor Server)
|
||||
- 로그인: `/taxbaik/admin/login`
|
||||
|
||||
### 2.2 계층 책임
|
||||
@@ -54,11 +54,11 @@ TaxBaik.Web ASP.NET Core 앱 (포트 5001)
|
||||
- 복잡한 관리 UI를 쉽게 구현
|
||||
|
||||
**왜 단일 앱 (통합 Web)인가?**
|
||||
- 소규모 프로젝트 → 분리의 이점 < 개발 복잡도
|
||||
- 공개 사이트와 관리자 화면을 같은 호스트와 PathBase에서 운영하면 라우팅과 인증 구성이 단순함
|
||||
- **개발**: 터미널 1개, 포트 1개 (5001)
|
||||
- **배포**: 앱 1개, DB 마이그레이션 1회
|
||||
- **유지보수**: 모든 비즈니스 로직 한 곳 (Application)
|
||||
- **장점**: 기존 분리 구조의 모든 기능 + 간단한 개발 경험
|
||||
- **장점**: 블로그 SEO와 관리자 기능을 하나의 실행 단위로 운영
|
||||
|
||||
**왜 Dapper인가?**
|
||||
- 팀 기존 지식 (QuantEngine에서 사용)
|
||||
@@ -112,7 +112,7 @@ dotnet run -p TaxBaik.Web
|
||||
# 터미널 1: SSH 터널 유지
|
||||
ssh -L 5432:127.0.0.1:5432 kjh2064@178.104.200.7
|
||||
|
||||
# 터미널 2: 통합 Web 앱 (Razor Pages + Blazor)
|
||||
# 터미널 2: 통합 Web 앱 (Razor Pages + Blazor Server Admin)
|
||||
cd TaxBaik.Web
|
||||
dotnet run
|
||||
# 접속:
|
||||
@@ -248,48 +248,23 @@ ssh kjh2064@178.104.200.7
|
||||
5432 : PostgreSQL (localhost 바인드)
|
||||
```
|
||||
|
||||
### 3.3 배포 절차 (Shadow Copy를 통한 Hot Deploy)
|
||||
### 3.3 배포 절차 (CI only)
|
||||
|
||||
**핵심 전략**: .NET Core shadow copy로 배포 중 무중단 실행
|
||||
배포는 수동 실행이 아니라 **Gitea Actions CI/CD**만 사용한다.
|
||||
|
||||
1. **로컬 빌드** (단일 앱 통합):
|
||||
```bash
|
||||
dotnet clean TaxBaik.sln
|
||||
dotnet publish TaxBaik.Web -c Release -o ./publish
|
||||
```
|
||||
1. `master` 브랜치에 push
|
||||
2. Gitea Actions가 `TaxBaik.Web`을 build/publish
|
||||
3. CI가 서버의 `taxbaik` 서비스와 `~/taxbaik_active`를 갱신
|
||||
4. CI가 서비스 재시작 후 `/taxbaik/admin/login`으로 헬스 체크
|
||||
|
||||
2. **CI/CD 배포** (Gitea Actions):
|
||||
- 새 버전을 `~/deployments/taxbaik_TIMESTAMP/` 에 업로드
|
||||
- 기존 프로세스는 계속 실행 (원본 DLL은 영향 없음)
|
||||
**운영 규칙**:
|
||||
- 로컬 또는 서버에서 수동 `dotnet publish`로 운영 배포하지 않는다
|
||||
- `rsync`로 직접 아티팩트를 올리지 않는다
|
||||
- 배포 실패 시 CI 로그를 먼저 본다
|
||||
|
||||
3. **Shadow Copy 메커니즘**:
|
||||
- .NET Core 런타임이 어셈블리를 메모리에 로드
|
||||
- `~/deployments/` 아래의 새 DLL들을 준비
|
||||
- 심링크만 변경 (`ln -sfn ~/deployments/taxbaik_TIMESTAMP ~/taxbaik_active`)
|
||||
|
||||
4. **Graceful Restart**:
|
||||
- 기존 요청 완료 대기 (max 30초)
|
||||
- `sudo systemctl restart taxbaik` 실행
|
||||
- 새 프로세스가 새 DLL 로드
|
||||
|
||||
5. **롤백 (1초 이내)**:
|
||||
```bash
|
||||
ln -sfn ~/deployments/taxbaik_PREVIOUS_TIMESTAMP ~/taxbaik_active
|
||||
sudo systemctl restart taxbaik
|
||||
```
|
||||
|
||||
6. **오래된 배포 정리** (매 배포마다):
|
||||
```bash
|
||||
# 최근 5개 배포만 유지
|
||||
ls -dt ~/deployments/taxbaik_* | tail -n +6 | xargs -r rm -rf
|
||||
```
|
||||
|
||||
**systemd 서비스 graceful shutdown 설정**:
|
||||
```ini
|
||||
[Service]
|
||||
TimeoutStopSec=35 # 기존 요청 완료 대기 (30초) + 여유
|
||||
KillMode=mixed # SIGTERM → 30초 대기 → SIGKILL
|
||||
```
|
||||
**롤백**:
|
||||
- 이전 정상 커밋을 `master`에 revert 또는 hotfix로 되돌린다
|
||||
- 서버 파일을 수동으로 복구하지 않는다
|
||||
|
||||
### 3.4 서비스 파일 위치
|
||||
```
|
||||
@@ -297,14 +272,7 @@ KillMode=mixed # SIGTERM → 30초 대기 → SIGKILL
|
||||
```
|
||||
|
||||
### 5.5 배포 디렉토리 구조 (서버)
|
||||
```
|
||||
/home/kjh2064/
|
||||
├── taxbaik_active → ./deployments/taxbaik_20260626_150000/
|
||||
└── deployments/
|
||||
├── taxbaik_20260626_150000/ (통합 Web publish 출력)
|
||||
├── taxbaik_20260626_140000/ (이전 버전)
|
||||
└── ...
|
||||
```
|
||||
배포 디렉토리는 CI가 관리한다. 로컬에서 구조를 맞추거나 수동으로 갱신하지 않는다.
|
||||
|
||||
---
|
||||
|
||||
@@ -319,7 +287,7 @@ location /taxbaik {
|
||||
proxy_pass http://127.0.0.1:5001;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "Upgrade";
|
||||
proxy_set_header Connection $connection_upgrade;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
@@ -328,7 +296,7 @@ location /taxbaik {
|
||||
}
|
||||
```
|
||||
|
||||
**참고**: 단일 `/taxbaik` 블록이 공개 사이트와 관리자 (Blazor WebSocket)를 모두 처리합니다.
|
||||
**참고**: 단일 `/taxbaik` 블록이 공개 사이트와 관리자(Blazor WebSocket)를 모두 처리합니다. 운영은 `5001` 통합 앱 기준이며, 설정 반영은 CI 배포로만 수행한다.
|
||||
|
||||
---
|
||||
|
||||
@@ -373,7 +341,7 @@ public async Task<BlogPost?> GetBySlugAsync(string slug, CancellationToken ct)
|
||||
- 항상 `using var conn = Conn();` 사용 (자동 닫기)
|
||||
- 항상 `@ParameterName` 파라미터 사용 (SQL injection 방지)
|
||||
- 절대 문자열 연결 금지
|
||||
- 대소문자 구분 안 함 (Dapper가 매핑)
|
||||
- PostgreSQL `snake_case` 컬럼은 Dapper underscore 매핑을 전제로 함
|
||||
|
||||
### 3.3 마이그레이션
|
||||
|
||||
|
||||
Reference in New Issue
Block a user