Framework (Backend)/Gin

Gin framework (3) : MySQL 연결하기

가우리언 2025. 1. 3.
728x90
반응형

 

 

이번에는 Gin 프레임워크에 MySQL 을 붙여서 동작시켜보자. https://gauryan.tistory.com/241 을 참고하여 MySQL을 설치하기 바랍니다.

이제, mysql 을 이용해서 DB 서버에 접속해보자. mysql -u root -p 라고 입력하고, 비밀번호(test123)까지 입력해보자.

일단 새로운 User를 하나 생성해봅시다.

-- CREATE USER '아이디'@'%' IDENTIFIED BY '비밀번호';
CREATE USER 'test_user'@'%' IDENTIFIED BY 'test123';

자... 그러면... 이제 Database 를 생성해봅시다.

-- CREATE DATABASE 디비이름;
CREATE DATABASE test_db;

test_user 가 test_db 를 사용할 수 있도록 권한을 설정해보자.

-- GRANT ALL PRIVILEGES ON 디비이름.* to 사용자@'%';
GRANT ALL PRIVILEGES ON test_db.* to test_user@'%';

일단 exit 로 mysql 을 빠져나온다. mysql에 test_user로 test_db에 재접속해봅니다.

테스트용으로 테이블을 생성해봅시다.

CREATE TABLE TB_ADMIN
(
    ADMIN_NO INT AUTO_INCREMENT NOT NULL,
    LOGIN_ID VARCHAR(20) NOT NULL UNIQUE,
    PASSWD VARCHAR(20) NOT NULL,
    NICK VARCHAR(20) NOT NULL,
    EMAIL VARCHAR(40),
    PRIMARY KEY (ADMIN_NO)
);

테스용 데이터를 2개 넣어보겠습니다.

INSERT INTO TB_ADMIN(LOGIN_ID, PASSWD, NICK, EMAIL)
VALUES('honggildong', 'ajtwlddl', '홍길동', 'hgd@gmail.com');
 
INSERT INTO TB_ADMIN(LOGIN_ID, PASSWD, NICK, EMAIL)
VALUES('jangnara', 'dlQmsdl', '장나라', 'jnr@gmail.com');

스토어드 프로시저도 하나 만들어봅시다.

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

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

여기까지 해서, Database 쪽은 준비가 되었습니다. 이제, Gin 에서 DB 연결부터 조회하는 것까지 해봅시다. ORM 같은 것은 사용하지 않고, 쌩 SQL과 Stored Procedure 를 이용하는 법을 알아봅니다.

 

MySQL 사용을 위해서 github.com/go-sql-driver/mysql 모듈을 사용하겠습니다. go get -u 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, err = 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() string {
	var login_id string
	var passwd string
	var nick string
	var email string
	result_str := ""

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

	for rows.Next() {
		err := rows.Scan(&login_id, &passwd, &nick, &email)
		if err != nil {
			fmt.Println(err)
		}
		result_str += "(" + login_id + "," + passwd + "," + nick + "," + email + ")\n"
	}

	return result_str
}

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

package main

import (
	"log"
	"os"

	"github.com/joho/godotenv"

	"gapi/model"
	"gapi/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() // DB연결

	app := route.Router()
	app.Run("0.0.0.0:" + port)
}

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

package svc1

import (
	"gapi/model"

	"github.com/gin-gonic/gin"
)

func Req1(c *gin.Context) {
	result := model.GetAdminList()
	c.String(200, result)
}

func Req2(c *gin.Context) {
	c.JSON(200, gin.H{
		"SVC1": "REQ2",
	})
}

 

이제, 웹브라우저에서 http://localhost:8000/svc1/req1 을 호출하면 DB의 내용을 보여줄 거에요.

이 출력을 JSON 으로 바꾸어볼까요? 좀 무식하게~~~ GetAdminList() 함수를 아래와 같이 수정한다.

func GetAdminList() string {
	var login_id string
	var passwd string
	var nick string
	var email string
	result_str := "["

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

	cnt := 0
	for rows.Next() {
		if cnt == 0 {
			result_str += "{"
		} else {
			result_str += ",{"
		}
		err := rows.Scan(&login_id, &passwd, &nick, &email)
		if err != nil {
			fmt.Println(err)
		}
		result_str += `"LOGIN_ID": "` + login_id + `", "PASSWD": "` + passwd + `", "NICK": "` + nick + `", "EMAIL": "` + email + `"}`
		cnt += 1
	}
	result_str += "]"

	return result_str
}

 

그리고, svc1.go 의 Req1함수를 아래와 같이 수정한다.

func Req1(c *gin.Context) {
	result := model.GetAdminList()
	c.Header("Content-Type", "application/json; charset=utf-8")
	c.String(200, result)
}

그러면, 결과는 아래와 같다. 좀더 쌈빡하게 JSON 으로 변환하면 좋았겠지만, 일단 이정도에 만족하자.

 

이제, Stored Procedure 도 적용해보자. GetAdminList 함수에서 DBConn.Query 부분을 다음처럼 수정한다.

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

그리고, 실행하면, 역시 JSON으로 DB내용이 잘 출력 될 것이다.

 

 

여기까지 MySQL DB연결하는 방법을 알아보았다. 이 외에 인증이라던가 여러가지 작업들을 각자의 입맛에 맞게 추가해보도록 하자.

728x90
반응형

'Framework (Backend) > Gin' 카테고리의 다른 글

Gin framework (2) : 컨트롤러 확장하기  (0) 2025.01.01
Gin framework (1) : 시작해보기  (0) 2024.12.27

댓글