본문 바로가기

Language/Go

[Go] - web programming : postgresSQL연결, CRUD사용해보기

PostgresSQL

- 파일을 csv, 메모리에 계속올려두어 사용하는 것은 한정적이다. db서버를 이용해서 데이터를 접근하고 crud가능한 서버를 만들어 보자.

 

1. PostgresSQL 설치

- url - https://www.enterprisedb.com/downloads/postgres-postgresql-downloads

- 다운 받고 실행은 굉장히 직관적이고 쉬워서 설치과정은 생략한다.

- 글로벌하게 쓸라면 환경변수 설정해 주자. (자동으로 안잡아준다)

[내PC] -> [고급시스템설정] -> [환경변수] -> 시스템 변수에서 변수Path [편집] --> PostgresSQL의 bin 폴더 추가

 

설치확인용 출력

2. Postgres user생성 및 table 생성

-  postgres, db를 쓸라면 기본적으로 user와 user가 사용할 db를 만들어줘야한다.

- -P 옵션으로 비밀번호, -d 옵션으로 db생성을 허가한다. 그리고 createdb로 db생성을 해준다.

- createdb같은경우 --help를 쳐보면 디폴트로 user이름과 같은 db가 생성된다는 것을 알 수 있다.

createuser -P -d [username]
createdb [dbname]

createdb option

3. 테이블 추가 스크립트 작성

- 데이터를 저장할 테이블을 작성하여 setup.sql 파일을 만들고, 만들고 싶은 db에다가 테이블을 추가한다.

- 아래의 명령어를 실행하여 해당 db에 테이블을 생성한다.

psql -U [username] -f [scriptname] -d [dbname]

 

간단한 setup.sql 스크립트

- pgadmin4(gui)를 통해 table이 잘 생성된 것을 확인할 수 있다.

gui로 확인한 table posts의 정보

4. Db 연결하기

- Go에서 초기화 함수 init()을 정의하여 Db에 연결해주는 작업을 진행한다.

- sql.Open 함수에 db 드라이버와 데이터소스를 입력으로 sql.DB 구조체를 리턴 받아와야한다.

- 데이터베이스 드라이버의 경우 각각 DB의 서드 파티 드라이버를 go에 설치하여 가지고 오면 된다.

  https://github.com/golang/go/wiki/SQLDrivers : golang에서 제공하는 서드 파티 드라이버 url이다

  나는 postgres를 사용하니, 아래 명령어로 go에 서드 파티 드라이버를 설치하자

go get "github.com/lib/pq"

- Go는 공식적으로 드라이버를 제공하지 않으며 서드 파티 드라이버들은 sql.driver 패키지에 정의된 인터페이스를 구현한 드라이버를 제공해주는 것

- 데이터베이스 드라이버를 가져올 때 패키지 이름은 밑줄(_)로 설정하여 직접 다루거나 설정하지 않아야한다. (드라이버 코드는 database/sql만을 사용)

 

 

CRUD 사용

 

1. Create

- sql 구문을 작성해주자

- $1, $2에는 실제 값으로 변환해 레코드 생성 시 사용할 수 있다. 또한 db에서 id 열을 반환하도록 하자

statement := "insert into posts (content, author) values ($1, $2) returning id"

- sql.DB의 Prepare 와 QureyRow를 이용하여 db에 레코드를 생성한다.

 *Prepare 함수의 docs 설명

  - Prepare creates a prepared statement for later queries or executions. Multiple queries or executions may be run       concurrently from the returned statement. The caller must call the statement's Close method when the statement     is no longer needed. --> 다중 쿼리나 실행을 위해 어떤 "구문"을 준비해 놓고 있는 것

 *QureyRow 함수의 docs 설명

  - QueryRow executes a prepared query statement with the given arguments. If an error occurs during the                  execution of the statement, that error will be returned by a call to Scan on the returned *Row, which is always          non-nil. If the query selects no rows, the *Row's Scan will return ErrNoRows. Otherwise, the *Row's Scan scans          the first selected row and discards the rest. --> 준비된 쿼리 "구문"을 입력받은 인자로 실행하는 것

 

***전체코드

func (post *Post) Create() (err error) {
	statement := "insert into posts (content, author) values ($1, $2) returning id"
	stmt, err := Db.Prepare(statement)
	if err != nil {
		return
	}
	defer stmt.Close()
	err = stmt.QueryRow(post.Content, post.Author).Scan(&post.Id)
	return
}

 

2. Read

- Db에 id값을 조회해서 생성해준 post객체에 값을 복사

- 여기서는 sql.stmt대신 sql.DB의 QureyRow를 바로 사용하여 scan해 주었다.

func GetPost(id int) (post Post, err error) {
	post = Post{}
	err = Db.QueryRow("select id, content, author from posts where id=$1", id).Scan(&post.Id,
		&post.Content, &post.Author)
	return
}

 

3. Update

- 레코드의 정보를 바꾸고 싶을 때 사용

- 검색한 뒤, 그 값의 데이터를 변경하고, update query를 작성하여 upate를 진행하면 된다.

func (post *Post) Update() (err error) {
	_, err = Db.Exec("update posts set content=$2, author=$3 where id=$1", post.Id, post.Content, post.Author)
	return
}

- GetPost로 검색하고, 객체를 수정하여 Update를 진행해주면 된다.

readPost, _ := GetPost(post.Id)
fmt.Println(readPost)

readPost.Content = "안녕하세요!"
readPost.Author = "창종"
readPost.Update()

 

4. Delete

- update와 마찬가지로 Exec 메소드를 사용하여 delete query를 작성 해주면 된다.

func (post *Post) Delete() (err error) {
	_, err = Db.Exec("delete from posts where id=$1",post.Id)
	return
}

 

 

 

** Nosql 도 찾아봤다.

https://www.mongodb.com/blog/post/mongodb-go-driver-tutorial

공식 문서에서 튜토리얼이 잘 되어있어서 추후에 사용하는데 문제는 없어보인다.

 

CRUD의 작업은 그렇게 어렵지 않았다.. 하지만 시스템이 복잡해지면 query 구문 작성하는 것이 문제일 것 같다는 생각이 들었다. 내 시스템에서의 CRUD를 활용하고 db설계를 잘 생각해 봐야할 것 같다.