devlog of ShinJe Kim

[TIL] 2020-01-31

|

Today I Leaned

  • Spinner에 라디오 버튼을 구현하는 법을 찾아 한참 삽질했다. 결론은, 아래와 같이 하면 된다.

activity_main.xml (스피너를 넣을 화면에 스피너 생성)

<!--activity_main.xml-->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Spinner
        android:id="@+id/spinner"
        android:layout_width="200dp"
        android:layout_height="50dp"
        android:spinnerMode="dialog"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

스피너에 넣을 값을 values>strings.xml에 저장(파일명은 상관없음)

<!--strings.xml-->
<resources>
    <string-array name="stringArray">
        <item>apple</item>
        <item>banana</item>
        <item>citrus</item>\
    </string-array>
</resources>

메인 액티비티에서 어답터로 스피너를 생성하고, 값을 넣어준다. 나는 이 부분에서 삽질을 했다. spinner에 radio button을 나타나게 하는 방법을 갖가지 검색어로 구글링했을 때에는 adapter.setDropDownViewResourceandroid.R.layout.simple_spinner_dropdown_item 레이아웃을 사용하여 아이템을 보여주니 라디오버튼이 나왔었다. 하지만 이것은 옛날 자료였고 라이브러리가 변경된 것이다..ㅜ 지금은 아래와 같이 android.R.layout.simple_list_item_single_choice 혹은 android.R.layout.simple_list_item_single_choice 레이아웃을 적용해주면 스피너 아이템에 라디오버튼이 나타난다. (검색 범위를 2015년부터로 바꾸고나서 바로 찾았다. 진작 했으면 시간을 절약했을것을.. 반성하자)

class MainActivity : AppCompatActivity(), AdapterView.OnItemSelectedListener {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        ArrayAdapter.createFromResource(this, R.array.stringArray, android.R.layout.simple_spinner_item).also { adapter ->
            adapter.setDropDownViewResource(android.R.layout.simple_list_item_single_choice)
            spinner.adapter = adapter
            spinner.onItemSelectedListener = this
        }
    }
}

[TIL] 2019-01-30

|

Today I Leaned

  • 안드로이드에서는 다양한 기기를 지원하기때문에 기존의 absolute layout은 deprecated 되었고, 현재는 다양한 기기의 화면 사이즈에 반응형으로 디자인할 수 있는 LinearLayout, ConstraintLayout, GridLayout을 사용할 수 있다.
  • FrameLayout, ConstraintLayout, LinearLayout은 안드로이드 UI를 만들 때 가장 많이 사용되는 UI이다. FrameLayout은 오직 하나의 child view만 가질 때 적합하다. LinearLayout은 수직/수평으로 뷰들을 쌓을 때 유용하며, 화면에 비례하게 영역을 분할해준다. ConstraintLayout은 뷰들의 위치를 부모로부터 상대적으로 지정할 수 있도록 해준다.
  • zsh 쉘에서 adb 환경 변수를 설정하느라 이것 저것 건드렸더니 갑자기 뭘 해도 command not found가 나왔다. 아침부터 계속 삽질했는데 문제는 zsh의 zprofile의 환경변수였다.

    .bash_profile의 환경변수를 아래와 같이 작성한다.

    export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
    

    그리고 .zprofile에 아래와 같은 코드를 작성하여 .bash_profile의 설정을 불러오도록 한다.

    source ~/.bash_profile
    

    이렇게 하니 zsh 쉘에서 내가 썼던 명령어들을 다시 쓸 수 있게 되었다.

[TIL] 2019-01-29

|

Today I Leaned

<textview
    android:id = "@+id/this_is_id"/>
  • 위와 같은 안드로이드 xml에서 @ 기호는 ‘해당 문자를 스트링으로 받지 말아줘’ 라는 의미이며, 동시에 안드로이드 리소스 중 해당 컨텐츠를 찾는 역할을 한다.
  • + 기호는 ‘만약 이것이 존재하지 않으면 새로 만들어줘’ 라는 의미이다.
