don't stop believing

Perfect + Mustache 기본 사용해 보기 본문

Swift/Perfect

Perfect + Mustache 기본 사용해 보기

Tongchun 2017. 9. 15. 17:12

Front-End에서 사용할 page를 만들어 봅시다. mustache를 이용합니다.


적당한 곳에 프로젝트 폴더를 만들어 줍니다. 저는 nGleServer010이라고 만들었습니다.

여기에 swift package 초기화 해주고 Package.swift파일을 열어 dependencies를 추가해 줍니다.

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

dependencies에는 Perfect-HTTPServer.git과 Perfect-Mustache.git을 추가합니다.

import PackageDescription

let package = Package(
    name: "nGleServer010",
    targets: [],
    dependencies: [
        .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", majorVersion: 2),
        .Package(url: "https://github.com/PerfectlySoft/Perfect-Mustache.git", majorVersion: 2),
        ]
)

빌드를 한번 해줍니다.

$ swift build

그리고 documentroot로 사용할 webroot 폴더를 만들어 줍니다. webroot폴더는 프로젝트 경로의 최상단에 위치합니다.

webroot 안에는 words.mustache라고 파일을 만들어 줍니다.

다시 프로젝트 상단으로 이동해 xcode 프로젝트 파일을 만들어 줍니다.

xcode 프로젝트 파일이 생성되었으면 xCode로 프로젝트를 열어 줍니다.

$ mkdir webroot
$ cd webroot/
$ touch words.mustache
$ cd ..
$ swift package generate-xcodeproj
$ open nGleServer010.xcodeproj/

perfect가 재대로 설치되었는지 .get Method로 받아서 띄워봅시다.

아래 코드처럼 서버를 작성합니다.

import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import PerfectMustache

let server = HTTPServer()
server.serverPort = 8080
server.documentRoot = "webroot"

var routes = Routes()

func rootHello(request: HTTPRequest, response: HTTPResponse) {
    response.setBody(string: "Hello, tongchun, here is root.")
    .completed()

}

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

server.addRoutes(routes)

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

build 후 브라우저에서 Hello, tongchun, here is root.라고 나오는지 확인해 봅시다.

$ swift build
$ .build/debug/nGleServer010

메시지가 정상적으로 출력되었다면 이제 Mustache를 작성해 봅시다.


xCode에서 words.mustach 파일을 열고 파일 SyntaxColor를 html로 변경해 줍니다.

xCode (상단 메뉴) > Editor > Syntax Coloring > html

그리고 기본 html문을 작성해 줍니다.

이제 main.swift파일을 수정해 서버를 설정해 줍니다.

먼저 MustachePageHandler를 이용해 구조체를 만들어 줍니다.

struct MustacheHelper: MustachePageHandler {
    var values: MustacheEvaluationContext.MapType

    func extendValuesForResponse(context contxt: MustacheWebEvaluationContext, collector: MustacheEvaluationOutputCollector) {
        contxt.extendValues(with: values)
        do {
            try contxt.requestCompleted(withCollector: collector)
        } catch {
            let response = contxt.webResponse
            response.appendBody(string: "\(error)")
                .completed(status: .internalServerError)
        }
    }
}

request와 response를 받아 mustache를 호출하는 함수를 만들어 보겠습니다. 함수명은 wordMustache로 하겠습니다. 

함수를 만들면 routes.add 합니다.

func wordsMustache(request: HTTPRequest, response: HTTPResponse) {
    var values = MustacheEvaluationContext.MapType()
    mustacheRequest(request: request, response: response, handler: MustacheHelper(values: values), templatePath: request.documentRoot + "/words.mustache")
}

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

참고로 routes.add는 server.addRoutes(routes)보다 상단에 위치해야 합니다.

이제 빌드하고 브라우저에서 호출해 봅시다. http://localhost:8080/word


fileError(2, "No such file or directory /Users/ngle/Documents/JakeWork/nGleServer010/.build/checkouts/PerfectLib.git-3712999737848873669/Sources/PerfectLib/File.swift open(_:permissions:) 244")

만약 브라우저에서 호출할 때 위와 같은 에러가 나온다면 mustacheRequest의 templatePath가 정확한지 확인해 봅니다.

저는 templatePath: request.documentRoot + "/words.mustache" 에서 "/"이 빠져있어 에러가 발생했습니다.


mustache 파일에 데이터를 할당해 보겠습니다.

