블로그 이미지
App 개발에 대한 내용을 다룰 예정입니다. AppleSherbet

카테고리

분류 전체보기 (39)
한국프로야구 어플 (18)
세미나 (2)
Java Development (13)
Android App소개 (3)
기타 (2)
당근마켓 (1)
Total296,597
Today27
Yesterday16
 Building the first screen 
 
  전 시간에서 Model (데이터 베이스) - User, Post, Comment 를 만들어 보았다. 이제 드디어 우리 블로그의 첫 페이지를 만들어 보자. 누구나 그렇듯 UI가 보여야 개발하는 재미가 생기고 특히 요즘은 개발 기술만큼이나 UI가 중요하게 여겨지는 시대가 온 것 같다. 아래의 이미지는 우리가 만들 블로그의 Mock-up 이미지이다.


 
 Bootstrapping with default data


  시작하기 전에 먼저 test data를 로드 하는 부분을 추가하자. 아무리 블로그를 이쁘게 만든다고 해도 data가 없다면 블로그가 횡해 보이지 않겠는가! 또한 아직 아무런 UI도 만들지 않았기 때문에 우리가 포스팅을 할 수 조차 없다. 데이터를 DB에 로딩하는 가장 좋은 방법은 예전에도 설명했던 Fixture 를 이용하는 방법이다. 어플리케이션이 로드할때 Fixture를 이용해 초기 데이터를 DB에 저장하는 것이다. 그렇게 하기 위해
/yabe/app/Bootstrap.java 파일을 만들어보자.
import play.*;
import play.jobs.*;
import play.test.*;
 
import models.*;
 
@OnApplicationStart
public class Bootstrap extends Job {
 
    public void doJob() {
        // Check if the database is empty
        if(User.count() == 0) {
            Fixtures.loadModels("initial-data.yml");
        }
    }
 
}
  눈치 챘겠지만 우리가 주목해야할 부분은
@OnApplicationStart 어노테이션이다. 이 어노테이션은 Play로 하여금 어플리케이션이 처음 시작할때 BootStrap 클래스의 doJob() 메소드를 자동으로 수행하도록 해준다. test 시 사용했던 data.yml 파일을 yabe/conf/initial-data.yml 로 복사하자. 이미 만들어 놓은 것이 있기 때문에 그대로 사용하면 된다. 이제 play run 커맨드를 이용해 http://localhost:9000 페이지가 브라우져에 별 에러 없이 나오는지 확인해보자.

 The blog home page

  이제 진짜 블로그 페이지를 만들어보자. 맨 처음 설명했었던 어떻게 index.html이 렌더링 되는지 기억하는가? 요약하면 사용자가 브라우져를 통해 / (루트) URL에 접속하면 request를 받은 play 서버는 route 파일을 참조해
controllers.Application.index() 액션 메소드를 수행한다. index() 액션에서는 다시 render() 함수가 호출되고 render 함수는 index와 같은 이름을 가진 /yabe/app/views/Application/index.html 을 찾아 랜더링을 수행한다.
이제 index 코드를 먼저 우리의 블로그에 맡게 수정해보자.
/yabe/app/controllers/Application.java 파일을 열고 index() 액션 메소드를 Post의 리스트를 로딩하도록 수정한다.
package controllers;
 
import java.util.*;
import play.*;
import play.mvc.*;
import models.*;
 
public class Application extends Controller {
 
    public static void index() {
        Post frontPost = Post.find("order by postedAt desc").first();
        List<Post> olderPosts = Post.find(
            "order by postedAt desc"
        ).from(1).fetch(10);
        render(frontPost, olderPosts);
    }
}
  코드에서 볼 수 있듯이 render 메소드로 Object type을 넘길 수 있다. 또한 넘길 수 있는 파라메터 수의 제한도 없다. Model 을 상속 받으므로써 사용할 수 있는 find() 헬퍼 메소드의 사용 또한 주목해서 보자. first() 메소드는 쿼리 결과 리스트의 첫번째 Post를 리턴하고, from~fetch() 메소드는 특정 번호부터 10개의 Post들을 리런해준다. frontPost는 가장 최신 포스팅을 의미하며 olderPosts는 최신 10개의 포스팅들을 의미한다.(가장 최신 포스트를 메인화면에 자세히 보여주고 나머지 10개의 최근 포스팅들을 리스트로 보여주려는 의도)
