이번에는 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연결하는 방법을 알아보았다. 이 외에 인증이라던가 여러가지 작업들을 각자의 입맛에 맞게 추가해보도록 하자.
'Framework (Backend) > Gin' 카테고리의 다른 글
Gin framework (2) : 컨트롤러 확장하기 (0) | 2025.01.01 |
---|---|
Gin framework (1) : 시작해보기 (0) | 2024.12.27 |
댓글