안녕하세요 후르륵짭잡 입니다!
이번에는 Vapor를 이용해서 PostgreSQL에 저장, 수정, 삭제, 읽기를 구현할 것 입니다.
일단,,,, Vapor에 대한 자세한 설명이 없어서,,, 정말 고생 많이 했습니다.
Vapor에도 고차함수가 있는데,,, 기본적인 쓰임은 비슷하나,,,, 용도의 정확한 의미를 몰라서,,, 많이 헤맸습니다.
나중에 Vapor에 익숙해지면 깊게 다시 다뤄볼 생각 입니다.
(주의 사항 : 시행착오를 기록한 내용이니, 두서가 별로 없고 자세한 내용은 기대하지 마세요 ㅎㅎㅎㅎㅎ)
** Model 생성 **
import Foundation
import Vapor
import FluentSQLiteDriver
final class user : Model, Content {
static let schema : String = "user"
@ID(key: .id)
var id : UUID?
@Field(key: "status")
var status: String
init(){}
init(id : UUID? = nil , status : String){
self.id = id
self.status = status
}
}
일단 기본적인 Model을 생성해주세요!
Model은 데이터 페이스랑 Xcode를 연결하는 역할을 한다고 생각하면 됩니다.
따라서 CRUD를 구현할 때, 반드시 필요합니다.
** Migration 생성 **
import Foundation
import Fluent
import FluentPostgresDriver
struct CreateUserModel : Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
database.schema("user")
.id()
.field("status", .string)
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
database.schema("user").delete()
}
}
Migraion은 테이블 생성이라 생각하면 됩니다.
schema에 해당하는 이름으로 테이블을 만들고 field를 그 구성요소를 만들게 됩니다.
따라서 Model에도 Field를 만드는데, Model에서 만든 Field는 데이터 베이스와 연결을 위한 용이고
Migraion은 초기 생성에 사용된다 생각하면 됩니다.
( 하지만, 다른 블로거들을 본다면 Migraion에 굉장히 많은 코드가 들어가는데, 그 부분에 대해서 쫌 더 알 필요가 있을 것 같습니다.
추후 공부해서 올리도록 하겠습니다. )
** READ 구현 **
자료가 별로 없어서 고생좀 했습니다 ㅎㅎㅎㅎ
일단 READ 구현에는 두가지 방법이 있습니다.
UUID로 찾는 방법
특정 Field로 찾는 방법
이 두가지를 모두 다뤄보도록 하겠습니다.
ID 값으로 찾는 방법 :
import Vapor
import Leaf
import Fluent
func routes(_ app: Application) throws {
//UUID로 찾기
app.get("find",":id"){ req -> EventLoopFuture<user> in
let id = req.parameters.get("id" , as : UUID.self)
let test = user.find(id, on: req.db)
let temp = test.unwrap(or: Abort(.notFound)).map({ (result) -> user in
return result
})
return temp
}
}
id로 찾는 방식은 위 Model에서 id를 자동으로 생성하도록 했습니다.
만약 이 id 값을 알고 있다면, localhost:8080/find/<ID>값으로 보내줘서
req.parameters.get(id)를 적으면 UUID에 해당 값이 있는지 확인하고 존재한다면
id를 반환하고 없다면 nil을 반환하게 됩니다.
그리고 이 값을 Model.find(<UUID 형식의 ID>, on : request.db) 이렇게 작성 해줍니다.
request.db는 Vapor DOC에 적혀 있기를,,,
The easiest way to connect to your database is simply using the incoming Request. This will use the model's defaultDatabase property to automatically fetch a pooled connection to the database.
데이터베이스에 연결하는 가장 쉬운 방법은 들어오는 요청을 사용하는 것입니다. 모델의 defaultDatabase 속성을 사용하여 데이터베이스에 대한 풀링 된 연결을 자동으로 가져옵니다.
이렇게 적혀 있습니다.
즉, 그냥 request.db 해주면 현재 Model의 schema와 일치하는 DB를 찾아서 연결 시켜주는 것 같습니다.
(아직 완벽하게 이해 한 것이 아니라 ㅠㅠ 부족한 점이 많아 죄송합니다)
자 여기 까지가,,, 이제 찾는 거 였습니다.
이제 그 값이 존재 할수도 있고 없을 수도 있습니다.
(test 값을 보면 EventLoopFuture<user?> 로 되어 있습니다. 옵셔널 타입인데,, 일반적인 옵셔널 타입이 아닙니다 ㅎㅎㅎㅎ)
따라서 unwrap(or: Abort(.notFound)) 를 해줍니다.
(unwrap는 Enum의 ERROR 타입을 해결해주는 방식으로 여러 타입이 있습니다.)
그리고 젤 중요한 map으로 모든 요소를 탐색해줍니다.
operations performed in map should not block, or they will block the entire event loop. map is intended for use when you have a data-driven function that performs a simple data transformation that cannot error.
내용을 보시면 "no Block, entire evnet loop , performs a simple data transformation that cannot error"로 적혀 있는 것으로 보아
오류가 발생하지 않는 데이터의 반복문으로 생각 할 수 있을 것 같습니다.
이렇게 하고 map의 Return 값으로 Model을 넣어주면 됩니다!
특정 Field 값으로 찾기 :
//UUID 없이 찾기
app.get("findItem"){ req -> EventLoopFuture<user> in
let test = user.query(on: req.db).filter(\.$status == "test").first().unwrap(or: Abort(.notFound)).map { (result) -> user in
return result
}
return test
}
위에서는 URI에 localhost:8080/find/<ID> 값을 넣어줘서 보내줬지만,
일반적으로 사용할 때는 Field 값을 사용합니다.
그래서 query문을 사용해서 탐색을 합니다!
Xcode와 데이터 베이스 연결은 Model에서 합니다.
따라서 Model의 내부 함수인 query를 사용합니다.
(이때 반드시 필요한것이 import Fluent를 잊지 말아야합니다!)
그리고 filter를 사용합니다!!
그런데,, 우리가 일반적으로 사용하는 filter라 사용법이 다릅니다 ㅎㅎㅎㅎ
(\.$값 == "값")
이런씩의 표기법을 사용합니다!
어쨋든,, ㅋㅋ 이렇게 filter를 해주고 first()로 첫번 째 요소가 있는지 탐색하고 map으로 반환해줍니다!
(갑자기 Multiple 데이터에는 어떻게 반환 할 수 있을지 의구심이 드네요,,,,)
** Multiple Data 받아오기 **
app.get("getMutiple"){ req -> EventLoopFuture<[user]> in
return user.query(on: req.db).filter(\.$status == "test").all()
}
위에서 많은 기술에 대해 배웠습니다.
Multiple 데이터를 쿼리로 부터 가져오기 위해서는 위에 처럼
fileter를 해주시고 all() 를 사용해서 가져오면 됩니다!
다음에는 Update & Save & Delete에 대해 연구 해보도록 하겠습니다!
참고사이트 :
docs.vapor.codes/4.0/fluent/query/
docs.vapor.codes/3.0/fluent/querying/
theswiftdev.com/get-started-with-the-fluent-orm-framework-in-vapor-4/
theswiftdev.com/a-generic-crud-solution-for-vapor-4/
stackoverflow.com/questions/59108951/vapor-filters-are-ambiguous-in-context
github.com/vapor/fluent-kit/releases/tag/1.0.0-beta.5
'Server > Vapor - ServerSide' 카테고리의 다른 글
Vapor) Heroku와 Postgresql을 적용해보자 (0) | 2020.10.26 |
---|---|
Vapor) Heroku를 사용해서 웹 사이트를 만들어보자 (0) | 2020.10.26 |
Vapor ) Postgresql을 사용해서 DataBase를 구축하자! (0) | 2020.10.13 |
Vapor ) Vapor와 Leaf로 웹 사이트를 만들어보자 2부 (1) | 2020.10.12 |
Vapor ) Vapor와 Leaf로 웹 사이트 만들어보자 1부 (0) | 2020.10.12 |
댓글