fiber (3/3) : MySQL 연결하기

이번에는 fiber 프레임워크에 MySQL 을 붙여서 동작시켜보자. 윈도우에 MySQL 8.4.x 설치하기 을 참고하여 MySQL을 설치하기 바랍니다. 이 과정을 거치면, DB(test_db)를 만들고, 테이블(TB_ADMIN)도 만들고, 샘플 데이터도 넣게 됩니다.

스토어드 프로시저도 하나 만들어보겠습니다.

DELIMITER $$
CREATE PROCEDURE SP_L_ADMIN()
BEGIN
    SELECT ADMIN_NO, LOGIN_ID, PASSWD, NICK, EMAIL FROM TB_ADMIN;
END $$
DELIMITER;

DB에 접속해서 해당 스토어드 프로시져 호출이 잘 되는지도 확인해 봅시다.

CALL SP_L_ADMIN();

여기까지 해서, Database 쪽은 준비가 되었습니다. 이제, fiber 에서 DB 연결부터 조회하는 것까지 해봅시다. ORM 같은 것은 사용하지 않고, 쌩 SQL과 Stored Procedure 를 이용하는 법을 알아봅니다.   MySQL 사용을 위해서 github.com/go-sql-driver/mysql 모듈을 사용하겠습니다.

우선 .env 파일에 DB관련 항목들을 추가해줍니다.

PORT = 8000

TEST_DB_CONFIG__HOST           = localhost
TEST_DB_CONFIG__PORT           = 3306
TEST_DB_CONFIG__DBNAME         = test_db
TEST_DB_CONFIG__USERNAME       = test_user
TEST_DB_CONFIG__PASSWORD       = test123
TEST_DB_CONFIG__MAX_IDLE_CONNS = 10
TEST_DB_CONFIG__MAX_OPEN_CONNS = 10

이제, model 폴더를 만들고, 그 안에 mysql.go 파일을 생성하여 아래와 같이 작성합니다.

package model

import (
	"database/sql"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"

	_ "github.com/go-sql-driver/mysql"
	"github.com/joho/godotenv"
)

var DBConn *sql.DB

func Init() {
	var err error

	// .env 파일 로드
	if err = godotenv.Load(); err != nil {
		log.Fatalf("Error loading .env file: %v", err)
	}

	// 환경 변수에서 DB정보 가져오기
	HOST := os.Getenv("TEST_DB_CONFIG__HOST")
	PORT := os.Getenv("TEST_DB_CONFIG__PORT")
	DBNAME := os.Getenv("TEST_DB_CONFIG__DBNAME")
	USERNAME := os.Getenv("TEST_DB_CONFIG__USERNAME")
	PASSWORD := os.Getenv("TEST_DB_CONFIG__PASSWORD")
	MAX_IDLE_CONNS := os.Getenv("TEST_DB_CONFIG__MAX_IDLE_CONNS")
	MAX_OPEN_CONNS := os.Getenv("TEST_DB_CONFIG__MAX_OPEN_CONNS")

	DSN := USERNAME + ":" + PASSWORD + "@tcp(" + HOST + ":" + PORT + ")/" + DBNAME
	DBConn, _ = sql.Open("mysql", DSN)

	// Connection Pool
	_MAX_IDLE_CONNS, _ := strconv.Atoi(MAX_IDLE_CONNS)
	_MAX_OPEN_CONNS, _ := strconv.Atoi(MAX_OPEN_CONNS)
	DBConn.SetMaxIdleConns(_MAX_IDLE_CONNS)
	DBConn.SetMaxOpenConns(_MAX_OPEN_CONNS)
	DBConn.SetConnMaxLifetime(time.Hour)
}

func GetAdminList() []map[string]interface{} {
	var admin_no int
	var login_id string
	var passwd string
	var nick string
	var email string
	result_slice := []map[string]interface{}{}

	rows, err := DBConn.Query("SELECT ADMIN_NO, LOGIN_ID, PASSWD, NICK, EMAIL FROM TB_ADMIN")
	if err != nil {
		fmt.Println(err)
	}
	if rows != nil {
		defer rows.Close()
	}

	for rows.Next() {
		result_map := map[string]interface{}{}

		err := rows.Scan(&admin_no, &login_id, &passwd, &nick, &email)
		if err != nil {
			fmt.Println(err)
		}

		result_map["ADMIN_NO"] = admin_no
		result_map["LOGIN_ID"] = login_id
		result_map["PASSWD"] = passwd
		result_map["NICK"] = nick
		result_map["EMAIL"] = email
		result_slice = append(result_slice, result_map)
	}

	return result_slice
}

소스에 추가한 mysql 모듈을 설치하기 위해서 go mod tidy를 실행해줍니다.

그리고, main.go 도 DB연결할 수 있도록 수정해줍니다.

package main

import (
	"log"
	"os"

	"github.com/joho/godotenv"

	"fapi/model"
	"fapi/route"
)

func main() {
	// .env 파일 로드
	if err := godotenv.Load(); err != nil {
		log.Fatalf("Error loading .env file: %v", err)
	}

	// 환경 변수에서 포트 가져오기
	port := os.Getenv("PORT")
	if port == "" {
		log.Fatal("PORT is not set in the .env file")
	}

	model.Init()

	app := route.Router()
	log.Fatal(app.Listen("0.0.0.0:" + port))
}

svc1.go 의 Req1 함수도 수정해줍니다.

package svc1

import (
	"fapi/model"

	"github.com/gofiber/fiber/v2"
)

func Req1(c *fiber.Ctx) error {
	result := model.GetAdminList()
	return c.JSON(result)
}

func Req2(c *fiber.Ctx) error {
	return c.JSON(&fiber.Map{"SVC1": "REQ2"})
}

웹브라우저에서 http://localhost:8000/svc1/req1 을 호출하면 DB의 내용을 보여줄 거에요.   이제, Stored Procedure 도 적용해보겠습니다. GetAdminList 함수에서 DBConn.Query 부분을 다음처럼 수정합니다.

// rows, err := DBConn.Query("SELECT ADMIN_NO, LOGIN_ID, PASSWD, NICK, EMAIL FROM TB_ADMIN")
rows, err := DBConn.Query("CALL SP_L_ADMIN()")

그리고, 실행하면, 역시 JSON으로 DB내용이 잘 출력 될 거에요.   여기까지 MySQL DB연결하는 방법을 알아보았습니다. 이 외에 인증이라던가 여러가지 작업들을 각자의 입맛에 맞게 추가해보도록 하면 되겠습니다.

이전최근