이클립스에서 Android Application 실행 시 USB로 연결 된 안드로이드 기기를 제대로 인식하지 못한다면,


adb가 설치되어 있는 곳으로 가서


adb kill-server

adb start-server

sudo adb devices


를 실행해주자




저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by 우너효

원본: https://cirw.in/blog/time-to-move-on

번역: 우너효


MVC 패턴은 정말 멋진 생각입니다. 상태를 담고 있는 독립적인 모델과, UI를 가지고 있는 독립적인 뷰, 그리고 무언가를 가지고 있는 독립된... 읭?


MVC 패턴을 적용해 보셨다면 아시겠지만, 코드를 어디에 넣어야 할 지 몰라서 결국 컨트롤러에만 수많은 코드를 꾸역꾸역 넣어본 경험이 있으실 겁니다. 이러한 문제점이 있음을 깨달은 건 비단 저 뿐만은 아니겠지요.


이를 해결하기 위해 저는 새로운 패턴을 사용했습니다. 

바로 MOVE 패턴입니다. 

Models, Operations, Views, 그리고 Events.



Overview

MOVE를 적용한 애플리케이션의 구조

자세한 얘기에 앞서, 위의 다이어그램은 MOVE 패턴을 적용한 애플리케이션의 기본 구조를 나타내고 있습니다.

  • 모델은 애플리케이션이 알아야 할 모든 것을 담고 있습니다.
  • 오퍼레이션은 애플리케이션이 해야 할 모든 것을 담고 있습니다.
  • 뷰는 애플리케이션과 유저 간의 징검다리 역할을 합니다.
  • 이벤트는 모든 요소들이 잘 어우러지게끔 하는 역할을 합니다.

스파게티 코드가 되는 사태를 막기 위해, 타입 별 객체들이 할 수 있는 일에 대해 정해 놓는 것은 정말 중요한 일입니다. 저는 그러한 점을 다이어그램에 화살표로 표시해 놓았습니다. 예를 들어서, 뷰는 모델에 의해 생겨난 이벤트를 받습니다. 그리고, 오퍼레이션은 모델을 변경할 수 있지만, 뷰나 오퍼레이션을 참조해서는 안됩니다.


Models

전형적인 모델 객체는 바로 "user"가 되겠습니다. 적어도 이메일 주소가 있겠고, 이름이나 전화번호도 있을 수 있겠죠. MOVE 애플리케이션에서 모델은 'knowledge'만을 담고 있습니다. 이는 모델 내에 getter와 setter 함수 이외에도, "이게 정말 그 user의 비밀번호가 맞아?"라는 식의 함수가 있을 수도 있다는 겁니다. 하지만, 그러한 정보를 데이터베이스에 저장하거나, 외부 API를 통해 업로드를 하는 함수는 없습니다. 그러한 작업은 오퍼레이션에 의해 처리가 되어야 합니다. 


Operations

애플리케이션의 일반적인 오퍼레이션은 사용자 로그인일 겁니다. 사실 이는 2개의 서브 오퍼레이션(sub-operation)으로 구성되어 있다고 볼 수 있습니다. 하나는 사용자로부터 이메일 주소와 비밀번호를 받는 거고, 다른 하나는 데이터베이스에서 "user" 모델을 불러와 앞서 받은 이메일 주소와 비밀번호의 일치여부를 확인하는 겁니다.

MOVE 패턴에서 오퍼레이션은 행동대장(!?)이라 볼 수 있습니다. 모델을 변경하고, 적절한 때에 적절한 뷰를 보여주고, 사용자의 입력에 의해 발생한 이벤트에 적절한 반응을 하게 됩니다. 잘 만들어진 애플리케이션이라면, 각각의 서브 오퍼레이션들은 해당 부모로부터 독립적으로 실행이 되어야 합니다. 위의 다이어그램의 오퍼레이션 안을 봤을 때, 이벤트들의 흐름은 위로 이루어지고 변화는 아래로 이루어지는 이유가 바로 그 때문입니다. 

오퍼레이션을 이런 식으로 사용할 경우 여러분이 만든 애플리케이션 자체가 프로그램이 부팅 될 때 하나의 오퍼레이션으로 처리될 수 있기 때문에 정말 좋습니다. 서브 오퍼레이션들은 필요한 만큼 만들어져 동시에 존재하고, 병렬적으로 실행이 되며, 작업을 모두 마치고 나면 프로그램을 종료하게 됩니다.