findViewById(R.id.this_id_id);
  • 위의 코드에서 R은 안드로이드 tool chain에서 자동으로 생성해주는 클래스이다.
  • 자바에서는 변수 이름에 슬래시(/)를 허용하지 않기 떄문에 id뒤에 .으로 변수명을 연결하였다.

  • 안드로이드에서 chip 혹은 chipgroup을 사용하려면 styles.xmlAppTheme이 아래와 같이 Material로 되어있어야 한다. 나는 Appcompat으로 되어있었는데 에러가 발생하고 Material로 바꾸라는 메시지가 로그에 찍혔다. material 테마를 사용하기 위해서는 material 라이브러리를 gradle에 추가해야 한다. ```xml

[TIL] 2019-01-23

|

Today I Leaned

  • 안드로이드 Activity란?

    Responsible for creating the window that your application uses to draw and receive events from the system. Only the Activity is an Android Component and responsible for displaying the application user interface.

    (응용 프로그램이 시스템에서 이벤트를 가져오고받는 데 사용하는 window를 생성한다. Activity는 Android 컴포넌트이며 애플리케이션 사용자 인터페이스를 보여줍니다.)

  • The Android Manifest is used to register components with the Android framework. (안드로이드 매너페스트는 안드로이드 프레임 워크의 컴포넌트를 등록하는 데에 사용된다.)

  • 안드로이드에는 res라는 리소스를 분리한 디렉토리가 있다. 이는 애플리케이션의 외형을 업데이트하는 것을 용이하게 한다. 코드의 수정 없이 이미지 사이즈나 언어를 변경할 수도 있다. 이는 다양한 기기를 지원하는 안드로이드에서 매우 중요한 부분이다.

[TIL] 2019-01-20

|

객체지향 개발 5대 원리 SOLID

  1. SRP(Single Responsibility Principle; 단일 책임 원칙)

    : 한 클래스는 하나의 책임만을 가져야 한다. 모든 클래스의 하나의 책임만 가지며, 클래스는 그 책임을 완전히 캡슐화(encapsulation)해야한다. 클래스가 제공하는 모든 기능은 이 책임 원칙에 부합해야 한다.

    로버트 마틴은 ‘책임’을 ‘변경하려는 이유’ 로 정의하였다. 어떤 클래스나 모듈은 변경하려는 단 하나의 이유만을 가져야한다고 말한다. 한 클래스를 하나의 관심사에 집중하도록 유지하는 것이 중요한 이유는, 이것이 클래스를 더욱 튼튼하게 만들기 때문이다. 여러가지 관심사가 하나의 클래스에 있다면, 하나의 책임을 수정할 때 다른 코드가 망가질 위험이 높다.

  2. OCP(Open-Closed Principle; 개방 폐쇄 원칙)

    : 소프트웨어 개체(클래스, 모듈, 함수 등등)는 확장에는 열려(open)있으나 변경에는 닫혀(close)있어야 한다. 프로그래머는 추상화에 의존해야하며 구체화에 의존하면 안된다. 의존성 주입은 이 원칙을 따르는 방법 중 하나이다. 소프트웨어 개발 작업에 이용된 많은 모듈 중에 하나에 수정을 가할 때 그 모듈을 이용하는 다른 모듈을 모두 고쳐야 한다면, 이와 같은 프로그램은 수정하기 어렵다. 개발-폐쇄 원칙은 시스템의 구조를 올바르게 리팩토링하여 나중에 이와 같은 유형의 변경이 더 이상의 수정을 유발하지 않도록 하는 것이다.

    아래는 개방-폐쇄 원칙의 두 가지 속성이다.

    • 확장에 대해 열려 있다: 애플리케이션의 요구 사항이 변경될 때, 이 변경에 맞게 새로운 동작을 추가해 모듈을 확장할 수 있다.
    • 수정에 대해 닫혀 있다: 모듈의 소스코드나 바이너리 코드를 수정하지 않아도 모듈의 기능을 확장하거나 변경할 수 있다. 그 모듈의 실행 가능한 바이너리 형태나 링크 가능한 라이브러리(ex. 자바의 .jar)를 건드릴 필요가 없다.
  3. LSP(The LIskov Substitution Principle; 리스코브 치환 원칙)

    : 프로그램의 객체는 프로그램의 정확성을 꺠뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다. 치환성(substitutability)은 객체 지향 프로그래밍의 원칙이다. 컴퓨터 프로그램에서 자료형 S가 자료형 T의 하위형이라면 필요한 프로그램의 속성(정확성, 수행하는 업무 등)의 변경 없이 자료형 T의 객체를 자료형 S의 객체로 교체(치환)할 수 있어야 한다는 뜻이다. (이부분이 이해가 안간다. 자바에서 자동으로 다운캐스팅이 되는 것…?)

  4. ISP(Interface Segregation Principle; 인터페이스 분리 원칙)

    : 클라이언트는 자신이 이용하지 않는 메서드에 의존하지 않아야 한다. 큰 덩어리의 인터페이스들을 구체적이고 작은 단위들로 분리시킴으로써 클라이언트들이 꼭 필요한 메서드들만 이용할 수 있게 하는 원칙이다. 이러한 작은 단위들을 역할 인터페이스 라고도 한다. 인터페이스 분리 원칙을 통해 시스템의 내부 의존성을 약화시켜 리팩토링, 수정, 재배포를 쉽게 할 수 있다.

  5. DIP(Dependency Inversion Principle; 의존성 역전 원칙)

    : 의존성 역전 원칙은 크게 두 가지 내용을 담고 있다.

    • 첫째, 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
    • 둘째, 추상화는 세부 사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.

    이러한 원칙은 상위 계층(정책 결정)이 하위 계층(세부 사항)에 의존하는 전통적인 의존 관계를 반전(역전)시킴으로써 상위 계층이 하위 계층의 구현으로부터 독립되게 할 수 있다.

정보 은닉과 캡슐화의 차이점?

이펙티브 자바 아이템 15(클래스와 멤버의 접근 권한을 최소화하라)를 보다가 정보 은닉과 캡슐화가 자꾸 혼동되었다. 구글에 ‘information hiding vs encapsulation’이라고 검색해보았다. 나같은 사람들을 위해 친절하게도 TechDifferences라는 웹사이트가 있었다. 아래는 이 웹사이트에 설명된 정보 은닉과 캡슐화의 차이점이다.

캡슐화란 클래스 내부에 멤버 데이터와 메서드의 구현을 감싸는 것을 의미한다. 클래스 안에 모든 데이터 멤버와 메서드의 구현이 캡슐화되어 있으면, 해당 클래스의 객체에서 수행하는 동작만 메서드의 이름으로 설명해주면 된다. 정보 은닉은 클래스의 멤버를 부적절하거나(illegal) 허가되지 않은 접근(unauthorized access)으로부터 보호하는 것을 의미한다.

정보 은닉과 캡슐화의 가장 큰 차이점은, 정보 은닉은 데이터의 보안에 중점을 두고 캡슐화는 시스템의 복잡성을 숨기는 데에 중점을 둔다는 것이다. 그 외의 차이점들은 아래의 표에 정리되어 있다.

비교 기준 정보 은닉 캡슐화
Basic 정보 은닉은 데이터의 보안과 복잡성을 감추는 것이다. 캡슐화는 시스템의 복잡성을 감추기 위해 데이터를 감싸는(wrap)것이다.
Focus 정보 은닉은 캡슐 내부 데이터를 사용하는 것을 금지/허용하는 것이 중점이다. 캡슐화는 복잡한 데이터를 감싸는 것이 중점이다.
Access Specifier 정보 은닉에서 데이터는 항상 private이며 외부에서 접근할 수 없다. 캡슐화에서 데이터는 private 혹은 public일수도 있다.
Process 정보 은닉은 프로세스이자 테크닉이다. 캡슐화는 정보 은닉의 부차적인 과정이다.

정보은닉(Information Hiding)

즉, (내가 이해한 바에 의하면..) 정보 은닉은 private 접근 제어자를 사용하여 클래스 외부에서 내부 데이터에 접근할 수 없도록 하는 것을 의미한다. 이펙티브 자바에 나온 정보은닉의 장점은 아래와 같다.

  • 시스템 개발 속도를 높인다. 여러 컴포넌트를 병렬로 개발할 수 있기 때문이다.
  • 시스템 관리 비용을 낮춘다. 각 컴포넌트를 더 빨리 파악하여 디버깅할 수 있고, 다른 컴포넌트로 교체하는 부담도 적기 때문이다.
  • 정보 은닉 자체가 성능을 높여주지는 않지만, 성능 최적화에 도움을 준다. 완성된 시스템을 프로파일링해 최적화할 컴포넌트를 정한 다음, 다른 컴포넌트에 영향을 주지 않고 해당 컴포넌트만 최적화할 수 있기 때문이다.
  • 소프트웨어 재사용성을 높인다. 외부에 거의 의존하지 않고 독자적으로 동작할 수 있는 컴포넌트라면 그 컴포넌트와 함께 개발되지 않은 낯선 환경에서도 유용하게 쓰일 가능성이 크기 때문이다.
  • 큰 시스템을 제작하는 난이도를 낮춰준다. 시스템 전체가 아직 완성되지 않은 상태에서도 개별 컴포넌트의 동작을 검증할 수 있기 때문이다.

참고 자료