2013년 11월 21일 목요일

장고 무작정 시작하기 - 시작하기에 앞서

이 글은 Django Project  사이트 튜토리얼을 참조하여 쓰는 글입니다. 저도 아직 초보자임을 미리 밝힙니다.

장고를 시작하기에 앞서
장고의 장점들을 알아봅시다

1. 모델(데이타베이스 스키마) 디자인이 편하다
물론 웹사이트를 데이터베이스 없이 만들수도 있지만, 필요하다면 간편하게 모델을 만들 수 있습니다.

예:

from django.db import models

class Reporter(models.Model):
    full_name = models.CharField(max_length=70)

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.full_name

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter)

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.headline
이렇게 객체 클래스를 선언하듯이 선언하여 모델을 만들 수 있는데
이것을 object-relational mapping 이라고 하고, 이것은 mysite/news/models.py
에 저장됩니다.

2. 쉽게 여기저기서 작업할 수 있다.
프로젝트 파일들로 구성되어있기 때문에, 파일만 들고와서
파이썬 명령어로 서버를 구동시키기만 하면 구동됩니다.

3. 에러를 확인하기가 매우 쉽다..
콘솔창과 브라우져에서 어떤 에러가 떴는지, 어디서 에러가 발생하였는지 보여주는데다가,
고친 부분이 바로바로 적용됩니다. (DB 를 제외하고)
그리고 콘솔창에서 파이썬 명령어로 미리 어떤 결과가 나올지 볼 수도 있습니다.
개인적으로 저 또한 웹 만들어보는 것을 처음 해 보았기에, 가장 마음에 드는 점이였습니다.

이 외에도 좋은 점들이 매우 많지만(원하는 URL 지정, 템플릿 만들기, 원하는 뷰 만들기 등)
처음 하시는 분들은 잘 모르실테니 필자도 잘 모릅니다
직접 장고를 해 보면서 알아가도록 합시다.

참고로, 장고를 기반으로 만든 사이트들은
Disqus, 인스타그램, 핀터레스트 등이 있습니다.


참조한 글:
https://docs.djangoproject.com/en/1.6/intro/overview/

2013년 11월 17일 일요일

Google Volley 의 기능들과 사용법 (코드 예제)


Volley의 주 기능과 장점

* 하나의 requestQueue 모든 요청들을 처리한다
     -알아서 동시다발적으로 요청을 할수있다

* 우선 순위 설정을 할수 있다.
     -이미지 파일들은 기본적으로 낮은 우선순위를 가진다.
     -Priority class 를 상속하여 우선순위를 customize 할 수도 있다.

* 리퀘스트를 취소할 수도 있다. ( ListView 에서 유저가 빠르게 스크롤링 할 경우, 스크롤링 한 내용을 다 로딩할 필요가 없고, 보여지는 부분 이외에 로딩이 안된 리퀘스트들은 취소할 수 있다. )
      -Volley 가 알아서 자동으로 처리한다.

* 프로요 버전의 HttpURLConnection에 있는 버그를 해결해준다.


* NetworkImageView 클래스가있다.

     -imageLoader 구현
     -이미지로딩 요청들을 모았다하 하나로 묶어서 보내준다.
     -캐싱 기능
     -이미지 스케일링 기능 (훨씬 빠른 로딩이 가능하다)
     -병행 (동시다발적) 이미지 로딩 - 핸드폰의 코어수 만큼의 로딩하여 최적화 함.

Volley 가 작동하는 법!

     



처음 리퀘스트를 생성하고 큐에 넣으면, 우선순위에 맞추어 캐시 큐로 들어간다.
그 후, 리퀘스트가 큐에서 나올 차례가 되면, CacheDispatcher 가 리퀘스트를 빼간다.
그럼 Volley는 리퀘스트에 대한 결과값이 캐시에서 가져올 수 있는지 확인한다. (hit 화살표)
만약 가져올수 없으면 miss 다. (miss 화살표)

캐시 hit 의 경우, 캐시에서 결과 값을 읽어온 후 파싱을 하고 response를 던진다.

miss 의 경우, NetworkResponse에서 리퀘스트를 받아서 넷상으로 request를 보내고 결과 값을 받아 파싱한다.

코드 예제
Volley를 쓰려면 기본적으로 3 단계를 거친다.:
1. RequestQueue  를 만든다.
2. Reuest를 만든다.
3. Request를 RequestQueue 에 넣는다.