Views

로그인 화면은 사용자에게 몇 개의 텍스트 상자를 보여주는 뷰에 해당합니다. 사용자가 뷰에 있는 "로그인" 버튼을 클릭할 경우, 사용자가 입력한 '이메일 주소'와 '비밀번호'를 담고 있는 "로그인시도(loginAttempt)"라는 이벤트를 만들게 됩니다. 

사용자에게 보여줘야 하거나, 사용자가 조작해야 할 것들은 반드시 뷰를 통해 제공되어야 합니다. 애플리케이션의 상태를 이해하기 쉽게 나타내야 할 뿐 아니라, 끊임 없는 사용자의 조작을 잘 처리하여 의미 있는 이벤트로 만들어야 합니다. 

뷰는 모델을 직접 변경하지 않고, 오퍼레이션에 이벤트를 보내게 됩니다. 그리고 모델에 의해 발생된 이벤트를 통해 변경 사항을 알게 됩니다.


Events

사용자가 로그인을 클릭했을 때 해당 뷰는 "로그인시도"라는 이벤트를 보내게 됩니다. 그리고 로그인 오퍼레이션이 완료될 경우, "현재사용자(currentUser)" 모델이 변경되었음을 알리는 이벤트를 애플리케이션에 보내게 됩니다. 

이벤트에 대한 리스닝(listening)은 MOVE (그리고 MVC)로 하여금 제어의 역전(Inversion of Control)이 가능케 합니다. 즉, 어떠한 뷰를 업데이트 해야 할지 모델이 알지 못하더라도, 뷰를 업데이트 할 수 있게 됩니다. 이는 컴포넌트들이 서로 간섭하지 않고도 연결되어 작동할 수 있게 해주는 매우 강력하고 추상적인 기법입니다.


Why now?

MVC 패턴을 적용하는 게 나쁘다고 말하는 건 아닙니다. 지난 수십 년 간,  대규모의 애플리케이션을 만드는 데 적용된 MVC 패턴은 매우 성공적이었으니까요. 하지만 MVC 패턴이 만들어진 이후로도, 많은 프로그래밍 기법들이 유명세를 탔습니다. 클로저(혹은 익명 블록)가 없었다면 이벤트 바인딩은 매우 힘들었을 겁니다. 그리고 deferrables(deferreds 혹은 promises) 가 없었다면, 개별 오퍼레이션을 객체로 다루는 아이디어는 생겨나지도 못했을 겁니다.


마치며

물론 MVC 패턴은 훌륭합니다. 다만, 몇십 년 전의 예전 기술로 만들어졌다는 점을 말하고 싶습니다. 

MOVE는 현재 우리가 사용하는 새로운 도구들을 더 잘 사용할 수 있게 해주는 업데이트일 뿐입니다.


추신

이러한 생각을 한 건 비단 저 뿐만이 아닐 겁니다. 

만약 MOVE에 동의하신다면, objectifyinteractions를 활용하셔서 MVC 애플리케이션에 MOVE의 장점을 추가해보세요. 

이와 관련하여 추천하고 싶거나 알고 있는 링크가 있다면 여기로 알려주시기 바랍니다.


추추신

이 포스트는 여기 저기에 일본어로 번역이 되었으며, 러시아어, 스페인어로도 번역이 되었습니다. 고마워요!

저작자 표시
신고
Posted by 우너효

ListView나 GridView를 구현할 때, overlap 되어 있는 view에 가려지게 하지 않기 위해 padding 값을 주는 경우가 있다.


스크롤을 통해 해당 overlap 된 View를 사라지게끔 할 수 있는데, 이 때 사라진 View로 인해 넣어준 padding 범위까지 ListView나 GridView의 내용을 보여주고 싶으면


clipToPadding:false


속성을 지정해주면 된다







적용 후 그리드뷰의 모습. 상단에 Padding이 적용되어 살짝 아래로 내려와 있다.







기존에 GridView의 상단에 위치해 있던 Spinner는 스크롤 시 사라지고,

ClipToPadding:false 로 인해 GridView의 내용이 스크롤 시 상단의 Padding영역까지 모두 보여지게 된다.



저작자 표시 비영리 동일 조건 변경 허락
신고
Posted by 우너효


티스토리 툴바