똑같은 삽질은 2번 하지 말자
Golang vol.3 본문
개요
고랭 학습하면서 느낀점이나 기록하면 좋을법한 내용들을 정리
1. 더미데이터 만들때 좋은 패키지
go get -u github.com/bxcodec/faker/v3
usage
package main
import (
"ambassador/src/database"
"ambassador/src/models"
"github.com/bxcodec/faker/v3"
)
func main() {
database.Connect()
for i := 0; i < 30; i++ {
ambassador := models.User{
FirstName: faker.FirstName(),
LastName: faker.LastName(),
Email: faker.Email(),
IsAmbassador: true,
}
ambassador.SetPassword("1234")
database.DB.Create(&ambassador)
}
}
2. go의 console log
import (
"log"
)
func Example(c *fiber.Ctx) error {
log.Printf("%v", c)
}
3. model의 공통 column(or field)를 추상화 하는 이하의 방법이 있다.
package models
type Model struct {
Id uint `json:"id"`
}
// product.go
package models
type Product struct {
Model
Title string `json:"title"`
Description string `json:"description"`
Image string `json:"image"`
Price float64 `json:"price"`
}
// user.go
package models
type Product struct {
Model
Title string `json:"title"`
Description string `json:"description"`
Image string `json:"image"`
Price float64 `json:"price"`
}
4. SQL 로그 남기기
LogLevel을 logger.info로 함으로써 모든 sql로그들이 출력되게 된다.
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Info, // Log level slient 1 ~ info 4
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
Colorful: true, // Disable color
},
)
// populate log pre-fields here before set to
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
Logger: newLogger,
})
5. model의 field 메소드 정의할 때 주의할 점
6. JWT에 유저별로 scope 설정하기
ClaimsWithScope라는 구조체를 하나 만들어서 Scope를 가진 Claims(속성정보)를 만들어 준다.
jwt.ParseWithClaims로 쿠키와 구조체 비밀키를 넣으면 로그인할 때 설정한 claim을 얻을 수 있는데,
그 안에 scope도 잘 설정되어 있다.
const SecretKey = "secret"
type ClaimsWithScope struct {
jwt.StandardClaims // 이 안에 있는 요소들이 distructuring 하는것 처럼 풀어서 들어가는것 같다.
Scope string
}
func IsAuthenticated(c *fiber.Ctx) error {
cookie := c.Cookies("jwt")
token, err := jwt.ParseWithClaims(cookie, &ClaimsWithScope{}, func(token *jwt.Token) (interface{}, error) {
return []byte(SecretKey), nil
})
if err != nil || !token.Valid {
c.Status(fiber.StatusUnauthorized)
return c.JSON(fiber.Map{
"message": "unauthorized",
})
}
payload := token.Claims.(*ClaimsWithScope)
IsAmbassador := strings.Contains(c.Path(), "/api/ambassador")
if (payload.Scope == "admin" && IsAmbassador) || (payload.Scope == "ambassador" && !IsAmbassador) {
c.Status(fiber.StatusUnauthorized)
return c.JSON(fiber.Map{
"message": "unauthorized",
})
}
return c.Next()
}
func GenerateJWT(userId uint, scope string) (string, error) {
payload := ClaimsWithScope{}
payload.Subject = strconv.Itoa(int(userId)) // 이거랑 string(user.Id)랑 다른가? 보다
payload.ExpiresAt = time.Now().Add(time.Hour * 24).Unix()
payload.Scope = scope
return jwt.NewWithClaims(jwt.SigningMethodHS256, payload).SignedString([]byte(SecretKey))
}
7. Redis 활용
docker-compose.yml
redis:
image: redis:latest
ports:
- 6379:6379
go에서 Redis를 쉽게 사용할 수 있게하는 패키지
go get github.com/go-redis/redis/v8
usage
상품의 전체 정보를 캐싱해서 들고있게 하는게 목적
func ProductsFrontend(c *fiber.Ctx) error {
var products []models.Product
ctx := context.Background() // 캐시에 필요한 변수
result, err := database.Cache.Get(ctx, "products_frontend").Result()
if err != nil { // 캐싱되어 있지 않을때
fmt.Println(err.Error())
database.DB.Find(&products)
bytes, err := json.Marshal(products) // Marshal로 []byte로 변환
if err != nil {
panic(err)
}
if errKey := database.Cache.Set(ctx, "products_frontend", bytes, 30*time.Minute).Err(); errKey != nil {
panic(errKey)
}
} else {
json.Unmarshal([]byte(result), &products)
}
return c.JSON(products)
}
'Go' 카테고리의 다른 글
Golang vol.5 (0) | 2022.05.05 |
---|---|
Golang vol.1 (Getting Start, := = 차이, 함수) (0) | 2022.04.17 |
Comments