don't stop believing

Perfect + StORM + PostgreSQL 데이터 처리하기 1 본문

Swift/Perfect

Perfect + StORM + PostgreSQL 데이터 처리하기 1

Tongchun 2017. 9. 28. 18:21

Perfect로 DB에 접속해 데이터를 처리해 보겠습니다.

DB로는 PostgreSQL을 사용할 겁니다. 우선 Postgres에 Words라는 테이블을 만들어 영어단어를 넣어 놨습니다.

테이블 구조는 아래와 같습니다.

# \d words
                                    Table "public.words"
 Column  |          Type          |                        Modifiers                        
---------+------------------------+---------------------------------------------------------
 equipid | integer                | not null default nextval('words_equipid_seq'::regclass)
 word    | character varying(50)  | not null
 means   | character varying(250) | not null
 example | text                   | 
Indexes:
    "words_pkey" PRIMARY KEY, btree (equipid)

equipid는 자동 증가하는 Int 데이터로 Primary key입니다.


*** PostgresStORM를 package에 추가해 빌드하기 위해서는 libxml2 libpq 설치가 필요합니다. ***

Mac에서는 brew를 이용해 설치합니다.

brew install libxml2 libpq

Ubuntu라면 apt-get을 이용해 설치합니다.

sudo apt-get install libxml2 libpq-dev


이제 Perfect 기본 구조를 만들어 봅시다.

nGleServer013이라고 프로젝트 폴더를 만들고 swift package 초기화를 합니다.

$ mkdir nGleServer013
$ cd nGleServer013
$ swift package init --type executable
$ open Package.swift

Package.swift파일을 열고 dependencies를 추가해 줍니다.

import PackageDescription

let package = Package(
    name: "nGleServer013",
    dependencies: [
        .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2),
        .Package(url: "https://github.com/SwiftORM/Postgres-StORM", majorVersion: 1)
    ]
)

Package.swift파일을 저장하고 빌드를 해줍니다.

$ swift build

words 테이블 데이터를 처리할 swift파일을 Source안에다 하나 만들어 줍니다.

xcodeproj변환 후 xcode로 열어봅니다.

$ touch Source/words.swift
$ swift package generate-xcodeproj
$ open nGleServer013.xcodeproj/

이제 words 데이터 모델을 위한 class를 만들어 보겠습니다. word.swift파일을 열고 Words 클레스를 만들어 줍니다. 이때 PostgresStORM을 상속받습니다.

그리고 PostgreSQL의 Words 테이블에 해당하는 column 데이터를 변수로 선언합니다.

주의해야 할 부분은 primary key에 해당하는 column을 가장 처음에 정의되어야 합니다.

import StORM
import PostgresStORM

class Words: PostgresStORM {

    var equipid: Int = 0
    var word: String = ""
    var means: String = ""
    var example: String = ""
   
}

Words 클레스 안에 아래와 같이 table() 함수를 추가합니다.

return 되는 값은 실제 Postgres의 테이블 이름이어야 합니다.

override open func table() -> String {
    return "words"
}

Words 테이블의 데이터를 저장하기 위해 to() 함수를 추가합니다.

override func to(_ this: StORMRow) {
    equipid = this.data["equipid"] as? Int ?? 0
    word = this.data["word"] as? String ?? ""
    means = this.data["means"] as? String ?? ""
    example = this.data["example"] as? String ?? ""
}

Postgres에서 데이터를 불러 row단위로 저장할 함수를 만들어 줍니다.

func rows() -> [Words] {
    var rows = [Words]()
    for i in 0..<self.results.rows.count {
        let row = Words()
        row.to(self.results.rows[i])
        rows.append(row)
    }
    return rows
}

마지막으로 데이터를 Dictionary 형태로 반환할 함수를 만들어 줍니다.

func asDictionary() -> [String: String] {
    return [
        "word": self.word,
        "means": self.means,
        "example": self.example
    ]
}

여기까지 데이터 모델링에 대한 swift 파일이었습니다.

이제 main.swift에서 perfect 기본 구조를 잡아주고 데이터를 호출해 보겠습니다.

아래와 같이 perfect 기본 구조를 잡아 줍니다.

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer

let server = HTTPServer()
server.serverPort = 8080

var routes = Routes()

func testWord(request: HTTPRequest, response: HTTPResponse) {
    do {
        response.setBody(string: "Let's learn how to use PostgresStORM.")
        .completed()

    } catch {
        response.setBody(string: "Error handling request: \(error)")
            .completed(status: .internalServerError)
    }
}

routes.add(method: .get, uri: "/", handler: testWord)

server.addRoutes(routes)

do {
    try server.start()
} catch PerfectError.networkError(let err, let msg) {
    print("Network error thrown: \(err) \(msg)")
}

지금까지 문제가 없는지 빌드 후 서버를 실행해 봅니다.

$ swift build
$ .build/debug/nGleServer013

브라우저를 열고 http://localhost:8080을 호출하면 Let's learn how to use PostgresStORM.이 출력되는 것을 확인할 수 있습니다.

이제 main.swift 파일에 PostgresStORM을 import하고 데이터를 불러와 봅시다.

import StORM
import PostgresStORM

postgresql과 연결은 PostgresConnector로 합니다.

postgresql 서버는 192.168.0.6이고 username과 password, 그리고 database를 지정합니다.

postgresql의 기본 포트는 5432입니다.

PostgresConnector.host = "192.168.0.6"
PostgresConnector.username = "tongchun"
PostgresConnector.password = "tongchun"
PostgresConnector.database = "tongchun"
PostgresConnector.port = 5432

words.swift에 정의한 Words 클래스를 초기화 합니다. .setup()을 호출해 테이블을 만들어 줍니다.

let setupObj = Words()
try? setupObj.setup()

이제 DB의 모든 데이터를 호출해 json형태로 response하는 함수를 하나 만들어 봅시다.

getObj라는 상수를 만들고 Words 클래스를 초기화 합니다.

getObj에 .findAll() 함수로 Words 클래스에서 정의한 데이터를 모두 불러 옵니다.

그런 다음 for 문으로 getObj에 있는 모든 데이터를 wordDic에 추가합니다.

func allWord(request: HTTPRequest, response: HTTPResponse) {
    do {
        // get all words data
        let getObj = Words()
        try getObj.findAll()
        var wordDic: [[String: String]] = []

        for row in getObj.rows() {
            wordDic.append(row.asDictionary())
        }

        try response.setBody(json: wordDic)
            .setHeader(.contentType, value: "application/json")
            .completed()

    } catch {
        response.setBody(string: "Error handling request: \(error)")
            .completed(status: .internalServerError)
    }
}

라우터에 경로를 추가하고 allWord를 추가해 봅니다.

routes.add(method: .get, uri: "/allData", handler: allWord)

이제 빌드하고 서버를 실행해 줍니다. 그다음 브라우저에서 http://localhost:8080/allData를 호출해 봅니다.

DB의 모든 데이터가 브라우저에 출력된다면 성공입니다.






Comments