REST란?

Representational State Transfer의 약자
자원을 이름(자원의 표현)으로 구분하여 해당 자원의 상태를 주고받는 모든 것을 의미한다.
자원: 문서나 그림, 데이터 등 해당 소프트웨어가 관리하는 모든것을 의미한다.
자원의 표현: 그 자원을 표현하기 위한 이름
ex) DB의 학생 정보가 자원일 때, 'students'를 자원의 표현으로 정한다.
웹 사이트의 이미지,텍스트, DB 내용 등 모든 자원에 고유한 ID인 HTTP URI(Uniform resource Identifier)을 부여하고, HTTP Method(POST, GET, PUT,DELETE)를 통해 해당 자원에 대한 CRUD Operation을 적용하는 것을 의미한다.
REST API란?
Application Programming interface의 약자로 데이터와 기능의 집합을 제공하여 컴퓨터 프로그램간 상호작용을 촉진하며, 서로 정보를 교환 가능 하도록 하는것
REST 기반으로 서비스 API를 구현한 것
RESTful이란?
RESTful은 일반적으로 REST라는 아키텍처를 구현하는 웹 서비스를 나태내기 위해 사용되는 용어이다. REST API를 제공하는 웹 서비스를 "RESTful"하다라고 할 수 있다.
RESTful은 REST를 REST답게 쓰기 위한 방법으로, 누군가가 공식적으로 발표한 것이 아니다. 즉 REST의 원리를 따르는 시스템은 RESTful이란 용어로 지칭된다.
ex) main
package main
import (
"net/http"
"web3/myapp"
)
func main() {
http.ListenAndServe(":3000", myapp.NewHandler())
// 해당 네트워크 주소를 수신한다음 요청을 처리하기 위해 핸들러를 호출
}
ex) myapp
package myapp
import (
"encoding/json"
"fmt"
"net/http"
"strconv"
"time"
"github.com/gorilla/mux"
)
// json형태의 유저 스트럭스
type User struct {
ID int `json:"id"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
}
// 유저 정보를 들고있는 맵
var userMap map[int]*User
var lastID int // user id를 넣을 변수
// / 메인페이지에 출력할 메세지
func indexHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World")
// w에 Hello World 를 집어서 출력
}
// /users에 출력할 메세지
func usersHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Get UserInfo by /users/{id}")
// "Get UserInfo by /users/{id} 출력
}
// 유저 정보를 얻는다.
func getUserInfoHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
// 리퀘스트에 대한 경로 변수가 있는 경우 해당 변수를 반환
id, err := strconv.Atoi(vars["id"])
// string을 int로
if err != nil { // 에러가 났을때
w.WriteHeader(http.StatusBadRequest)
//제공된 http 리스폰스 헤더를 전송한다.
fmt.Fprint(w, err)
return
}
user, ok := userMap[id] // ok는 부울값
if !ok { // ok가 아닐때
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "No User Id:", id)
return
}
w.Header().Add("Content-Type", "application/json")
// WriteHeader에서 보낼 헤더 맵을 반환
// add(key, value) 를 헤더에 추가
w.WriteHeader(http.StatusOK)
data, _ := json.Marshal(user)
// user의 JSON 인코딩 반환
fmt.Fprint(w, string(data))
}
// 실제로 유저를 생성하는 코드
func createUsersHandler(w http.ResponseWriter, r *http.Request) {
user := new(User)
// User타입의 포인터 user 생성
err := json.NewDecoder(r.Body).Decode(user)
// NewDecoder: 바디에서 읽은 새 디코더 반환
// Decode : json 인코딩 값을 user에 저장
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, err)
return
}
// 유저 생성
lastID++ // 유저가 생성될때 마다 증가
user.ID = lastID
user.CreatedAt = time.Now() //현재 시간
userMap[user.ID] = user
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
data, _ := json.Marshal(user)
fmt.Fprint(w, string(data))
}
func deleteUserHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id, err := strconv.Atoi(vars["id"])
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, err)
return
}
_, ok := userMap[id]
if !ok {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "No User ID:", id)
return
}
delete(userMap, id)
// 해당 키를 가진 요소를 맵에서 삭제한다.
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "Deleted User ID:", id)
}
func updateUserHandler(w http.ResponseWriter, r *http.Request) {
updateUser := new(User)
err := json.NewDecoder(r.Body).Decode(updateUser)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprint(w, err)
return
}
//값이 없을때
user, ok := userMap[updateUser.ID]
if !ok {
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "No User ID:", updateUser.ID)
return
}
//빈값이 아닐때
if updateUser.FirstName != "" {
user.FirstName = updateUser.FirstName
}
if updateUser.LastName != "" {
user.LastName = updateUser.LastName
}
if updateUser.Email != "" {
user.Email = updateUser.Email
}
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
data, _ := json.Marshal(user)
fmt.Fprint(w, string(data))
}
// 새로운 핸들러를 만들어주는 핸들러
func NewHandler() http.Handler {
userMap = make(map[int]*User)
// 유저맵 생성
lastID = 0
mux := mux.NewRouter()
// 고릴라 먹스를 이용하여 새 라우터 인스턴스 반환
mux.HandleFunc("/", indexHandler)
mux.HandleFunc("/users", usersHandler).Methods("GET")
//.Methods("메소드")고릴라 먹스 기능
// 메소드에 따라 핸들러가 바껴야됨
// GET 일때 해당 핸들러 사용
mux.HandleFunc("/users", createUsersHandler).Methods("POST")
// POST 일때 해당 핸들러 사용
mux.HandleFunc("/users/{id:[0-9]+}", getUserInfoHandler).Methods("GET")
//{id:[0-9]+} 고릴라 먹스가 자동으로 id를 추출
mux.HandleFunc("/users/{id:[0-9]+}", deleteUserHandler).Methods("DELETE")
// DELETE 매소드를 썻을때 deleteUserHandler 핸들러 사용
mux.HandleFunc("/users", updateUserHandler).Methods("PUT")
// PUT 메소드를 썻을때 업데이트
return mux
}
메인 페이지

/users 페이지

/users/id를 입력했을때

현재 아무 정보도 없음

POST 매서드를 이용해 json형태로 입력 후 send

/users/1 페이지에 표시 되는것을 알 수 있다.

해당 아이디를 입력하고 put 매서드를 이용해 업데이트



해당 아이디를 delete 매서드로 삭제