1. RequestQueue 를 Singleton 형식으로 만든다.
Volley는 하나의 Queue에서 모든 요청을 처리하므로, Queue는 하나만 만들어 쓰면 되기에 Singleton 패턴을 쓴다.


public class VolleySingleton {
    private static VolleySingleton mInstance = null;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;

    private VolleySingleton(Context context){
        mRequestQueue = Volley.newRequestQueue(context);
        mImageLoader = new ImageLoader(this.mRequestQueue, new ImageLoader.ImageCache() {
            private final LruCache mCache = new LruCache(10);
            public void putBitmap(String url, Bitmap bitmap) {
                mCache.put(url, bitmap);
            }
            public Bitmap getBitmap(String url) {
                return mCache.get(url);
            }
        });
    }

    public static VolleySingleton getInstance(Context context){
        if(mInstance == null){
            mInstance = new VolleySingleton(context);
        }
        return mInstance;
    }

    public RequestQueue getRequestQueue(){
        return this.mRequestQueue;
    }

    public ImageLoader getImageLoader(){
        return this.mImageLoader;
    }
}

2. Http Request를 구현한다.
1)미리 Type이 정의된 리퀘스트의 경우
생성자 파라미터로  int Request.Method.(GET or POST), String url, T Content, Response Listener, Response ErrorListener 를 받는다.
new JsonObjectRequest( //JsonArrayRequest and StringRequest(call API in URI) is the same
                Request.Method.POST, "url", null,
                new Response.Listener() {
                    @Override
                    public void onResponse(JSONObject jsonObject) {

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError volleyError) {

                    }
                }
        );
    };
2)커스텀 Request (JsonRequest or Request)의 경우
      1 - JsonRequest는 parsenetworkResponse 메소드에서 결과값인 NetworkResponse를 파싱 해주어야 한다.

    JsonRequest jsonRequest = new JsonRequest(Request.Method.POST, "url", "requestBody",
            new Response.Listener() {
                @Override
                public void onResponse(JSONArray jsonArray) {

                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError volleyError) {

                }
            })
    {
        @Override
        protected Response parseNetworkResponse(NetworkResponse networkResponse) {
            try{
                String json = new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers));
                return Response.success(
                        new JSONArray(json), HttpHeaderParser.parseCacheHeaders(networkResponse)
                );
            }
            catch(UnsupportedEncodingException e){
                return Response.error(new ParseError(e));
            }
            catch(JSONException e){
                return Response.error(new ParseError(e));
            }
        }
    };
-2 Request 의 경우에도 parseNetworkResponse 에서 파싱을 해주고, deliverResponse에서 Response 리스너가 반응하는 함수를 넣어주어야 한다.

    Request integerRequest = new Request(Request.Method.POST, "url", new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {

        }
    }) {
        @Override
        protected Response parseNetworkResponse(NetworkResponse networkResponse) {
            try {
                Integer i = new Integer(new String(networkResponse.data, HttpHeaderParser.parseCharset(networkResponse.headers)));
                return Response.success(i, HttpHeaderParser.parseCacheHeaders(networkResponse));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }

        @Override
        protected void deliverResponse(Integer integer) {
             listener.onResponse(integer);
        }
    };
3) 이미지 요청은 URL 과 위의 Singleton 에 있는 ImageLoader를 이용하여 요청한다.
    ImageRequest a = new ImageRequest("url", new Response.Listener() {
        @Override
        public void onResponse(Bitmap bitmap) {

        }
    }, /*maxWidth*/0, /*maxHeight*/ 0, Bitmap.Config.ARGB_8888, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError volleyError) {
        }
    });
또는 XML 레이아웃파일에 com.android.volley.toolbox.networkimageview 를 넣어놓고 Java에서 뷰를 부른 후, 아래와 같은 형식으로 요청한다.
    mImageView.setImageUrl(URL, mImageLoader);
(자동으로 큐에 들어가므로 더욱 간단하다.)

3. 생성한 Request를 큐에 넣는다.
VolleySingleton.getInstance(mContext).getRequstQueue().add(request);


참고 자료:
     Youtube - Google I/O 2013 - Volley: Easy, Fast Networking for Android
                    http://www.youtube.com/watch?v=yhv8l9F44qo
     Setting up the Android Google Volley ImageLoader for NetworkImageView
          http://cypressnorth.com/mobile-application-development/setting-android-google-volley-imageloader-networkimageview/ 
     [android] Volley - Network & ImageLoading 라이브러리 ( google I/O 2013 )     
          http://hanburn.tistory.com/135