현대적인 Go 웹 서버로, Gin 프레임워크를 기반으로 구축되었으며 JWT 인증, SQLite 데이터베이스, RESTful API 엔드포인트를 제공합니다.
- ⚡ 고성능 웹 프레임워크: Gin 웹 프레임워크 기반으로 구축
- 🔐 JWT 인증 시스템: 안전한 토큰 기반 인증
- 🗄️ 경량 데이터베이스: GORM ORM과 함께하는 SQLite
- 🌐 CORS 지원: 크로스 오리진 리소스 공유 활성화
- 🏥 헬스체크: 내장된 서버 상태 확인 엔드포인트
- 🛑 그레이스풀 셧다운: 적절한 서버 종료 처리
- ⚙️ 환경 변수 설정: 환경 변수 기반 설정 관리
- 📝 구조화된 로깅: 이모지와 함께하는 포괄적인 로깅 시스템
- 🧩 모듈화 아키텍처: 깔끔한 코드 구조와 분리
- ⚡ 실시간 업데이트: WebSocket을 통한 실시간 토론 정보 동기화
- 💬 토론 플랫폼: 찬반 토론을 위한 완전한 플랫폼 (ARGX 토큰 시스템 포함)
- Go 1.25.3: 고성능 프로그래밍 언어
- Gin Web Framework: 경량 웹 프레임워크
- GORM: Go를 위한 강력한 ORM 라이브러리
- SQLite: 서버가 필요 없는 관계형 데이터베이스
- JWT: JSON Web Token 인증
- CORS Middleware: 크로스 오리진 요청 처리
- Environment Management:
.env파일 지원 - Crypto: 비밀번호 해싱 및 보안
- Logging: 구조화된 로그 관리
- WebSocket: 실시간 양방향 통신 (gorilla/websocket)
- Go 1.19 이상: Go 다운로드
- Git: 버전 관리 시스템
- 텍스트 에디터: VS Code, GoLand 등
- 운영체제: Windows, macOS, Linux
- 메모리: 최소 512MB RAM
- 디스크 공간: 100MB 이상
git clone <repository-url>
cd argu-x-server# Go 모듈 초기화 및 의존성 설치
go mod tidy
# 의존성 다운로드
go mod download# .env 파일 복사 (환경에 따라)
cp .env .env.local# 기본 포트(8000)로 실행
go run main.go
# 또는 특정 포트로 실행
PORT=3000 go run main.go# 최적화된 빌드
go build -ldflags "-s -w" -o server main.go
# 실행
./server서버가 성공적으로 시작되면 다음과 같은 로그를 확인할 수 있습니다:
🚀 Starting Argu-X Server...
📅 Started at: 2025-01-22 15:04:05
──────────────────────────────────────────────────
🔌 Connecting to database...
✅ Database connected and migrated successfully
🔧 Gin mode set to: release
🚀 Setting up server...
✅ Server setup completed
🌐 Server starting on port 8000
📊 Health check available at: http://localhost:8000/health
🔗 API available at: http://localhost:8000/api/v1
⏱️ Timeouts - Read: 15s, Write: 15s, Idle: 60s
✅ Server started successfully
서버는 환경 변수를 통해 설정됩니다. .env 파일을 수정하여 설정을 변경할 수 있습니다.
.env 파일을 생성하거나 수정하여 다음 변수들을 설정하세요:
# JWT 설정
JWT_SECRET=your-super-secret-jwt-key-here
# 서버 설정
PORT=8000
GIN_MODE=release
# 데이터베이스 설정
DATABASE_URL=argux.db
# CORS 설정
ALLOWED_ORIGINS=*
# 로깅 설정
LOG_LEVEL=info
# 타임아웃 설정 (초)
READ_TIMEOUT=15
WRITE_TIMEOUT=15
IDLE_TIMEOUT=60| 변수명 | 설명 | 기본값 | 필수 | 예시 |
|---|---|---|---|---|
JWT_SECRET |
JWT 서명용 비밀 키 | "argu-x" | ❌ | 강력한 32자 이상 문자열 |
PORT |
서버 포트 | 8000 | ❌ | 3000, 8080, 9000 |
GIN_MODE |
Gin 모드 | release | ❌ | debug, release, test |
DATABASE_URL |
SQLite 파일 경로 | "argux.db" | ❌ | ./data/app.db |
ALLOWED_ORIGINS |
CORS 허용 도메인 | "*" | ❌ | https://example.com |
LOG_LEVEL |
로그 레벨 | info | ❌ | debug, info, warn, error |
READ_TIMEOUT |
HTTP 읽기 타임아웃 | 15 | ❌ | 30, 60 |
WRITE_TIMEOUT |
HTTP 쓰기 타임아웃 | 15 | ❌ | 30, 60 |
IDLE_TIMEOUT |
HTTP 유휴 타임아웃 | 60 | ❌ | 120, 300 |
http://localhost:8000
서버 상태를 확인하는 간단한 엔드포인트
- GET
/health - 응답:
{"status": "ok"}
새로운 사용자 계정을 생성합니다.
- POST
/api/v1/signup - Content-Type:
application/json
요청 본문:
{
"name": "사용자명",
"email": "user@example.com",
"password": "비밀번호"
}응답:
{
"message": "User created successfully",
"user": {
"id": 1,
"name": "사용자명",
"email": "user@example.com",
"created_at": "2025-01-22T15:04:05Z"
}
}JWT 토큰을 받아서 인증합니다.
- POST
/api/v1/login - Content-Type:
application/json
요청 본문:
{
"email": "user@example.com",
"password": "비밀번호"
}응답:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"name": "사용자명",
"email": "user@example.com",
"argx": 10
}
}현재 로그인된 사용자의 프로필 정보를 반환합니다.
- GET
/api/v1/profile - Authorization:
Bearer <JWT_TOKEN>
시스템의 모든 사용자 정보를 반환합니다.
- GET
/api/v1/users - Authorization:
Bearer <JWT_TOKEN>
ID로 특정 사용자 정보를 조회합니다.
- GET
/api/v1/users/:id - Authorization:
Bearer <JWT_TOKEN>
응답 예시:
[
{
"id": 1,
"name": "사용자명",
"email": "user@example.com",
"avatar": "",
"argx": 10,
"created_at": "2025-01-22T15:04:05Z",
"updated_at": "2025-01-22T15:04:05Z"
}
]새로운 토론을 생성합니다.
- POST
/api/v1/debates - Authorization:
Bearer <JWT_TOKEN> - Content-Type:
application/json
요청 본문:
{
"title": "토론 제목",
"description": "토론 설명",
"category": "기술",
"image": "https://example.com/image.jpg",
"cons_title": "반대 측 제목",
"pros_title": "찬성 측 제목",
"start_at": "2025-01-22",
"end_at": "2025-01-23"
}모든 토론을 조회합니다.
- GET
/api/v1/debates
ID로 특정 토론을 조회합니다.
- GET
/api/v1/debates/:id - Authorization:
Bearer <JWT_TOKEN>
토론의 특정 측면에 인사이트를 추가합니다.
- POST
/api/v1/debates/:id/insights - Authorization:
Bearer <JWT_TOKEN> - Content-Type:
application/json
요청 본문:
{
"content": "인사이트 내용",
"debate_side_id": 1,
"argx": 10
}인사이트에 ARGX 토큰으로 투표합니다.
- POST
/api/v1/debates/:id/insights/:insight_id/vote - Authorization:
Bearer <JWT_TOKEN> - Content-Type:
application/json
요청 본문:
{
"insight_id": 1,
"argx": 5
}토론에 댓글을 작성합니다.
- POST
/api/v1/debates/:id/comments - Authorization:
Bearer <JWT_TOKEN> - Content-Type:
application/json
요청 본문:
{
"content": "댓글 내용",
"debate_id": 1
}WebSocket을 통해 특정 토론의 실시간 업데이트를 구독합니다.
- WebSocket
ws://localhost:8000/api/v1/ws/debates/:id
기능:
- 토론 정보 실시간 업데이트
- 인사이트 추가/수정 시 전체 토론 정보 전송
- 투표 및 댓글 작성 시 실시간 반영
사용 예시:
const ws = new WebSocket('ws://localhost:8000/api/v1/ws/debates/1');
ws.onmessage = (event) => {
const debateData = JSON.parse(event.data);
console.log('Debate updated:', debateData);
};argu-x-server/
├── src/ # 소스 코드
│ ├── core/ # 핵심 모듈
│ │ ├── config/ # 설정 관련
│ │ │ ├── database.go # 데이터베이스 연결 설정
│ │ │ └── jwt.go # JWT 토큰 설정
│ │ ├── middleware/ # 미들웨어
│ │ │ └── auth.go # JWT 인증 미들웨어
│ │ └── websocket/ # WebSocket 관리
│ │ └── manager.go # WebSocket 연결 및 브로드캐스트 관리
│ └── v1/ # API 버전 1
│ ├── routes/ # 라우팅
│ │ └── router.go # 라우트 정의
│ ├── debate/ # 토론 모듈
│ │ ├── controller.go # HTTP 핸들러
│ │ ├── service.go # 비즈니스 로직
│ │ ├── repository.go # 데이터 액세스
│ │ ├── model.go # 데이터 모델
│ │ └── dto.go # 데이터 전송 객체
│ └── user/ # 사용자 모듈
│ ├── controller.go # HTTP 핸들러
│ ├── service.go # 비즈니스 로직
│ ├── repository.go # 데이터 액세스
│ ├── model.go # 데이터 모델
│ └── dto.go # 데이터 전송 객체
├── WEBSOCKET_README.md # WebSocket 기능 문서
├── .env # 환경 변수 (예시)
├── .env.local # 로컬 환경 변수
├── .gitignore # Git 제외 파일
├── go.mod # Go 모듈 정의
├── go.sum # 의존성 체크섬
├── main.go # 애플리케이션 진입점
└── README.md # 프로젝트 문서
프로젝트는 Clean Architecture 원칙을 따르며, 다음과 같은 계층으로 구성됩니다:
- Handler/Controller: HTTP 요청/응답 처리
- Service: 비즈니스 로직 처리
- Repository: 데이터 액세스 추상화
- Model: 데이터 구조 정의
-
Core Module: 애플리케이션의 핵심 기능을 담당
config: 데이터베이스, JWT 등 설정middleware: HTTP 미들웨어 (인증 등)websocket: WebSocket 연결 관리 및 실시간 브로드캐스트
-
V1 Module: API 버전 1의 모든 기능
routes: URL 라우팅 정의user: 사용자 관리 모듈debate: 토론 플랫폼 모듈 (ARGX 토큰 시스템 포함)
# Go 버전 확인
go version
# 개발 도구 설치
go install github.com/cosmtrek/air@latest # 핫 리로딩# 환경 변수 설정
export GIN_MODE=debug
export PORT=3000
# 서버 실행
go run main.goair을 사용하여 코드 변경 시 자동으로 서버 재시작:
# air 설정 파일 생성 (.air.toml)
air init
# air로 개발 서버 실행
air- 파일명: 소문자, 언더스코어 사용 (e.g.,
user_controller.go) - 함수명: 카멜케이스 (e.g.,
GetUserByID) - 변수명: 카멜케이스 (e.g.,
userName) - 상수: 대문자, 언더스코어 (e.g.,
MAX_RETRY_COUNT)
// 좋은 예시
if err != nil {
log.Printf("❌ Error occurred: %v", err)
c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal server error"})
return
}// GORM 태그를 활용한 모델 정의
type User struct {
gorm.Model
Name string `json:"name" gorm:"type:varchar(100)"`
Email string `json:"email" gorm:"uniqueIndex;type:varchar(150);not null"`
Password string `json:"-" gorm:"type:varchar(255);not null"`
}GORM의 AutoMigrate 기능을 사용하여 스키마가 자동으로 생성됩니다:
// main.go에서 자동 마이그레이션
if err := config.DB.AutoMigrate(&user.User{}); err != nil {
log.Fatal("❌ Failed to migrate database:", err)
}# 최적화된 바이너리 생성
go build -ldflags "-s -w" -o server main.go
# 실행 파일 권한 설정 (Linux/macOS)
chmod +x server# Dockerfile
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -ldflags "-s -w" -o server main.go
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/server .
COPY --from=builder /app/.env .
CMD ["./server"]# 프로덕션 환경 변수
export GIN_MODE=release
export PORT=8000
export JWT_SECRET=your-production-secret-key
export DATABASE_URL=/data/argux.db서버는 이모지와 함께 구조화된 로깅을 제공합니다:
| 이모지 | 설명 | 사용처 |
|---|---|---|
| 🚀 | 서버 시작/설정 | 서버 부팅, 설정 로드 |
| 🔌 | 데이터베이스 | DB 연결, 마이그레이션 |
| 🌐 | 네트워크/HTTP | HTTP 요청, 응답 |
| ✅ | 성공 | 정상적인 작업 완료 |
| ❌ | 오류 | 에러 발생 |
| 경고 | 주의사항 | |
| 🛑 | 종료 | 서버 종료 |
- Debug: 상세한 디버깅 정보
- Info: 일반적인 정보 메시지
- Warn: 경고 메시지
- Error: 오류 메시지
- 강력한 비밀 키 사용 (32자 이상)
- 토큰 만료 시간 설정
- HTTPS 환경에서만 사용
- bcrypt 해싱 사용
- 최소 8자 이상 복잡한 비밀번호 정책
- 프로덕션에서는
AllowOrigins를 특정 도메인으로 제한 AllowCredentials: true설정 시 보안 주의
.env파일을 Git에서 제외 (.gitignore)- 프로덕션에서는 시스템 환경 변수 사용
# 모든 테스트 실행
go test ./...
# 특정 패키지 테스트
go test ./src/v1/user/...
# 벤치마크 실행
go test -bench=. ./...func TestUserService(t *testing.T) {
// 테스트 코드
}# 서버 상태 확인
curl http://localhost:8000/health
# 응답: {"status": "ok"}# 서버 로그 실시간 확인
tail -f logs/server.log
# 또는 Docker 로그
docker logs -f container_name# 포트 사용 중인 프로세스 확인
lsof -i :8000
# 다른 포트 사용
PORT=3001 go run main.go# 데이터베이스 파일 권한 확인
ls -la argux.db
# 권한 수정
chmod 666 argux.db# 모듈 정리
go mod tidy
# 캐시 정리
go clean -modcache- 브라우저 개발자 도구에서 확인
ALLOWED_ORIGINS환경 변수 설정- 프론트엔드 URL을 허용 도메인에 추가
export GIN_MODE=debug
export LOG_LEVEL=debug
go run main.go프로젝트 발전에 기여하고 싶으시다면:
- Fork 저장소
- Feature 브랜치 생성 (
git checkout -b feature/amazing-feature) - 변경사항 적용
- 테스트 추가
- Pull Request 제출
- 코드 리뷰를 위해 작은 단위로 변경
- 테스트 코드와 함께 제출
- 문서 업데이트
- 기존 코드 스타일 준수
이 프로젝트는 MIT 라이선스 하에 제공됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.
문의사항이나 버그 리포트는 다음 채널을 이용해주세요:
- GitHub Issues: 버그 리포트 및 기능 요청
- Email: project@example.com
- 문서: Wiki
GitHub Actions를 사용하여 자동으로 Docker 이미지를 빌드하고 GitHub Container Registry(GHCR)에 푸시하는 방법입니다.
- GitHub 저장소 설정에서
Settings>Secrets and variables>Actions로 이동 New repository secret을 클릭하여 다음 시크릿을 추가:DOCKERHUB_USERNAME: Docker Hub 사용자명 (Docker Hub 사용 시)DOCKERHUB_TOKEN: Docker Hub 액세스 토큰 (Docker Hub 사용 시)
main브랜치에 푸시하면 자동으로 GitHub Actions가 실행됩니다.- 성공적으로 빌드되면 GitHub Packages에서 이미지를 확인할 수 있습니다.
# GitHub Container Registry에서 이미지 가져오기
docker pull ghcr.io/username/argu-x-server:main
# 컨테이너 실행
docker run -p 8080:8080 ghcr.io/username/argu-x-server:main필요한 환경 변수는 .env 파일을 사용하거나 -e 플래그로 전달할 수 있습니다.
docker run -p 8080:8080 --env-file .env ghcr.io/username/argu-x-server:main- ⚡ 실시간 WebSocket 기능 추가
- 💬 토론 플랫폼 모듈 추가 (찬반 토론, ARGX 토큰 시스템)
- 🌐 WebSocket을 통한 실시간 토론 업데이트
- 📝 WebSocket API 문서화 완료
- 초기 릴리즈
- JWT 인증 시스템
- 사용자 관리 API
- SQLite 데이터베이스
- 문서화 완료
만든이: Argu-X Team 버전: 1.1.0 최종 업데이트: 2025년 1월 22일