먼저 main.swift에 wordsMustache 라고 함수를 만들고 MustacheEvaluationContext.MapType() 타입으로 만든 values변수에 데이터를 넣습니다.


func words01Mustache(request: HTTPRequest, response: HTTPResponse) {
    var values = MustacheEvaluationContext.MapType()
    values["word"] = "asset"
    values["korean"] = "[^에셋t]\n자산(이 되는 사람, 물건)\n(특히 부동산과 같은) 자산, 재산"
    values["means"] = "Something or someone that is an asset is considered useful or helps a person or organization to be successful.\nThe assets of a company or a person are all the things that they own."
    mustacheRequest(request: request, response: response, handler: MustacheHelper(values: values), templatePath: request.documentRoot + "/words01.mustache")
}

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

저는 영어 단어를 넣었습니다.

그리고 words01이라는 mustache파일을 만들고 아래와 같이 html코드를 추가합니다.

<!DOCTYPE html>
<html>
    <head>
        <title>mustache: words sample</title>
    </head>
    <body>
        <h1>{{word}}</h1></br>
        <h3>{{korean}}</h3></br>
        <h3>{{means}}</h3></br>
    </body>
</html>

브라우저에 http://localhost:8080/words01을 호출하면 아래와 같이 출력됩니다.

계시판의 리스트 같이 특정 데이터가 반복되는 경우는 아래와 같이 작성합니다.

func words02Mustache(request: HTTPRequest, response: HTTPResponse) {
    var values = MustacheEvaluationContext.MapType()
    values["words"] = [
        ["word": "flexibility",
         "korean": "[플^뤡서빌리디]\n융통성, 신축성",
         "means": "I also registered for yoga classes..."],
        ["word": "flexible",
         "korean": "[플^뤡서블]\n구부릴 수 있는, 유연한, 적응성",
         "means": "A flexible object or material can be ..."],
        ["word": "flick",
         "korean": "[플^뤽k]\n(손가락 등으로) 튀기다, 털다, ",
         "menas": "If something flicks in a particular direction, or ..."]
    ]
    mustacheRequest(request: request, response: response, handler: MustacheHelper(values: values), templatePath: request.documentRoot + "/words02.mustache")
}

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

mustache파일에서 반복은 {{#<key>}} ... {{/<key>}} 로 작성합니다.

<!DOCTYPE html>
<html>
<head>
<title>mustache: words sample</title>
</head>
<body>
    {{#words}}
    <h1>{{word}}</h1>
    <h3>{{korean}}</h3>
    <h3>{{means}}</h3>
    {{/words}}
</body>
</html>

브라우저에서 호출하면 아래와 같이 됩니다.

DB에서 불러오는 데이터가 없을 경우에는 {{^<key>}} ... {{/<key>}} 로 작성해 주면 됩니다.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
<title>mustache: words sample</title>
</head>
<body>
    {{#words}}
    <h1>{{word}}</h1>
    <h3>{{korean}}</h3>
    <h3>{{means}}</h3>
    {{/words}}

    {{^words}}
    <h1>데이터가 없습니다.</h1>
    {{/words}}
</body>
</html>

main.swift파일에서 words02Mustache() 함수의 values 값을 values["words"] = []로 수정 후 브라우저를 호출하면 아래와 같이 데이터가 없다고 노출된다.

마지막으로 mustache에서 html파일을 분리해 보겠습니다.

html 코딩이 많거나 header와 footer 처럼 고정적으로 사용되는 부분이라면 분리해서 만들수 있고 include 할 수 있습니다.

mustache의 include는 {{><파일명>}}로 할수 있습니다.

html파일에서 body 테그를 중심으로 상단과 하단으로 구분한다면 각 mustache파일을 만들고 {{><파일명>}}로 추가할 수 있습니다.

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>mustache: words sample</title> </head> <body>

위 코드처럼 header.mustache 파일을 만들고, 아래 코드처럼 footer.mustache파일을 만듭니다.

    </body>
</html>

그리고 {{>header}} 와 {{>footer}}로 추가할 수 있습니다.

{{>header}}
    {{#words}}
    <h1>{{word}}</h1>
    <h3>{{korean}}</h3>
    <h3>{{means}}</h3>
    {{/words}}

    {{^words}}
    <h1>데이터가 없습니다.</h1>
    {{/words}}
{{>footer}}


이상 Perfect에서 Mustache 기본 사용법이었습니다.


Comments