SWIFT로 만든
SERVER FRAMEWORK 개발기
발표자 소개
이요섭
호서대학교
컴퓨터공학과
장태환
한국기술교육대
메카트로닉스(4)
CONTENTS
1. TREVI란?
• 무엇인가?
• Lime이란?
• 왜 만들었지?
• 어떻게 시작했을까
2. 한계점
• 확장의 한계
3. 웹어플리케이션 이해하기
• 코드에게 물어보기
• 망설이지말고 돌려보기
• 배운것을 반영하기
• 성장한점
4. 시스템모듈 이해하기
• 시스템 라이브러리 적용하기
• 상위언어에서 c 모듈 사용시 문제점
• 코드에게 배우고 반영하기
• 성장한점
5. 앞으로의 방향
TREVI란?
TREVI & LIME
Trevi란 무엇인가?
Trevi는
Swift로 만들어진
서버 프레임워크입니다.
Node.js와 비슷한 방식으로 작동하며,
사용법도 비슷합니다.
Trevi란 무엇인가?
서버 프레임워크란,
외부에서의 접속을 처리 할 수 있는
네트워킹 라이브러리의 묶음이라 할 수 있습
니다.
ex) Node.js
Lime이란?
Lime은
Swift로 만들어진
웹 애플리케이션 프레임워크입니다.
Express.js와 비슷한 방식으로 작동하며,
사용법도 비슷합니다.
웹 애플리케이션 프레임워크
(Web application framework)
동적인 웹 페이지나, 웹 애플리케이션, 웹 서비스 개발 보조용으
로 만들어지는 애플리케이션 프레임워크의 일종.
웹 페이지를 개발하는 과정에서 겪는 어려움을 줄이는 것이 주
목적으로 통상 데이터베이스 연동, 템플릿 형태의 표준, 세션 관
리, 코드 재사용 등의 기능을 포함한다.
Lime이란?
출처 : https://ko.wikipedia.org/wiki/웹 애플리케이션 프레임워크
Lime이란?
요약하면,
웹 애플리케이션 프레임워크란,
웹 상에서 구동되는 어플리케이션의 제작을
위한
라이브러리의 묶음이라 할 수 있습니다.
ex) Express.js
Trevi & Lime
Trevi는 혼자 사용되면 Web Server로 사용되고
Lime과 함께 사용하면
Web Application Server로 사용됩니다. .
Trevi Stack
Middleware
Lime
Trevi
왜 만들었을까?
왜 만들었지?
Swift로 만들어진 서버 프레임워크가 없어서.
왜 만들었지?
사실, Apple가고 싶어서.
어떻게 시작했을까?
어떻게 시작했을까
기본적인 이론을 공부했습니다.
HTTP, TCP, Server Model 등등
어떻게 시작했을까
Q. 스스로 바둑을 두는 프로그램
을 만들려는데 기본적인 기계 학습
이론만 안다고 만들 수 있을까?
어떻게 시작했을까
무식하면 용감하다
어떻게 시작했을까
아는 것과 할 수 있는 것을 최대한 사용해서 Node.js
인터페이스와 비슷하게 만들었습니다.
어떻게 시작했을까
Trevi 사용 예제 코드
어떻게 시작했을까
Http Server
Socket
Request Response
Finish read
Data
Middleware
Manager
Routeable
Route Mapping Table
Application
Middleware
Middleware
Middleware
Middleware
Trevi 초기 구성
한계점
한계점
서버 프레임워크의 기능과
웹 어플리케이션 프레임워크의 기능 간
의존성이 강해 확장을 할 수 없었습니다.
한계점
의존성이 강하다.
1.Trevi + @ 가 불가능
오직 Trevi(Lime)만 가능
2.HTTP만 가능,
HTTPS, FTP는 불가능한 구조
한계점
Apple의 system library인 GCD가
Linux를 완벽하게 지원하지도 않았습니다.
한계점
해결할 법 모르는 바보들이 모이면?
멍청이 + 멍청이 = 똥멍청이
한계점
해결할 법 모르는 바보들이 모이면?
멍청이 + 멍청이 = 똥멍청이
한계점
만들어 본 사람도 별로 없습니다.
한계점
철학도 필요했습니다.
미국 가서 어떻게 만들었냐 물어볼 수 없으니,
만들어 진 것을 살펴보기로 했습니다.
웹 어플리케이션 이해하기
코드에게 물어보기
코드를 분석하기로 분석 하기로 결심한 이유?
코드에게 물어보기
메이저 코드를 분석하면
해결책을 얻을 수 있을 것 같았고,
코드에게 물어보기
천명에 가까운 인원이 오랜 기간 고민했
던 것이 내가 했던 고민의 솔루션이라고 생각
했으며,
코드에게 물어보기
Node.js를 지향하고 있었기 때문에
그들의 코드를 분석하기로 했습니다.
코드에게 물어보기
롤 모델인
Node.js & Express.js
(웹 서버 프레임워크 & 웹 어플리케이션 프레임워크)
코드에게 물어보기
Javascript와 Swift는
코드에게 물어보기
함수형 프로그래밍
코드에게 물어보기
이벤트 기반
코드에게 물어보기
코드의 흐름을 파악하기가 어렵고,
놓치는 데이터들이 많았습니다.
코드에게 물어보기
그렇다면,
그 많고 이해하기 힘든 코드를
어떻게 효율적으로 분석할 수 있을까요?
코드에게 물어보기
1. 책 읽듯 코드를 읽기
2. 실제로 실행시키며, 디버거나 로그를
활용
코드에게 물어보기
아무리 복잡해 보이는 코드도
실행시켜보면 생각보다 쉽게 이해할 수 있습니다.
코드에게 물어보기
디버깅은 한눈에 변하는 값들을 확인 할 수 있어 읽을 때 놓칠 수
있는 값을 확인 할 수 있습니다.
코드에게 물어보기
1. Kitura 코드 깨기
코드 읽어보기 & Trevi 모듈과 비교하기
코드에게 물어보기
1. Kitura 코드 깨기
코드 읽어보기 & Trevi 모듈과 비교하기
코드에게 물어보기
2. Node.js & Express.js 코드 깨기
IDE를 활용해 디버깅하면서 프로세스를 이해
코드에게 물어보기
2. Node.js & Express.js 코드 깨기
IDE를 활용해 디버깅하면서 프로세스를 이해
망설이지말고 돌려보기
Event
&
Prepared
망설이지말고 돌려보기
실행방식의 차이
코드에게 물어보기
그 무렵, 경쟁 모델인
IBM-Kitura, Perfect
의 코드를 분석
출처 : https://developer.ibm.com/swift/kitura/
출처 : http://perfect.org/
배운 것을 반영하기
코드를 읽으면 무식하게 만든 것과 확실한
개념적 차이를 이해 할 수 있습니다.
출처 : https://github.com/nodejs/node
배운 것을 반영하기
데이터를 읽는 법
(Before & After)
배운 것을 반영하기
무작정 만들었을 때
Http Server
Socket
Request Response
Finish read
Data
Middleware
Manager
Routeable
Route Mapping Table
Application
Middleware
Middleware
Middleware
Middleware
배운 것을 반영하기
HTTP
Request
Read
HTTP Parser
OnBody
OnBodyComp
OnHeader
OnHeaderComp
OnInComing
Socket
State
handler
Begin
Besiness Logic
HTTP Server
socket parser
socket parser
socket parser
… …
socket parser
Node.js를 분석 후
배운 것을 반영하기
라우팅
(Before & After)
배운 것을 반영하기
Query Parser
Middeware manager
OAuth
Multi-Part
Router
error
/index Function
Router
/trevi Function
/d2/fast Routable
/naver Function
무작정 만들었을 때
배운 것을 반영하기
Node.js 분석 후
Lime Layer
Middleware
Router
Application
Protocol
1 N
배운 것을 반영하기
Node.js 분석 후
배운 것을 반영하기
Node.js 분석 후
Router
/main
/join
/login
Client
Client
Client
/…
/…
/…
성장
코드를 읽고?
성장
언어의 스킬을 이해
알고리즘의 중요성
성장
언어의 스킬을 이해
알고리즘의 중요성
성장
무엇보다 중요한 것
성장
이제 모르는 것이 생겼을 때
다른 코드를 분석하는데 겁을 먹지 않는
다!
시스템모듈 이해하기
시스템 라이브러리 적용하기
웹 어플리케이션 서버는 socket, file system,
thread 등 많은 시스템 함수를 호출 합니다.
시스템 라이브러리 적용하기
이와 같은 시스템함수를 호출할 때
서버의 성능을 높이려면 blocking이
발생하지 않도록 해야합니다.
시스템 라이브러리 적용하기
이를 위해 소켓을 non-blocking으로 설정하고
event-driven 방식으로 처리하려면
구현하기 어렵고 프로젝트가 많이 복잡해 집니
다.
시스템 라이브러리 적용하기
또한 OS별로 효율적으로 처리하는 시스템
함수 API가 달라서 이를 일일이 처리하기에는
많은 작업이 필요합니다.
시스템 라이브러리 적용하기
- epoll - kqueueOS
System
Library
GCD, libevent, libuv
Frame
work
Node.js, kitura
시스템 라이브러리 적용하기
Apple runtime system library
출처 : https://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/
시스템 라이브러리 적용하기
GCD는 어플리케이션을 개발하는 사용자에게
Asynchronous I/O 및 multicore hardware에서
효율적으로 동작하는 환경을 제공합니다.
시스템 라이브러리 적용하기
하지만 어떻게 설계해야 할까?
시스템 라이브러리 적용하기
처음에는 GCD를 적용한 간단한 Swift socket 프로젝트 분석
출처 : https://github.com/AlwaysRightInstitute/SwiftSockets
시스템 라이브러리 적용하기
SwiftSockets에서 GCD의 동작 방식 이해와
POSIX Socket API 공부 후
이전 Trevi 시스템 모듈을 설계했습니다.
시스템 라이브러리 적용하기
• 이전 Trevi system module
시스템 라이브러리 적용하기
• 이전 Trevi system module
Socket 127.0.0.1 : 8080
non-block,
sockopt
SocketSocket Socket
Listene
r
accep
t
accep
t
accep
t
시스템 라이브러리 적용하기
• 이전 Trevi system module
Socket
SocketSocket Socket
readabl
e
readabl
e
writabl
e
readabl
e
writable
readabl
e
writable
시스템 라이브러리 적용하기
• 이전 Trevi system module
Main
queu
e
Main thread
시스템 라이브러리 적용하기
• 이전 Trevi system module
Globa
l
queu
e
Thread
Pool
Threa
d
Threa
d
Threa
d
Threa
d
Threa
d
Threa
d
Threa
d
시스템 라이브러리 적용하기
이때까지 이 모듈이 효율적으로 동작하고
아무 문제가 없다고 생각했지만…
시스템 라이브러리 적용하기
출처 : https://github.com/apple/swift-corelibs-libdispatch
리눅스에서 GCD 적용 문제
시스템 라이브러리 적용하기
GCD의 Linux 지원에 문제가 있었고,
사용이 어려워졌습니다.
시스템 라이브러리 적용하기
그리고
파일시스템을 개발 시 기존 Socket 모듈의
Read / Write 부분 재사용 불가 했습니다.
시스템 라이브러리 적용하기
출처 : http://libuv.org/
Node.js system library
시스템 라이브러리 적용하기
기본적으로 Asynchronous I/O 지원하며
multi-platform 에서 안정적으로 동작합니
다.
또한 다양한 server side API들을 지원하여
GCD을 대체하여 적용하였습니다.
고급언어에서 c API 사용 시 문제점
libuv는 C로 구성된 system library이며
Swift에서 C library를 적용하고 사용하는 데
는
아무런 문제가 없었습니다.
고급언어에서 c API 사용 시 문제점
그러나 libuv는 발생하는 이벤트의 callback
을
C의 함수 포인터로 인자를 받아서
Swift의 클로저를 libuv의 callback 함수로
사용하기에는 많은 어려움이 있습니다.
고급언어에서 c API 사용 시 문제점
libuv callback 함수 예시
고급언어에서 c API 사용 시 문제점
class Server {
var clientNumber = 0
var socket: Listener!
func createServer (port: Int) {
socket = Listener(port)
socket.listenClientEvent(){
client in
clientNumber += 1
self.printClientNumber()
}
}
func printClientNumber(){
print(“client number : (clientNumber)”)
}
}
변수 및 함수 참조
클로저를 libuv callback 함수 대입 시 문제
코드에게 배우고 반영하기
그럼 이제 어떻게?
코드에게 배우고 반영하기
API 문서 및 예제 코드를 통해 배우고
libuv를 적용한 서버 프레임워크들을 분석
(Node.js, Luvit, Julia … etc)
코드에게 배우고 반영하기
Node.js architecture
출처 : http://www.iij.ad.jp/en/company/development/tech/nodejs/index.html
코드에게 배우고 반영하기
해당 부분은 GitHub의 nodejs/node 에서
src 디렉토리 아래 c++ 모듈
코드에게 배우고 반영하기
• 현재 Trevi system module
코드에게 배우고 반영하기
• 현재 Trevi system module
handle
struct
static object
dictionary
handle
object
callbacks(closur
e)
코드에게 배우고 반영하기
• 이전 system module의 문제 해결
코드에게 배우고 반영하기
• multi-thread model
New eventWork event module
onConnecti
on
onRead
afterWrite onClose
onTimeou
t
onConnecti
on
onRead
afterWrite onClose
onTimeout
Work thread
pool
Thread
코드에게 배우고 반영하기
• Cluster module (예정)
출처 : http://www.aosabook.org/en/posa/from-socialcalc-to-ethercalc.html
성장
어려운 부분들을 해결하는 데
가장 도움이 된 방법
성장
실행 & 분석
성장
이를 통해 배울 수 있었던 것?
성장
숙련된 개발자의 개발 방법
잘 몰랐던 부분의 이론이나 지식
…
etc
(socket, swift socket api, blocking, library 등)
앞으로의 방향
앞으로의 방향
‘해보고 싶었으니까’를 넘어서서
앞으로의 방향
‘누군가에게 쓰이기 위해’를 향해서.
THANKS
Reference
• https://ko.wikipedia.org/wiki/웹 애플리케이션 프레임워크
• https://github.com/expressjs/express
• https://nodejs.org/en/
• https://developer.ibm.com/swift/kitura/
• http://perfect.org/
• https://github.com/nodejs/node
• https://github.com/AlwaysRightInstitute/SwiftSockets
• https://github.com/apple/swift-corelibs-libdispatch
• http://www.iij.ad.jp/en/company/development/tech/nodejs/i
ndex.html

제 5회 D2 CAMPUS SEMINAR - Swift로 만든 serverframework 개발기