Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions config/config.dev.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ app:

db:
host: "localhost"
port: 5432
user: "postgres"
password: "postgresadmin"
dbname: "sound_postgres"
port: 3305
user: "root"
password: "root"
dbname: "main_db"
sslmode: "disable"

secure:
Expand Down
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ require (
)

require (
filippo.io/edwards25519 v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-sql-driver/mysql v1.9.3 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -15,6 +17,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
Expand Down
6 changes: 4 additions & 2 deletions internal/cmd/gocore/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/labstack/echo/v4" // 웹 프레임워크 (Spring의 @RestController 같은)
"go.uber.org/fx" // 의존성 주입 (Spring의 @Autowired 같은)

_ "github.com/go-sql-driver/mysql"

// 우리 프로젝트의 패키지들
"github.com/nicewook/gocore/internal/global/config" // 설정 관리
"github.com/nicewook/gocore/internal/global/db" // 데이터베이스 연결
Expand Down Expand Up @@ -93,7 +95,7 @@ func NewLogger(cfg *config.Config) *slog.Logger {
}

func NewDB(lc fx.Lifecycle, cfg *config.Config) *sql.DB {
// 데이터베이스 연결 생성

dbConn, err := db.NewDBConnection(cfg)
if err != nil {
log.Fatalf("DB connection error: %v", err)
Expand All @@ -117,7 +119,7 @@ func RegisterMiddlewares(cfg *config.Config, logger *slog.Logger, e *echo.Echo)
middlewares.RegisterMiddlewares(cfg, logger, e)
}

func RegisterRoutes(e *echo.Echo) {
func RegisterRoutes(e *echo.Echo, db *sql.DB) {
// 헬스체크 엔드포인트
e.GET("/health", func(c echo.Context) error {
return errors.OK(c, map[string]string{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package order
package subscription

import (
"net/http"
Expand Down
14 changes: 14 additions & 0 deletions internal/domain/subscription/subscription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package subscription

import "time"

type Subscription struct {
ID int64 `json:"id"`
UserID int64 `json:"user_id" validate:"required,gt=0"`
URL string `json:"url" validate:"required,url"`
Alias string `json:"alias,omitempty" validate:"omitempty,max=30"`
KeywordFilter string `json:"keyword_filter,omitempty" validate:"omitempty,max=100"`
IsUrgent bool `json:"is_urgent"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}
1 change: 1 addition & 0 deletions internal/domain/subscription/subscriptionHandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package subscription
1 change: 1 addition & 0 deletions internal/domain/subscription/subscriptionUsecase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package subscription
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package product
package summary

import (
"net/http"
Expand Down
14 changes: 14 additions & 0 deletions internal/domain/summary/summary.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package summary

import "time"

// Summary struct는 데이터베이스의 summary 테이블과 매핑되는 엔티티입니다.
type Summary struct {
ID int64 `json:"id"`
SubscriptionID int64 `json:"subscription_id" validate:"required,gt=0"`
Hash string `json:"hash" validate:"required"`
Summary string `json:"summary" validate:"required"`
IsRead bool `json:"is_read"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}
1 change: 1 addition & 0 deletions internal/domain/summary/summaryHandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package summary
1 change: 1 addition & 0 deletions internal/domain/summary/summaryUsecase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package summary
11 changes: 11 additions & 0 deletions internal/domain/user/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package user

import "time"

// User struct는 데이터베이스의 user 테이블과 매핑되는 엔티티입니다.
type User struct {
ID int64 `json:"id"`
Name string `json:"name" validate:"required,max=30"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt *time.Time `json:"updated_at,omitempty"`
}
1 change: 1 addition & 0 deletions internal/domain/user/userHandler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package user
1 change: 1 addition & 0 deletions internal/domain/user/userUsecase.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package user
91 changes: 80 additions & 11 deletions internal/global/db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"
"time"

_ "github.com/lib/pq" // PostgreSQL 드라이버 (사용하지 않지만 import 필요)

"github.com/nicewook/gocore/internal/global/config"
)

Expand All @@ -16,18 +14,17 @@ import (
func NewDBConnection(cfg *config.Config) (*sql.DB, error) {
// DSN(Data Source Name) 생성 - 데이터베이스 연결 문자열
dsn := fmt.Sprintf(
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
cfg.DB.Host, // 데이터베이스 호스트 주소
cfg.DB.Port, // 데이터베이스 포트 번호
cfg.DB.User, // 데이터베이스 사용자명
cfg.DB.Password, // 데이터베이스 비밀번호
cfg.DB.DBName, // 데이터베이스 이름
cfg.DB.SSLMode, // SSL 연결 모드 (disable, require 등)
"%s:%s@tcp(%s:%d)/%s?parseTime=true",
cfg.DB.User,
cfg.DB.Password,
cfg.DB.Host,
cfg.DB.Port,
cfg.DB.DBName,
)

// PostgreSQL 데이터베이스 연결 생성
// mysql 데이터베이스 연결 생성
// sql.Open은 실제 연결을 생성하지 않고 연결 가능한 객체만 반환
db, err := sql.Open("postgres", dsn)
db, err := sql.Open("mysql", dsn)
if err != nil {
return nil, fmt.Errorf("데이터베이스 연결 생성 실패: %w", err)
}
Expand All @@ -37,6 +34,17 @@ func NewDBConnection(cfg *config.Config) (*sql.DB, error) {
db.SetMaxIdleConns(5) // 유휴 상태로 유지할 연결 수: 5개
db.SetConnMaxLifetime(5 * time.Minute) // 연결의 최대 수명: 5분 (5분 후 재연결)

if err := createUserTable(db); err != nil {
return nil, fmt.Errorf("failed to create users table: %w", err)
}

if err := createSubscriptionTable(db); err != nil {
return nil, fmt.Errorf("failed to create subscriptions table: %w", err)
}

if err := createSummaryTable(db); err != nil {
return nil, fmt.Errorf("failed to create summary table: %w", err)
}
// 실제 데이터베이스 연결 테스트
// Ping()을 통해 데이터베이스가 실제로 연결 가능한지 확인
if err := db.Ping(); err != nil {
Expand All @@ -46,3 +54,64 @@ func NewDBConnection(cfg *config.Config) (*sql.DB, error) {
// 연결 성공 시 데이터베이스 객체 반환
return db, nil
}

func createUserTable(db *sql.DB) error {

const query = `
CREATE TABLE IF NOT EXISTS user (
id BIGINT NOT NULL AUTO_INCREMENT,
name VARCHAR(30) NOT NULL,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id)
)
`
if _, err := db.Exec(query); err != nil {
return fmt.Errorf("failed to create User table: %w", err)
}
return nil
}

func createSubscriptionTable(db *sql.DB) error {

const query = `
CREATE TABLE IF NOT EXISTS subscription (
id BIGINT NOT NULL AUTO_INCREMENT,
user_id BIGINT NOT NULL,
url TEXT NOT NULL,
alias VARCHAR(30),
keyword_filter VARCHAR(100),
is_urgent BOOLEAN NOT NULL DEFAULT FALSE,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES user(id) ON DELETE CASCADE
)
`
if _, err := db.Exec(query); err != nil {
return fmt.Errorf("failed to create products table: %w", err)
}
return nil
}

func createSummaryTable(db *sql.DB) error {

const query = `
CREATE TABLE IF NOT EXISTS summary (
id BIGINT NOT NULL AUTO_INCREMENT,
subscription_id BIGINT NOT NULL,
hash TEXT NOT NULL,
summary TEXT NOT NULL,
is_read BOOLEAN NOT NULL DEFAULT FALSE,
created_at DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
updated_at DATETIME(6) DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP(6),
PRIMARY KEY (id),
FOREIGN KEY (subscription_id) REFERENCES subscription(id) ON DELETE CASCADE
)
`

if _, err := db.Exec(query); err != nil {
return fmt.Errorf("failed to create orders table: %w", err)
}
return nil
}