Search API 구현 프로젝트
🙈

Search API 구현 프로젝트

Created
May 29, 2024 06:16 AM
Last edited time
Last updated May 31, 2024
Tags
ElasticSearch
Language
docker
Language
GoLang
URL

Intro::

gin gonic, elasticsearch를 활용한 Search API 구현 프로젝트입니다.

초기 설정

  • elasticsearch에 넣을 데이터와 인덱스는 엘라스틱서치 실무 가이드에서 제공하는 스냅샷을 사용하였습니다.

docker-compose.yml

services: es01: image: docker.elastic.co/elasticsearch/elasticsearch:7.8.1 container_name: es01 environment: - cluster.name=javacafe-cluster - node.name=es01 - network.host=0.0.0.0 - http.port=9200 - transport.tcp.port=9300 - cluster.initial_master_nodes=es01 - path.repo=/es/book_backup/search_example - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 volumes: - data01:/usr/share/elasticsearch/data - ./search_example:/es/book_backup/search_example ports: - 9200:9200 - 9300:9300 networks: - elastic kibana: image: docker.elastic.co/kibana/kibana:7.8.1 container_name: kibana restart: always environment: ELASTICSEARCH_HOSTS: http://es01:9200 ports: - 5601:5601 depends_on: - es01 networks: - elastic volumes: data01: driver: local networks: elastic: driver: bridge

데이터 넣어주기

// kibana를 사용해서 elasticsearch에서 스냅샷 복구 // 스냅샷 등록 PUT _snapshot/search_example { "type": "fs", "settings": { "location": "/es/book_backup/search_example", "compress": true } } // 스냅샷 등록 확인 GET _snapshot/search_example/_all // 스냅샷 복구 POST _snapshot/search_example/movie-search/_restore

go.mod

go get -u github.com/gin-gonic/gin# gin gonic 설치 go get github.com/olivere/elastic/v7# olivere/elastic 설치 go get -u golang.org/x/sync/errgroup
 

gin gonic

Gin Gonic은 Go 언어로 작성된 고성능 웹 프레임워크입니다. 주로 RESTful API를 구축하는 데 사용되며, 간결하고 직관적인 API를 제공하여 개발자가 빠르게 웹 애플리케이션을 개발할 수 있도록 돕습니다.

주요 특징

  1. 고성능: Gin Gonic은 HTTP 요청을 빠르게 처리할 수 있도록 최적화되어 있습니다.
  1. 간결한 코드: 최소한의 코드로 웹 서버와 라우트를 설정할 수 있습니다.
  1. 미들웨어 지원: 인증, 로깅, CORS 등 다양한 미들웨어를 쉽게 추가할 수 있습니다.
  1. 라우팅: RESTful 라우팅을 지원하며, 경로 파라미터, 쿼리 스트링 등의 다양한 요청 데이터를 쉽게 처리할 수 있습니다.
  1. JSON 처리: JSON 요청 및 응답 처리가 매우 간편합니다.
  1. 컨텍스트: 요청 수명 주기 동안 상태를 유지하고 공유할 수 있도록 컨텍스트 객체를 제공합니다.

예제 코드

package main import ( "log" "net/http" "github.com/gin-gonic/gin" ) type Album struct { ID string `json:"id" binding:"required"` Title string `json:"title" binding:"required"` Artist string `json:"artist" binding:"required"` Price float64 `json:"price" binding:"required"` } var albums = []Album{ {ID: "1", Title: "Blue Train", Artist: "John Coltrane", Price: 56.99}, {ID: "2", Title: "Jeru", Artist: "Gerry Mulligan", Price: 17.99}, {ID: "3", Title: "Sarah Vaughan and Clifford Brown", Artist: "Sarah Vaughan", Price: 39.99}, } func getAlbums(c *gin.Context) { c.IndentedJSON(http.StatusOK, albums) } func postAlbums(c *gin.Context) { var newAlbum Album if err := c.BindJSON(&newAlbum); err != nil { log.Println(err) c.Status(http.StatusBadRequest) return } log.Println("GOOD~~") albums = append(albums, newAlbum) c.IndentedJSON(http.StatusCreated, newAlbum) } func main() { router := gin.Default() router.GET("/albums", getAlbums) router.POST("/albums", postAlbums) router.Run("localhost:8080") }

olivere/elastic

package elasticconn import ( "context" "log" "time" "github.com/olivere/elastic/v7" ) var ( EsClient *elastic.Client ) func InitEs() { EsClient, _ = elastic.NewClient( elastic.SetURL("http://localhost:9200"), // elasticsearch 서버 설정 & ','으로 다수 등록 가능 elastic.SetSniff(false), // 클러스터 sniffing 비활성화 elastic.SetHealthcheckInterval(10*time.Second), // 클러스터 상태 확인 간격 설정 elastic.SetRetrier(elastic.NewBackoffRetrier(elastic.NewExponentialBackoff(100*time.Millisecond, 10*time.Second)))) // 재시도 전략 if _, err := EsClient.CatHealth().Do(context.TODO()); err != nil { log.Println("ELASTIC CLIENT 연결 실패", err) } else { log.Println("ELASTIC CLIENT 연결 성공!!!") } }
 

Swagger 적용

go get -u github.com/swaggo/swag/cmd/swag go get -u github.com/swaggo/gin-swagger go get -u github.com/swaggo/files
// main.go 파일 설정 import ( ginSwagger "github.com/swaggo/gin-swagger" swaggerFiles "github.com/swaggo/files" _ "searchAPI/cmd/docs"// docs 경로는 상황에 맞게 작성해두면 된다. ) func main() { e := gin.New()// 혹은 gin.Default()로 생성한 Gin 엔진 e.GET("/api/v1/ping", requestPing) setUpSwagger(e) } // @title Swagger SearchAPI // @version 1.0 // @description SearchAPI server. // @license.name Apache 2.0 // @license.url http://www.apache.org/licenses/LICENSE-2.0.html // @host localhost:8080 // @BasePath /api/v1 func setUpSwagger(r *gin.Engine) { r.GET("/", func(c *gin.Context) { c.Redirect(http.StatusFound, "/swagger/index.html") }) r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) } // @Summary request ping // @Description This is detail Description. // @Accept json // @Produce json // @Router /api/v1/ping [get] // @Success 200 {object} string func requestPing(c *gin.Context) { fmt.Println("got ping") c.JSON(200, gin.H{ "message": "pong", }) }
# main.go 파일이 있는 위치 swag init # 만약 main.go 가 루트 위치가 아니라면 swag init -g cmd/main.go # 와 같이 경로 명시 # 서버 실행 go run main.go # swagger 서버 접속 http://localhost:8080 혹은 http://localhost:8080/swagger/index.html

References::

 

Loading Comments...