이제
/yabe/app/views/Application/index.html 을 열어서 frontPost와 olderPosts로 저장된 객체를 표시하도록 수정하자.
#{extends 'main.html' /}
#{set title:'Home' /}
 
#{if frontPost}
    

${frontPost.title}

${frontPost.content.nl2br()}
#{if olderPosts}

Older posts from this blog

#{list items:olderPosts, as:'oldPost'}

${oldPost.title}

#{/list}
#{/if} #{/if} #{else}
There is currently nothing to read here.
#{/else}
  index.html 에서는 예상했듯이 render메소드로 전달된 frontPost, olderPosts 객체를 그대로 사용할 수 있다. 물론 frontPost.author, frontPost.postedAt 등의 값에 접근도 가능하다. 여기서
frontPost.postedAt.format('MMM dd') 를 주목하자. 우리는 따로 format('MMM dd') 를 정의해준 적이 없다. 또한  frontPost.postedAt은 Date 타입인데 JDK Java 의 Date 타입에는 format이라는 메소드가 있지도 않다. 결론부터 말하면 Java object extentions 라고 해서 Play에서는 특정 타입의 변수에 유용한 메소드들을 추가적으로 정의해 두어 런타임시에 view에서 쉽게 사용할 수 있다.
 
  Custom extension또한 정의가 가능하다. 즉, 개발자가 특정 java object type에 필요한 메소드를 추가적으로 정의하면 어디서든 해당 type의 변수에서 custom extension을 쓸 수 있다. 이러한 extension 기능은 view의 코드를 깔끔하게 유지시켜주고 중복또한 제거해 줄 수 있어서 매우 유용하다. 이곳에서 간단하게 읽어보고 진행하는 것을 추천한다.

  Java object extentions을 사용한 부분이 한군데 더 있다. 바로
frontPost.comments.size().pluralize() 이다 이 메소드는 size()가 복수의 값을(>=2) 리턴할 경우 문자열에 "s"를 추가해 복수를 표현해 준다.
  또 한가지 봐야 할 부분은 Groovy 를 사용했다는 점이다.
#{list items:olderPosts, as:'oldPost'} 가 대표적인 예인데 Java와 문법이 흡사하다. 즉, olderPost 리스트에 있는 item 갯수만큼 순환을 돌게되며 #{list }... #{/list} 안에서는 oldPost 로(as:'oldPost' 에 의해) 접근 할 수 있다. 나머지 문법들도 jsp 와 같은 스크립트 언어를 사용해 봤다면 쉽게 이해할 수 있을 것이다.

자, 이제 브라우져에서 refresh를 해보자.


UI는 좀 별루지만 아무튼 잘 보이고 있다.

  이미 눈치챈 분들도 있겠지만 index.html을 보면 거의 같은 코드가 중복되고 있다. 또한 앞으로 우리는 그와 같은 코드를 몇몇 다른 코드에서 다시 사용할 것이므로 중복된 코드를 따로 분리해보자. Play에서는 이런 기능을 지원하기 위해 Play tag 를 지원해준다. Tag를 만들기 위해
