Scala for play

2,760 views

Published on

Scala for play

  1. 1. for myeesan@gmail.com 라 스칼라 코딩단 최정열
  2. 2. Play 는 모르셔도 되지만 , 스칼라는 조금 아셔야 합니다 .
  3. 3. Scala for Play
  4. 4. 프레임워크를 찾아서 ... ● 모바일 테스트 서버가 필요해 ... ● 웹 프론트 개발을 위한 베이스 ... ● 무엇보다 만들고 싶은게 많았음 ...
  5. 5. 프레임워크 선택 기준 ... ● ● Quick and Dirty 확장 가능성 ● Testablity & TDD able ● 뚜렷한 지향점 ● JAVA ● ● JVM 투명성
  6. 6. 웹 프레임워크 ...
  7. 7. History - Play 1.x
  8. 8. History - Play 1.x
  9. 9. History - Play 1.x SBT Akka Template
  10. 10. History - Play 2
  11. 11. 고민 스칼라를 배워야 하나 ?
  12. 12. 결정 ! 목숨걸고 한 3 개월 하면 되겠지 ?
  13. 13. 잃어버린 2013
  14. 14. Play framework Simple Great Testing Support URL Routing JPA/Ebean Support (Java only) Class Reloading NIO Server(Netty) Share-Nothing Asset Compiler Java & Scala Support i18n Compile time checking Instant deply on Heroku, Cloud bees
  15. 15. Simple
  16. 16. Servlet Play
  17. 17. Simple > All in One
  18. 18. Simple > Code Restful Routes GET /index controllers.App.index Straitforward Controllers Action { Request → Response } Easy Template <h1> @name </h1>
  19. 19. Simple > Web Spec HTTP/1.1(rfc2616) HTML5 / CSS
  20. 20. Simple > Http Result Result.scala def SeeOther(url: String): SimpleResult = Redirect(url, 303) val BadRequest = new Status(400) val NotFound = new Status(404) val InternalServerError = new Status(500) val NoContent = SimpleResult( header = ResponseHeader(204), body = Enumerator.empty, connection = HttpConnection.KeepAlive) } 응답코드에 따른 행동은 플레이가 알아서 ~
  21. 21. Simple > Test Integration Test browser.goTo("http://localhost:" + port) browser.pageSource must contain("Hello") Unit Test val home = route(FakeRequest(GET, "/")).get status(home) must equalTo(OK) contentType(home) must beSome.which("text/html") contentAsString(home) must contain ("Hello")
  22. 22. Simple > Deploy on Heroku Procfile 개발 / 배포 설정도 플레이가 알아서 ! web: target/start -Dhttp.port=${PORT} -DapplyEvolutions.default=true -Ddb.default.url=${DATABASE_URL} -Ddb.default.driver=org.postgresql.Driver Deploy! $ git push heroku master
  23. 23. Simple > Deploy on CloudBees
  24. 24. Simple > I18n conf/messages error.notfound = Post not found error.required = Mandatory field is empty user.confirmPassword = Confirm Password validation.duplicated = Already exists! validation.required = Required! conf/messages.ko error.notfound = 페이지를 찾을 수 없습니다 . error.required = 필수로 입력 되어야 합니다 . user.confirmPassword = 패스워드를 확인해주세요 . validation.duplicated = 이미 존재합니다 ! validation.required = 필수입니다 .
  25. 25. Simple > Too Simple 하위 호환성은 기대하지 않는게 좋습니다 .
  26. 26. Case Study
  27. 27. Play inside
  28. 28. Project 1 프로젝트 생성 $ play new myApp 2 콘솔 진입 $ play 3 실행 > run IDE 프로젝트 생성시 소스를 포함하여 빌드 > Idea with-source = true > eclipse with-source=true
  29. 29. Structure app └ assets └ controllers └ models └ views conf └ application.conf └ routes public project test LESS CSS, CoffeeScript Application controllers Application business layer Templates Configurations files Main configuration file Routes definition Image, CSS, JavaScript Build, Plugins Setting Unit and Integration Test
  30. 30. Play framework Routes Routes ... ... ... ... request request Client dispatch Controller 1 2 Controller Controller 1 2 Controller response response View View Model
  31. 31. Routes Http method Uri Body (scala code) GET / controllers.App.index GET /add controllers.App.blank POST /article controllers.App.insert GET /article/$num<d{9}> controllers.App.details(num: Long) POST /article/:id controllers.App.update(id: Long) POST /article/:id/delete controllers.App.delete(id: Long) GET /assets/*file controllers.Assets.at(path="/public", file)
  32. 32. Routes Http method Uri Body (scala code) GET / controllers.App.index GET /add controllers.App.blank POST /article controllers.App.insert GET /article/$num<d{9}> controllers.App.details(num: Long) POST /article/:id controllers.App.update(id: Long) POST /article/:id/delete controllers.App.delete(id: Long) GET /assets/*file controllers.Assets.at(path="/public", file)
  33. 33. Controller POST /article/:id controllers.App.detail(id: Long) object App extends Controller { def detail(num: Long) = Action{ OK(Item.find(num)...) } def join = WebSocket{ ... } }
  34. 34. Actions def r: Result = Action { Ok("Hello World!") } Action { Ok("Hello World!").withHeaders( CACHE_CONTROL -> "max-age=3600", ETAG -> "xx" )} Action.Async { future.map(i => Ok("Hello World!" + i))} Action (parse.json) { implicit request: => Ok("Request: " + request) } WebSocket.using[String] { request: => val in = Iteratee.foreach[String] val out = Enumerator("Hello!") (in, out) }
  35. 35. Request def i = Action { implicit req => Ok("Request: [" + req + "]") }
  36. 36. Request def i = Action { implicit req: [ Ok("Request: [" + req + "]") } ] =>
  37. 37. Request def i = Action { implicit req: AnyContent => Ok("Request: [" + req + "]") }
  38. 38. Request def j = Action(parse.json) { implicit req => Ok("Request: [" + req + "]") }
  39. 39. Request def j = Action(parse.json) { implicit req: [ Ok("Request: [" + req + "]") } ] =>
  40. 40. Request def j = Action(parse.json) { implicit req: JsValue => Ok("Request: [" + req + "]") }
  41. 41. Scala for Play 플레이를 공부하면서 가장 많이 나온 주제를 정 리했습니다 . Template implicit keyword Form Option[T] type
  42. 42. Scala for Play Tem plate
  43. 43. Template 어느날 제자가 스승에게 물었다 . 스승님 바람에 나뭇가지가 흔들리는 것은 나뭇가지가 흔들리는 것입니까 바람이 흔들리는 것 입니까 ? 그러자 스승이 답했다 . 흔들리는 것은 나뭇가지도 아니고 바람도 아니다 . 바로 너의 마음이다 .
  44. 44. Template Header.scala.html @(title: String) <h1>@title</h1> convert Header.template.scala def apply(title: String) = { format.raw( "<h1>" + title + "</h1>" ) }
  45. 45. Template @(title: String, articles: List[article]) @import helper._ <table> @main(title){ @articles.map{ article => <li> @article.title </li>}} </table>
  46. 46. Template composition Header main (header) (side)(content) side Content
  47. 47. Implicit Parameter
  48. 48. Implicit val db: DB = application.getDatabase() def query(str: String)(db: DB): List[User] val users = query("""SELECT * FROM USER""")(db) val posts = query("""SELECT * FROM POST WHERE ...""")(db) val pets = getPost("""SELECT * FROM PET""")(db)
  49. 49. Implicit val db: DB = application.getDatabase() def query(str: String)(db: DB): List[User] val users = query("""SELECT * FROM USER""")(db) val posts = query("""SELECT * FROM POST WHERE ...""")(db) val pets = getPost("""SELECT * FROM PET""")(db)
  50. 50. Implicit implicit val db: DB = application.getDatabase() def query(str: String)(implicit db: DB): List[User] val users = query("""SELECT * FROM USER""")(db) val posts = query("""SELECT * FROM POST WHERE ...""")(db) val pets = getPost("""SELECT * FROM PET""")(db)
  51. 51. Implicit implicit val db: DB = application.getDatabase() def query(str: String)(implicit db: DB): List[User] val users = query("""SELECT * FROM USER""") val posts = query("""SELECT * FROM POST WHERE ...""") val pets = getPost("""SELECT * FROM PET""")
  52. 52. Implicit import play.api.Play.current def getAll: List[Product] = DB.withConnection { implicit connection => sql().map ( row => Product(row[Long]("id"), row[String]("name") ).toList}
  53. 53. Implicit import play.api.Play.current def getAll: List[Product] = DB.withConnection { implicit connection => sql().map ( row => Product(row[Long]("id"), row[String]("name") ).toList} Play.api.Play.scala implicit def current: Application = maybeApplication...
  54. 54. Option Type List 와 함께 가장 중요한 타입입니다 . 처음부터 잘 살펴 보세요 >_< 스칼라 코드에서 여러분이 null 을 보실 일은 거의 없습니다 . 가능한 null 체크를 사용하지 않도록 노력 해보세요 ~ (null object pattern) Scala.Option.scala def apply[A](x: A): Option[A] = if (x == null) None else Some(x) // mothods flatMap, Flatten, map, foreach, idDefined, isEmpty...
  55. 55. Form (hide nothing) 1 Client GET /signup 2 Signup.html 3 Validate Fail su /index 5 Redirect cc es s 4 Create
  56. 56. 마무리 Pros & Cons ( 순전히 개인적인 )
  57. 57. Pros 단점 빼고 다 좋습니다 !
  58. 58. Pros 단점 빼고 다 좋습니다 ! 라고 하면 ...
  59. 59. Pros ● Simple ● Type Safe everywhere ● Java ↔ Scala
  60. 60. Cons ● SBT ● Type Safe ● 불완전한 IDE ● 적은 유저
  61. 61. 2.3 Roadmap ● ● ● ● ● 브라우저 내에서의 개발환경 구성 WebJar - Jquery, require.js, ecc JSUnit test Bootstrap 탬플릿 향상 JSON API → Form 매핑 Java ● JDK8 Compat Library ● Java 8 – template
  62. 62. 질문 여러분은 무엇을 만들고 싶으세요 ?
  63. 63. 이렇게 시작해서 ...
  64. 64. 이렇게 시작해서 ...
  65. 65. 언젠가는 ... 발표에 사용된 예제 코드 : https://github.com/organizations/ScalaPlayers
  66. 66. 감사합니다 ! 라 스칼라 코딩단 GoogleGroups/ScalaKorea https://groups.google.com/forum/#!forum/scala-korea 발표에 사용된 샘플 코드 (2013-11-01 이후 업로드 ) github.com/ScalaPlayers/SpringCampWithScala2013 최정열 SNS: facebook.com/choijeongyeol Email: myeesan@gmail.com
  67. 67. Scala "Scala is deep where other languages are broad."

×