- 로그인을 한 사용자에 따라 노출되는 할 일 목록을 구분해주어야 한다.
- session ID 로 구분하기 때문에 SQLite DB 스키마에도 session ID 를 추가하였다.
- session ID 에 따라 Query 문에 WHERE 절을 사용할 예정이기 때문에 sessionId 를 index로 생성하여(이진검색트리) 빠른 검색이 되도록 한다.
- CREATE INDEX 는 모든 컬럼에 대해 만들 필요는 없다. 오히려 비효율적이기 때문이다. 어떤 컬럼에 대해 INDEX 를 설정해야 효율적이 될 지는 계속 학습해야 한다고 한다.
func newSqliteHandler(filepath string) DBHandler {
database, err := sql.Open("sqlite3", filepath)
if err != nil {
panic(err)
}
statement, _ := database.Prepare(
`CREATE TABLE IF NOT EXISTS todos (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sessionId STRING,
name TEXT,
completed BOOLEAN,
createdAt DATETIME
);
**CREATE INDEX IF NOT EXISTS sessionIdIndex ON todos (
sessionId ASC
);`)**
statement.Exec()
return &sqliteHandler{db: database}
}
- 스키마가 변경되었고, session ID 에 따라서 선택적으로 할 일 목록이 노출되어야 하기 때문에 getTodos() 함수를 변경했다. string 타입의 sessionId 를 인자로 받아 Query 문 WHERE 절에 조건을 추가한 것이다.
func (s *sqliteHandler) GetTodos(sessionId string) []*Todo {
todos := []*Todo{}
rows, err := s.db.Query("SELECT id, name, completed, createdAt FROM todos WHERE sessionId=?", sessionId)
if err != nil {
panic(err)
}
defer rows.Close()
for rows.Next() {
var todo Todo
rows.Scan(&todo.ID, &todo.Name, &todo.Completed, &todo.CreatedAt)
todos = append(todos, &todo)
}
return todos
}
- 마찬가지로 addTodo() 메서드도 sessionId 를 인자로 받아 자료를 저장할 때 세션ID 도 함께 저장되도록 수정했다.
func (s *sqliteHandler) AddTodo(name string, sessionId string) *Todo {
statement, err := s.db.Prepare("INSERT INTO todos (sessionId, name, completed, createdAt) VALUES (?, ?, ?, datetime('now'))")
if err != nil {
panic(err)
}
result, err := statement.Exec(sessionId, name, false)
if err != nil {
panic(err)
}
id, _ := result.LastInsertId()
var todo Todo
todo.ID = int(id)
todo.Name = name
todo.Completed = false
todo.CreatedAt = time.Now()
return &todo
}
- 이제 getTodos() 와 addTodo() 메서드가 받는 인자가 달라지면서, (컴퓨터가 인식하기에는 사실상 완전 다른 메서드가 되었기에) DBHandler 에 정의해준 인터페이스도 변경해야 한다.
type DBHandler interface {
GetTodos(sessionId string) []*Todo
AddTodo(name string, sessionId string) *Todo
RemoveTodo(id int) bool
CompleteTodo(id int, complete bool) bool
Close()
}
- 동시에 DBHandler 를 사용하는 app.go 의 AppHandler 의 메서드도 모두 수정했다.
- getTodoListHandler()나 addTodoHandler() 메서드가 실행된다는 것은 OAuth 로그인이 정상적으로 이루어졌다는 것을 의미한다. 따라서 getSessionID() 를 통해 세션 ID 를 가져와 호출하는 함수의 인자에 맞게 넣어준다.
func (a *AppHandler) getTodoListHandler(w http.ResponseWriter, r *http.Request) {
sessionId := getSessionID(r)
list := a.db.GetTodos(sessionId)
rd.JSON(w, http.StatusOK, list)
}
func (a *AppHandler) addTodoHandler(w http.ResponseWriter, r *http.Request) {
sessionId := getSessionID(r)
name := r.FormValue("name")
todo := a.db.AddTodo(name, sessionId)
rd.JSON(w, http.StatusCreated, todo)
}