/yabe/app/views/tag/display.html 파일을 만들자. display tag는 두개의 파라메터를 인자로 갖는다: Post object와 display mode(여기선 "home", "teaser", "full). Display tag 를 아래처럼 구현해준다.
*{ Display a post in one of these modes: 'full', 'home' or 'teaser' }*
 

${_post.title}

#{if _as != 'teaser'}
Detail:
${_post.content.nl2br()}
#{/if}
#{if _as == 'full'}

${_post.comments.size() ?: 'no'} comment${_post.comments.size().pluralize()}

#{list items:_post.comments, as:'comment'}
Detail:
${comment.content.escape().nl2br()}
#{/list}
#{/if}
  /yabe/app/views/tag/ 에 만드는 것은 관례이므로 따라야 한다. display tag는 _as 값에 따라 다르게 결과를 표시해주는 것을 볼 수 있다. 이제 중복 코드를 분리했으니 다시 index.html 을 아래 처럼 수정하자.
#{extends 'main.html' /}
#{set title:'Home' /}
#{if frontPost}
    #{display post:frontPost, as:'home' /}
    #{if olderPosts.size()}
        

Older posts from this blog

#{list items:olderPosts, as:'oldPost'} #{display post:oldPost, as:'teaser' /} #{/list}
#{/if} #{/if} #{else}
There is currently nothing to read here.
#{/else}
  index 코드를 보면 #{display post:olderPosts, as:'oldPost'} 와 같이 post, as 란 이름으로 파라메터를 전달한다. display tag에서는 이와 같이 전달된 파라메터에 '_' 를 앞에 붙인 _post, _as 로 접근해 해당인자를 사용할 수 있다. 다시 브라우져를 refresh 해보자.

 Improving the layout

  index.html 을 보면 main.html 을 상속(extends)받고 있는 것을 볼 수 있다. 모든 view에서 공통으로 보여주고 싶은 layout 즉, blog title, 로그인 link 등을 추가하기 위해
main.html을 수정하자.

/yabe/app/views/main.html
    
        #{get 'title' /}		
        
        
        
    
    
        
        
        
        
#{doLayout /}
  자 이제 다시 브라우져를 refresh 해보자. blogTitle, blogBaseLine 부분을 제외하고는 잘 동작 하는 것 같다. 잘 동작하도록 해주기 위해 render(...) 메소드에 해당 파라메터를 넘겨주는 방법이 있다 하지만 main.html 은 모든 view에서 공통으로 사용될 것이므로 조금 다른 방법으로 파라메터를 넘겨보자. Application controller에 아래와 같이 addDefault() 메소드를 추가하자.
@Before
static void addDefaults() {
    renderArgs.put("blogTitle", Play.configuration.getProperty("blog.title"));
    renderArgs.put("blogBaseline", Play.configuration.getProperty("blog.baseline"));
}
  renderArgs에 put을 통해 넣은 파라메터는 모든 template 에서 사용가능하다는 장점이 있다. @Before 어노테이션을 이용해 다른 액션이 불리기 전에 가장 먼저 수행 하도록 했다. 여기서 우리는 Play.configuration 객체를 이용해 파라메터를 가져오고 있는 것을 볼 수 있다. 아직 configuration 파일에 필요한 정보를 넣지 않았으므로 /yabe/conf/application.conf에 configuration 정보를 넣어주자.
# Blog engine configuration
# ~~~~~
blog.title=Yet another blog
blog.baseline=We will write about nothing
  이제 Play.configuration.getProperty 메소드는 정상적으로 설정 정보 즉, Yet another blog와 We will... 에 대한 문자열 정보를 읽어올 수 있을 것이다.
다시 브라우져를 refresh 해보자. 잘 나오는가!
 

Adding some style
 

  자 이제 블로그의 홈페이지가 거의 완성되어 간다. 하지만 정말 볼품이 없다. style을 추가해서 블로그를 멋지게 바꿔보자. 좀 전에 main.html 에 이미 우리는 /public/stylesheets/main.css 경로를 추가 했었다. 그러므로 해당 파일을 /public/stylesheets/ 폴더에 넣어주기만 하면 될 것이다.
  css 에 대해 이곳에서 설명하는 것은 무리가 있으므로 생략하겠다. 혹시 css에 대해 전혀 모른다면 wikipedia 에서 간단히 개념 정도는 알고 넘어가자.

  그럼 이곳에서 main.css파일을 다운받아
/public/stylesheets/ 폴더에 넣어주자. 다시 브라우져를 refresh 해보자. 몇배 알흠다워진 우리 블로그를 볼 수 있다.

 

저작자 표시
신고
Posted by AppleSherbet

최근에 달린 댓글

최근에 받은 트랙백

글 보관함

티스토리 툴바