도메인 비즈니스 로직 호출(in) 또는 외부 어댑터(out) 호출 하기 위한 데이터 struct는 pkg에 정의한다.
// 위치 pkg/port/user/model.go
package user
type User struct {
Id string
Pwd string
...
}
type UserDetail struct {
User
CreatedAt time.Time
}
// 위치 pkg/port/user/in.go
package user
type OAuthUserUseCase interface {
SignIn(code, state string) (user *UserDetail, err error)
}
// 위치 pkg/port/user/out.go
package user
type LoadUserPort interface {
GetUser(id string) (*UserDetail, error)
}
type WriteUserPort interface {
Save(user *User) (*UserDetail, error)
}
API 요청, 응답에 대한 데이터 struct는 internal/adapter/{domain}/command에 정의한다.
// 위치 internal/adapter/user/command/model.go
package command
type UserSignInRequest struct {
Id string `json:"id"`
Pwd string `json:"pwd"`
}
// 위치 internal/adapter/user/command/controller.go
package command
var oauthUserService pkguser.OAuthUserUseCase
func UserController(router *gin.Engine, oauthUserUseCase pkguser.OAuthUserUseCase) {
oauthUserService = oauthUserUseCase
userApi := router.Group("/v1/users")
{
userApi.GET("/signin", signIn)
}
}
func signIn(ctx *gin.Context) {
var requestBody UserSignInRequest
if err := ctx.ShouldBindJson(&requestBody); err != nil {
...
}
...
}
Persistence 관련 데이터 struct는 internal/adapter/{domain}/persistence에 정의한다.
// 위치 internal/adapter/user/persistence/model.go
package persistence
type UserEntity struct {
Id string `gorm:"id"`
Pwd string `gorm:"pwd"`
...
CreatedAt time.Time `gorm:"created_at"`
}
func (u *UserEntity) ToUserDetail() *pkguser.UserDetail {
return &pkguser.UserDetail {
User: {
Id: u.Id,
Pwd: u.Pwd,
...
},
CreatedAt: u.CreatedAt,
}
}
// 위치 internal/adapter/user/persistence/repository.go
package persistence
type rdbRepository struct {
Db *gorm.DB
}
func NewRdbRepository(Db *gorm.DB) *rdbRepository {
return &rdbRepository {
Db: Db,
}
}
Domain 관련 데이터 struct는 internal/domain/{domain}에 정의한다.
// 위치 internal/domain/user/model.go
package user
type User struct {
Id string
Pwd string
...
CreatedAt time.Time
}
...User 관련 Functions...
pkg를 제외한 각 model.go에 정의된 데이터 struct에서는 pkg데이터 struct로 mapping 해주는 매퍼를 만들어서 관리하면 편리하다.
pkg데이터 struct에서 변경이 발생하는 경우 관련매퍼들만 수정해주면 된다.
domain struct에 변경이 발생하더라도 다른 영역에 영향을 주지 않는다. (=정책 변경에 자유롭다.)