안드로이드 개발자 기술 면접 중 나왔던 질문 정리

김흰돌·2023년 5월 18일
30

안드로이드 개발자(신입) 기술 면접을 보면서 받았던 질문들을 정리해본다.
면접을 진행한 회사는 8군데 정도 됐고 거기서 나왔던 질문들이다.

내가 쓴 글 중 Java, Kotlin, Android에 크게 상관없는 면접 질문들도 있지만 해당 주제에 대한 얘기 중 나왔던 질문이라 그냥 포함시켰다.
ex) Java 항목에 추상화에 대한 글, Android 항목에 동기와 비동기에 대한 글



Java

접근 제어자의 종류와 각 접근제어자에 대한 설명을 해주세요

  • private: 오직 선언된 클래스 내에서만 접근 가능합니다.
  • default: 같은 패키지 내에서만 접근할 수 있습니다.
  • protected: 같은 패키지 내의 클래스나 상속 관계에 있는 하위 클래스에서 접근할 수 있습니다. 패키지가 다른 경우에는 접근이 제한됩니다.
  • public: 가장 넓은 범위의 접근 제어자로, 어떤 클래스나 패키지에서든 접근할 수 있습니다.

SOLID 원칙에 대해 설명해주세요.

객체지향 프로그래밍에서 사용되는 다섯 가지 원칙의 앞글자를 딴 약어입니다. 각 원칙은 소프트웨어 설계를 유연하고 확장 가능하며 유지보수하기 쉽게 만들기 위해 고안되었습니다.

  • SRP (Single Responsibility Principle - 단일 책임 원칙): 클래스는 단 하나의 책임을 가져야 하며, 클래스의 변경 이유는 오직 하나여야 합니다.
  • OCP (Open-Closed Principle - 개방-폐쇄 원칙): 확장에는 열려 있어야 하고 변경에는 닫혀 있어야 합니다. 즉, 기존의 코드를 수정하지 않고도 기능을 추가하거나 변경할 수 있어야 합니다.
  • LSP (Liskov Substitution Principle - 리스코프 치환 원칙): 부모 클래스의 인스턴스는 언제나 자식 클래스의 인스턴스로 교체할 수 있어야 합니다. 이 원칙은 상속과 다형성을 올바르게 사용하기 위한 지침을 제공합니다.
  • ISP (Interface Segregation Principle - 인터페이스 분리 원칙): 클라이언트는 자신이 사용하지 않는 메서드에 의존하도록 강요받지 않아야 합니다. 따라서 인터페이스는 클라이언트에 필요한 기능만 포함해야 합니다.
  • DIP (Dependency Inversion Principle - 의존성 역전 원칙): 추상화에 의존해야 하며 구체화에는 의존하면 안 됩니다. 즉, 클래스는 구체적인 구현이 아니라 인터페이스나 추상 클래스와 같은 추상화에 의존해야 합니다.

추상화에 대해 설명해주세요.

  • 추상화는 프로그래밍에서 복잡한 시스템이나 개념을 단순화하고 필수적인 요소만을 강조하여 모델링하는 과정입니다. 추상화를 통해 세부 사항을 숨기고 핵심 개념을 이해하기 쉽게 만들 수 있습니다. 예를 들어, 추상화를 사용하면 객체 지향 프로그래밍에서 클래스를 정의하고 객체를 생성하여 문제를 해결할 수 있습니다. 추상화는 코드의 재사용성을 높이고 유지 보수를 용이하게 하며, 프로그램의 이해와 개발을 단순화 하는 데 도움이 됩니다.

클래스와 객체는 무엇일까요?

  • 클래스는 객체 지향 프로그래밍에서 객체를 생성하기 위한 템플릿 또는 청사진으로 볼 수 있습니다. 클래스는 객체의 상태를 나타내는 속성(멤버 변수)과 행위를 정의하는 메서드로 구성됩니다.
  • 객체는 클래스의 인스턴스로, 실제로 메모리에 할당된 것을 의미합니다. 객체는 클래스의 특정한 속성 값을 가지며, 클래스에서 정의한 메서드를 호출하여 동작합니다. 즉, 클래스는 추상적인 개념이고, 객체는 실제로 존재하는 구체적인 인스턴스입니다.



Kotlin

Java와 Kotlin의 차이는?

  • 문법과 표현력:
    - 코틀린은 보다 간결하고 표현력이 높은 문법을 가지고 있습니다. 변수 선언과 초기화, 함수 선언, 컬렉션 조작 등이 간단하고 명확하게 작성할 수 있습니다.
  • null 처리:
    - 자바에서는 변수에 null을 할당할 수 있고, 이로 인해 NullPointerException이 발생할 수 있습니다. 하지만 코틀린은 타입 시스템을 통해 null 안전성을 제공하며, 변수의 타입에 null을 허용할지 여부를 명시적으로 지정합니다. 또한 널 포인터 예외를 방지하기 위해 특별한 문법과 기능을 제공합니다.
  • 함수형 프로그래밍:
    - 코틀린은 함수형 프로그래밍을 지원하는 기능을 갖추고 있습니다. 함수를 일급 객체로 다루고, 람다식과 고차 함수를 사용하여 함수형 스타일의 코드를 작성할 수 있습니다.
    - 자바 8부터는 람다식과 스트림 API 등 몇 가지 함수형 프로그래밍 요소를 도입했지만, 코틀린은 좀 더 강력하고 통합된 함수형 프로그래밍 지원을 제공합니다.
  • 확장 함수와 프로퍼티:
    - 코틀린은 확장 함수(extension function)와 확장 프로퍼티(extension property)를 사용하여 기존 클래스에 메서드와 프로퍼티를 추가할 수 있는 기능을 제공합니다. 이를 통해 외부 라이브러리의 클래스를 수정하지 않고도 기능을 확장할 수 있습니다.

val과 var의 차이는 무엇일까요?

변수를 선언하는 데 사용되는 키워드입니다.

  • val은 value의 약자로, 불변 변수를 선언할 때 사용됩니다. 한 번 초기화되면 값을 변경할 수 없으며, 자바에서의 final 변수와 유사합니다.
  • var는 variable의 약자로, 가변 변수를 선언할 때 사용됩니다. 이 변수는 초기화 후에도 값을 변경할 수 있습니다.

kotlin에서 Null을 어떻게 처리하나요?

  • Nullable 타입 선언
    - 변수 또는 반환 타입에 ?를 붙여 Nullable 타입을 선언합니다. Nullable 타입은 해당 변수 또는 표현식이 null일 수 있다는 것을 나타냅니다.
    var name: String? = null
  • 안전 호출 연산자
    - Nullable 객체의 프로퍼티나 메서드에 접근할 때, 안전 호출 연산자를 사용하여 null 체크를 수행합니다. 이 연산자는 객체가 null이 아닌 경우에만 접근을 시도하고, null인 경우에는 null을 반환합니다.
    val length = name?.length
  • 엘비스 연산자
    - Nullable 객체가 null인 경우, 엘비스 연산자를 사용하여 기본값을 지정할 수 있습니다. 엘비스 연산자는 Nullable 객체가 null인 경우, 우측에 있는 기본값을 반환합니다.
    val length = name?.length ?: 0
  • 안전한 캐스트
    - Nullable 객체를 캐스트할 때, 안전한 캐스트를 사용하여 캐스트가 실패할 경우 null을 반환합니다.
    val number: Any? = "123"
    		val intValue: Int? = number as? Int
  • Non-null 단언
    - Nullable 객체를 Non-null 타입으로 강제로 캐스트합니다. 이 연산자는 객체가 null인 경우 NullPointerException을 발생시킬 수 있으므로 주의해야 합니다.
    val length = name!!.length

Set과 Map의 차이는 무엇일까요?

  • Set은 중복 요소를 허용하지 않는 컬렉션입니다. 동일한 요소가 한 번만 포함됩니다. Set은 주로 고유한 값의 컬렉션을 관리하고자 할 때 사용됩니다. Set은 순서가 정의되지 않은 컬렉션이므로, 요소의 순서에 의존하지 않는 상황에서 유용합니다.
  • Map은 키-값 쌍을 관리하는 컬렉션입니다. 각각의 요소는 고유한 키와 그에 대응하는 값으로 구성됩니다. Map은 주로 데이터를 검색하고 조작하기 위해 키를 사용하는 상황에서 사용됩니다. Map은 키를 기준으로 중복을 허용하지 않습니다. 특정 키에 대응하는 값은 유일해야 합니다. 하지만 값은 중복되어도 상관없습니다. 또한, Map은 순서가 정의되지 않은 컬렉션입니다. 키-값 쌍의 순서는 보장되지 않으며, 키를 사용하여 값을 검색하고 수정하는 데 사용됩니다.

interface와 abstract의 특징과 차이점에 대해 설명해주세요

  • interface:
    - 클래스는 여러 개의 인터페이스를 구현할 수 있습니다.
    - 인터페이스는 다른 클래스들 간에 공통적인 동작을 정의하는데 사용됩니다.
    - 인터페이스는 멤버 변수를 가질 수 없고, 오직 추상 메서드, 디폴트 메서드, 정적 메서드, 추상 프로퍼티, 상수 등을 선언할 수 있습니다.

  • abstract:
    - 하나 이상의 추상 메서드를 포함하는 클래스입니다. 추상 메서드는 선언만 있고, 구현 내용은 없습니다.
    - 한 클래스는 추상 클래스를 상속받으면서 동시에 다른 클래스를 상속받을 수 없습니다.
    - 추상 클래스는 공통된 특성과 동작을 가지는 클래스들의 베이스로 사용됩니다.
    추상 클래스는 멤버 변수, 일반 메서드, 추상 메서드 등을 가질 수 있습니다.

  • 차이점:
    구현 내용의 존재 여부: 인터페이스는 메서드의 선언만 있으므로 구현 내용이 없습니다. 추상 클래스는 추상 메서드 뿐만 아니라 일반 메서드의 구현 내용도 가질 수 있습니다.

    다중 상속: 인터페이스는 다중 상속을 지원합니다. 클래스에서 여러 개의 인터페이스를 구현할 수 있습니다. 추상 클래스는 다른 클래스를 상속받을 때 다중 상속이 불가능합니다.

    생성자의 존재 여부: 인터페이스는 생성자를 가질 수 없습니다. 추상 클래스는 생성자를 가질 수 있습니다.

    인스턴스화: 인터페이스는 직접 객체를 생성할 수 없으며, 클래스에서 인터페이스를 구현하여 사용합니다. 추상 클래스도 직접 객체를 생성할 수 없으며, 상속을 통해 하위 클래스에서 구체화되어야 합니다.

Scope function 중 어떤 걸 프로젝트에 적용해 보셨나요?, 결과값은 뭐가 나오나요?

프로젝트에선 let, run, apply를 사용해봤다고 대답했음.
Scope function이라는 특별한 함수들이 제공되며, 이러한 함수들은 객체의 범위(scope) 내에서 코드를 더 간결하고 가독성 있게 작성할 수 있도록 도와줍니다.

  • let: let은 nullable 객체를 안전하게 처리하고, null이 아닌 경우에만 블록 내에서 해당 객체를 사용할 수 있습니다. let 함수의 결과값은 블록 내의 마지막 표현식의 결과입니다.
  • run: run은 객체의 컨텍스트 내에서 코드 블록을 실행합니다. let과 마찬가지로 nullable 객체를 안전하게 처리할 수 있습니다. run 함수의 결과값은 블록 내의 마지막 표현식의 결과입니다.
  • with: with은 특정 객체의 컨텍스트 내에서 코드 블록을 실행합니다. with 함수는 객체 자체를 전달받아 사용하므로, 객체에 대한 참조를 명시적으로 제공할 필요가 없습니다. with 함수의 결과값은 블록 내의 마지막 표현식의 결과입니다.
  • apply: apply는 객체의 속성을 초기화하거나 수정하는 데 사용됩니다. apply 함수는 객체 자체를 전달받아 사용하며, 객체의 속성에 연속적으로 접근하여 값을 설정할 수 있습니다. apply 함수의 결과값은 해당 객체 자체입니다.
  • also: also는 객체를 받아서 사용하는 let과 유사하지만, also는 해당 객체를 반환하지 않고 전달받은 객체를 그대로 유지한 채로 다른 용도로 사용할 수 있습니다. also 함수의 결과값은 전달받은 객체 자체입니다.



Android

Activity의 생명주기에 대해 설명해주세요.

  • onCreate(): 액티비티가 생성될 때 호출되는 메서드입니다. 초기화 작업이나 인터페이스 설정 등을 수행합니다.
  • onStart(): 액티비티가 화면에 보여지기 직전에 호출되는 메서드입니다. 액티비티가 사용자에게 보여지기 시작합니다.
  • onResume(): 액티비티가 사용자와 상호작용을 시작하고 활동 상태에 들어갈 때 호출되는 메서드입니다. 액티비티가 포그라운드에 있으며 사용자 입력을 받을 수 있습니다.
  • onPause(): 액티비티가 일시 중지되거나 다른 액티비티가 화면을 가리는 등 포그라운드에서 벗어나기 전에 호출되는 메서드입니다. 데이터 저장이나 네트워크 연결 해제 등의 작업을 수행합니다.
  • onStop(): 액티비티가 더 이상 사용자에게 보여지지 않고 화면에서 완전히 가려질 때 호출되는 메서드입니다. 자원 해제나 정리 작업을 수행합니다.
  • onRestart(): 액티비티가 onStop() 상태에서 다시 시작되기 전에 호출되는 메서드입니다. 일시 중지된 액티비티를 다시 시작할 때 필요한 초기화 작업을 수행합니다.
  • onDestroy(): 액티비티가 소멸될 때 호출되는 메서드입니다. 액티비티에 할당된 자원을 해제하고 종료 작업을 수행합니다.

Fragment의 생명주기에 대해 설명해주세요.

  • onAttach(): 프래그먼트가 액티비티에 연결될 때 호출되는 메서드입니다. 프래그먼트가 액티비티에 붙을 때 필요한 초기화 작업을 수행합니다.
  • onCreate(): 프래그먼트가 생성될 때 호출되는 메서드입니다. 초기화 작업이나 인터페이스 설정 등을 수행합니다.
  • onCreateView(): 프래그먼트의 레이아웃을 그리는 메서드입니다. 프래그먼트의 UI를 생성하고 반환합니다.
  • onViewCreated(): onCreateView() 후에 호출되는 메서드로, 프래그먼트의 UI가 만들어진 후에 호출됩니다. UI 관련 작업을 수행합니다.
  • onStart(): 프래그먼트가 화면에 보여지기 직전에 호출되는 메서드입니다. 프래그먼트가 사용자에게 보여지기 시작합니다.
  • onResume(): 프래그먼트가 사용자와 상호작용을 시작하고 활동 상태에 들어갈 때 호출되는 메서드입니다. 프래그먼트가 포그라운드에 있으며 사용자 입력을 받을 수 있습니다.
  • onPause(): 프래그먼트가 일시 중지되거나 다른 프래그먼트가 화면을 가리는 등 포그라운드에서 벗어나기 전에 호출되는 메서드입니다. 데이터 저장이나 네트워크 연결 해제 등의 작업을 수행합니다.
  • onStop(): 프래그먼트가 더 이상 사용자에게 보여지지 않고 화면에서 완전히 가려질 때 호출되는 메서드입니다. 자원 해제나 정리 작업을 수행합니다.
  • onDestroyView(): 프래그먼트의 UI가 소멸될 때 호출되는 메서드입니다. UI와 관련된 리소스를 해제합니다.
  • onDestroy(): 프래그먼트가 소멸될 때 호출되는 메서드입니다. 프래그먼트에 할당된 자원을 해제하고 종료 작업을 수행합니다.
  • onDetach(): 프래그먼트가 액티비티와의 연결이 끊길 때 호출되는 메서드입니다. 프래그먼트와 액티비티 간의 연결을 해제합니다.

안드로이드 4대 컴포턴트에 대해 설명해주세요.

액티비티(Activity)

  • 액티비티는 사용자 인터페이스(UI)를 가지며, 사용자와 상호작용하는 화면을 나타냅니다.
  • 예를 들어, 앱의 로그인 화면, 설정 화면, 메인 화면 등이 액티비티로 구현됩니다.
  • 액티비티는 사용자 입력을 처리하고, 다른 액티비티와의 화면 전환을 관리하는 역할을 수행합니다.

서비스(Service)

  • 서비스는 백그라운드에서 실행되는 컴포넌트로, 사용자 인터페이스를 갖지 않습니다.
  • 주로 백그라운드에서 오래 실행되는 작업을 처리하기 위해 사용됩니다.
  • 예를 들어, 음악 재생, 네트워크 요청, 데이터 동기화 등을 처리하는데 사용될 수 있습니다.
  • 서비스는 앱이 활성화되지 않은 상태에서도 실행될 수 있습니다.

브로드캐스트 리시버(Broadcast Receiver)

  • 브로드캐스트 리시버는 안드로이드 시스템에서 발생하는 브로드캐스트 메시지를 수신하는 컴포넌트입니다.
  • 브로드캐스트 메시지는 시스템 이벤트(예: 배터리 부족 경고, 시간 변경 등)나 다른 애플리케이션에서 발생한 메시지를 포함할 수 있습니다.
  • 브로드캐스트 리시버는 이러한 메시지를 수신하고, 해당 이벤트에 대한 반응을 수행합니다.
  • 예를 들어, 충전기가 연결되었을 때 알림을 표시하거나, SMS 메시지를 수신했을 때 알림을 표시하는 등의 작업을 수행할 수 있습니다.

콘텐트 프로바이더(Content Provider)

  • 콘텐트 프로바이더는 데이터를 관리하고 다른 애플리케이션과 데이터를 공유하기 위한 인터페이스를 제공합니다.
  • 데이터베이스, 파일, 네트워크 등 다양한 데이터 소스에 접근하여 데이터를 읽고 콘텐트 프로바이더는 데이터를 읽고 쓰는 기능을 제공하며, 다른 애플리케이션에서 이 데이터에 접근할 수 있도록 합니다.
  • 다른 애플리케이션은 콘텐트 프로바이더를 통해 데이터를 쿼리하거나 수정할 수 있습니다.
  • 예를 들어, 주소록 애플리케이션의 경우 콘텐트 프로바이더를 통해 연락처 정보를 다른 애플리케이션과 공유할 수 있습니다.
  • 다른 애플리케이션은 콘텐트 프로바이더를 사용하여 주소록에 있는 연락처를 검색하거나 새로운 연락처를 추가할 수 있습니다.
  • 이를 통해 데이터의 일관성과 보안을 유지하면서 애플리케이션 간의 데이터 공유가 가능해집니다.

MVC, MVP, MVVM의 특징에 대해 설명해주세요.

MVC
특징:

  • 애플리케이션을 모델, 뷰, 컨트롤러 세 가지 구성 요소로 분리합니다.
  • 모델은 데이터와 비즈니스 로직을 처리하고, 뷰는 사용자 인터페이스를 표시하며, 컨트롤러는 사용자 입력을 처리합니다.
  • 분리된 구성 요소로 인해 유지보수와 확장성이 용이합니다.

장점:

  • 코드의 재사용성이 높아집니다.
  • 테스트가 용이합니다.
  • 다양한 플랫폼에 적용할 수 있는 범용적인 패턴입니다.

단점:

  • 컨트롤러가 비대해지거나 모델과 뷰 간의 복잡한 상호작용이 발생할 수 있습니다.
  • 데이터 흐름이 복잡해지고 유연성이 제한될 수 있습니다.

MVP

특징:

  • 애플리케이션을 모델, 뷰, 프레젠터 세 가지 구성 요소로 분리합니다.
  • 모델은 데이터와 비즈니스 로직을 처리하고, 뷰는 사용자 인터페이스를 표시하며, 프레젠터는 뷰와 모델 사이의 중간 역할을 수행합니다.
  • 뷰와 프레젠터 사이에 인터페이스를 통한 느슨한 결합을 유지합니다.

장점:

  • 뷰와 모델 간의 강한 의존성을 해결하여 테스트와 유지보수가 용이합니다.
  • 코드의 재사용성과 모듈화가 촉진됩니다.
  • UI 로직과 비즈니스 로직을 분리할 수 있습니다.

단점:

  • 구현하기에 따라 프레젠터의 역할과 책임을 명확히 정의하기 어려울 수 있습니다.
  • View와 Presenter 사이의 인터페이스 설계에 신경을 써야 합니다.

MVVM

특징:

  • 애플리케이션을 모델, 뷰, 뷰모델 세 가지 구성 요소로 분리합니다.
  • 모델은 데이터와 비즈니스 로직을 처리하고, 뷰는 사용자 인터페이스를 표시하며, 뷰모델은 뷰와 모델 사이의 매개체 역할을 수행합니다.
  • 뷰모델은 뷰와 완전히 분리되어 있으며, 데이터 바인딩을 통해 뷰와의 동기화를 처리합니다.
  • 뷰모델은 뷰에 대한 상태와 동작을 관리하고, 사용자 입력 및 이벤트 처리를 담당합니다.

장점:

  • 데이터 바인딩을 통해 뷰와 모델 사이의 동기화를 자동으로 처리합니다.
  • 유연하고 확장 가능한 구조를 제공하여 UI와 비즈니스 로직의 분리를 촉진합니다.
  • 명령(Command) 패턴을 통해 사용자 인터랙션을 처리할 수 있습니다.
  • UI 개발자와 비즈니스 로직 개발자 간의 협업을 용이하게 합니다.

단점:

  • 초기 학습 곡선이 높을 수 있으며, 복잡한 애플리케이션에서 구현하기에는 오버헤드가 발생할 수 있습니다.
  • 뷰모델이 많은 코드를 포함할 수 있으며, 관리가 어려울 수 있습니다.
  • 애플리케이션 규모가 작거나 단순한 경우에는 과도한 추상화일 수 있습니다.

개인적으로 MVVM 아키텍처를 사용한 이유, 본인이 느낀 장점에 대해 말해주세요.

  • 개인적인 프로젝트 경험을 통한 대답을 함

의존성 주입을 써봤나요?, 왜 사용하셨나요?

  • 저는 Hilt를 사용했다고 말 했고 이유는 Google에서 지원하는 라이브러리이기 때문에 사용했다고 말했습니다. 사용한 이유로는 코드의 간결성을 위주로 얘기했습니다.

synchronized란?

  • synchronized는 멀티스레드 환경에서 동기화를 위해 사용되는 키워드입니다. 동시에 여러 스레드가 접근할 수 있는 공유 자원에 대한 안전한 접근을 보장하기 위해 사용됩니다.

serializable parcelable의 특징과 차이점은 무엇일까요?

Serializable과 Parcelable은 Android에서 객체를 직렬화(serialize)하는 두 가지 인터페이스입니다. 이들은 객체를 바이트 스트림으로 변환하거나 바이트 스트림을 다시 객체로 변환하는 작업을 수행합니다.

  • 성능: Parcelable은 Serializable에 비해 더 빠릅니다. Serializable은 Java Reflection을 사용하여 객체를 직렬화하고 역직렬화하기 때문에 처리 과정에서 오버헤드가 발생합니다. Parcelable은 명시적으로 필드를 읽고 쓰는 데 집중하므로 성능이 향상됩니다.
  • 메모리 사용: Parcelable은 내부적으로 작동하기 위해 Android의 Binder 메커니즘을 사용합니다. 이로 인해 Parcelable은 객체를 직렬화하는 데 필요한 메모리 사용량을 줄일 수 있습니다. Serializable은 자바 직렬화 메커니즘을 사용하기 때문에 더 많은 메모리를 사용합니다.
  • 명시성: Parcelable은 직렬화 및 역직렬화 과정을 명시적으로 작성해야 합니다. 반면에 Serializable은 특별한 메서드 없이 직렬화됩니다. Parcelable은 개발자가 직렬화 및 역직렬화 방법을 명시적으로 작성해야 하므로 클래스의 구조 변경이 더 복잡할 수 있습니다.
  • 호환성: Serializable은 자바 직렬화 메커니즘을 사용하므로 객체를 직렬화하고 역직렬화하는 데에는 제약이 걸릴 수 있습니다. Serializable 클래스의 구조가 변경되면 역직렬화에 문제가 발생할 수 있습니다. Parcelable은 명시적으로 작성되므로 클래스 구조의 변경에 유연하게 대응할 수 있습니다.

사용해본 서드파티 라이브러리는 무엇이있나요?

본인이 사용한 서드파티 라이브러리를 미리 정리해가면 좋을 것 같습니다. 예상 못해서 순간 생각이 안 났음... 물론 결국 대답하긴 했습니다.

푸시 알림을 구현해보신적 있으신가요?

LiveData와 MutableLiveData의 차이와 실제 적용 사례를 말씀해주세요.

LiveData와 MutableLiveData의 주요 차이점은 데이터 변경 가능성입니다. LiveData는 읽기 전용이므로 외부에서 데이터를 수정할 수 없습니다. 반면에 MutableLiveData는 데이터를 수정할 수 있는 메서드를 제공하므로 데이터 변경이 가능합니다.

api 요청이 실패했을 때 어떻게 처리하셨나요?

다른 비동기 처리 라이브러리 말고 Coroutine을 사용하는 이유는 무엇일까요?

Coroutine은 비동기 처리를 위한 강력하고 유연한 도구입니다. Coroutine은 다른 비동기 처리 라이브러리와 비교하여 몇 가지 이점을 가지고 있습니다

  • 가독성: Coroutine은 동기 코드와 유사한 구문을 사용하여 비동기 작업을 표현할 수 있습니다. 이는 코드의 가독성을 향상시키고, 비동기 작업의 흐름을 이해하기 쉽게 만듭니다. 콜백 함수를 사용하는 기존의 비동기 처리 방식에 비해 코드의 복잡성을 줄일 수 있습니다.
  • 순차적인 코드 작성: Coroutine을 사용하면 순차적인 코드로 비동기 작업을 작성할 수 있습니다. 즉, 비동기 작업을 여러 단계로 나누고 각 단계를 순차적으로 실행할 수 있습니다. 이는 코드의 로직을 이해하기 쉽게 만들어주며, 에러 처리와 제어 흐름을 단순화할 수 있습니다.
  • 상태 유지: Coroutine은 상태를 유지할 수 있습니다. 이는 비동기 작업이 여러 단계에 걸쳐 이루어져야 하는 경우 매우 유용합니다. Coroutine은 각 단계에서 상태를 저장하고 다음 단계에서 이어서 실행할 수 있습니다. 이를 통해 비동기 작업의 일시 중지와 재개가 가능하며, 작업을 유지하면서도 코드를 단순화할 수 있습니다.
  • 에러 처리: Coroutine은 예외 처리를 간편하게 만듭니다. 일반적인 동기 코드와 마찬가지로 try-catch 구문을 사용하여 예외를 처리할 수 있습니다. 또한 Coroutine은 예외 처리를 작업의 단계별로 구성할 수 있어 디버깅과 오류 처리를 용이하게 합니다.
  • 확장성: Coroutine은 일반적인 비동기 작업 이외에도 다양한 동시성 작업에 유용합니다. 여러 개의 비동기 작업을 병렬로 실행하거나, 동기화를 필요로 하는 작업을 순차적으로 실행하는 등 다양한 동시성 패턴을 지원합니다.

Coroutine Flow도 사용해보셨나요?

Hilt 어노테이션에 대해 아는만큼 설명해주세요.

  • @HiltAndroidApp: 앱의 Application 클래스에 이 어노테이션을 지정하여 Hilt를 초기화합니다. Hilt가 앱의 컴포넌트 계층 구조를 구성하고 DI를 가능하게 합니다.
  • @AndroidEntryPoint: Android Framework 클래스들인 Activity, Fragment, Service, BroadcastReceiver 등에 이 어노테이션을 지정하여 Hilt가 해당 클래스의 종속성을 주입할 수 있도록 합니다.
  • @Inject: 이 어노테이션은 주입할 필드, 생성자 또는 메서드에 지정됩니다. Hilt는 해당 필드나 생성자에 대한 인스턴스를 자동으로 생성하고 주입합니다.
  • @Module: 이 어노테이션은 Hilt 모듈을 정의하는 클래스에 지정됩니다. 모듈은 주입할 종속성을 제공하는 방법을 정의합니다.
  • @Provides: 이 어노테이션은 모듈 내의 메서드에 지정됩니다. 해당 메서드는 종속성을 제공하고 Hilt에 의해 주입될 수 있도록 합니다.
  • @InstallIn: 모듈을 특정 컴포넌트에 설치하는 데 사용됩니다. @InstallIn 어노테이션은 모듈 클래스 위에 지정되며, @SingletonComponent, @ActivityRetainedComponent, @ActivityComponent 등과 같은 Hilt 컴포넌트를 대상으로 합니다.

Hilt에서 SingletonComponent의 의미는 무엇일까요?

Hilt에서 SingletonComponent는 Hilt 컴포넌트 중 하나로, 앱의 전역 범위에서 단일 인스턴스를 유지하는 데 사용되는 컴포넌트입니다. SingletonComponent는 앱의 라이프사이클 동안 한 번만 생성되고 유지됩니다.

MVVM의 ViewModel과 Jetpack의 AAC ViewModel은 어떤 차이가 있나요?

ViewModel은 MVVM 패턴의 일반적인 개념으로, 플랫폼에 독립적이며 View와 Model 간의 중개자 역할을 담당합니다. "AAC ViewModel"은 안드로이드 앱 개발을 위한 안드로이드 Jetpack 라이브러리의 일부로 제공되는 ViewModel 구현으로, 안드로이드의 수명 주기를 고려하여 ViewModel을 관리하고 부가 기능을 제공합니다.

Dispatchers의 종류와 특징은 무엇인가요?

안드로이드의 Dispatchers는 Kotlin Coroutine 라이브러리에서 사용되는 스레드 관리 도구입니다. 다양한 Dispatchers 종류가 있으며 각각 다른 특징을 가지고 있습니다

  • Dispatchers.Main: 안드로이드의 주 메인(UI) 스레드에서 동작합니다. UI 업데이트와 사용자 상호작용을 처리하기에 적합합니다.
  • Dispatchers.IO: 네트워크 요청, 파일 I/O 및 기타 입출력 작업을 처리하기에 적합한 스레드 풀입니다. 백그라운드에서 CPU를 많이 사용하지 않는 작업에 적합합니다.
  • Dispatchers.Default: CPU 집약적인 작업을 처리하기에 적합한 스레드 풀입니다. IO와 UI 작업을 포함한 일반적인 작업에 사용됩니다.
  • Dispatchers.Unconfined: 현재 실행중인 스레드를 그대로 사용합니다. 특정 스레드에 구속되지 않으므로 사용 시 주의가 필요합니다.

Compose를 사용해 보신 경험이 있으신가요?

공부 중이라고 말 함

Jetpack Navigation에서 popUpTo와 popUpToInclusive에 대해 설명해주세요.

popUpTo

  • 역방향 탐색 시 백 스택에서 제거할 목적지를 지정하는 속성입니다.
  • 목적지의 ID나 참조를 받을 수 있습니다. 이를 통해 역방향 탐색 중 해당 목적지 이후의 모든 프래그먼트를 제거할 수 있습니다.
  • popUpTo="@+id/destination_home"은 목적지가 destination_home인 프래그먼트까지 역방향으로 탐색할 때 destination_home 이후의 모든 프래그먼트를 제거합니다.

popUpToInclusive

  • 지정된 목적지를 포함하지 않고 그 이전의 모든 프래그먼트를 제거합니다. 이는 대상 목적지 자체도 백 스택에서 제거되는 의미입니다.
  • popUpTo의 대상 목적지를 포함하여 제거할 수 있습니다. 즉, popUpToInclusive="true"로 설정하면 대상 목적지도 함께 제거됩니다.

동기와 비동기에 대해 설명해주세요.

동기(Synchronous)와 비동기(Asynchronous)는 프로그래밍에서 작업의 진행 방식을 나타내는 용어입니다. 이들은 작업이 어떻게 실행되고 완료되는지를 기준으로 구분됩니다.

동기(Synchronous)

  • 동기 방식은 작업이 순차적으로 실행되며, 이전 작업이 완료될 때까지 다음 작업이 실행되지 않습니다. 간단히 말해, 작업 A가 작업 B에 의존하고 있을 때, 작업 A가 완료되기 전까지 작업 B는 시작되지 않습니다. 작업이 블로킹되고 대기 상태에 들어갈 수 있습니다.

비동기(Asynchronous)

  • 비동기 방식은 작업이 동시에 실행되고, 이전 작업이 완료되기를 기다리지 않고 다음 작업을 진행합니다. 각 작업은 별도의 스레드 또는 프로세스에서 실행되며, 작업 간에 상호 의존성이 없습니다. 작업이 블로킹되지 않고 계속 진행됩니다.

블로킹과 넌블로킹에 대해 설명해주세요.

블로킹(Blocking)과 넌블로킹(Non-blocking)은 작업을 어떻게 처리하는지를 나타내는 용어로서, 주로 입출력(IO) 작업과 관련됩니다.

블로킹(Blocking)

  • 블로킹 작업은 호출된 함수 또는 작업이 완료될 때까지 현재 실행 흐름이 멈추는 것을 의미합니다. 예를 들어, 파일을 읽을 때 블로킹 작업을 수행하면 파일이 완전히 읽혀질 때까지 다음 코드는 실행되지 않습니다. 블로킹 작업을 수행하는 동안은 대기 상태에 있을 수 있습니다.

넌블로킹(Non-blocking)

  • 넌블로킹 작업은 호출된 함수 또는 작업이 즉시 반환되며, 현재 실행 흐름이 멈추지 않고 계속 진행됩니다. 예를 들어, 파일을 비동기적으로 읽을 때 넌블로킹 작업을 수행하면 파일 읽기 요청 후 즉시 반환되며, 나중에 완료될 때 알림을 받을 수 있습니다. 넌블로킹 작업을 수행하는 동안 다른 작업을 수행할 수 있습니다.

BLE 연동을 해보신 적 있으신가요?

안드로이드 관련 CI/CD를 구축해보신적 있으신가요?



기타

Access 토큰과 Refresh 토큰의 특징에 대해 설명해주세요.

Access 토큰

  • 인증된 사용자의 리소스에 대한 접근 권한을 나타내는 토큰입니다.
  • 보통 짧은 유효 기간을 가지며, 일반적으로 몇 분에서 몇 시간 정도로 설정됩니다.
  • 클라이언트(일반적으로 애플리케이션 또는 웹사이트)는 Access 토큰을 API 요청의 인증 수단으로 사용합니다.
  • 서버는 Access 토큰을 확인하고 유효한 토큰인 경우 해당 사용자에 대한 요청을 처리합니다.
  • Access 토큰은 사용자의 권한과 범위(scope)를 포함하며, 보안을 위해 암호화되어 전송되어야 합니다.

Refresh 토큰

  • Access 토큰의 갱신을 위한 토큰입니다.
  • 일반적으로 Access 토큰보다 긴 유효 기간을 가지며, 보통 몇 일에서 몇 주 또는 몇 달 정도로 설정됩니다.
  • 클라이언트는 Access 토큰이 만료되었을 때 Refresh 토큰을 사용하여 새로운 Access 토큰을 얻을 수 있습니다.
  • 주로 사용자 인증 세션을 유지하고 재인증 없이 Access 토큰을 갱신하는 데 사용됩니다.

TCP와 UDP의 특징에 대해 설명해주세요.

TCP

  • 연결 지향적: 데이터를 전송하기 전에 연결을 설정하고, 신뢰성 있는 데이터 전송을 보장하기 위해 연결을 유지합니다.
  • 신뢰성: 패킷 손실이나 오류가 발생할 경우 재전송을 통해 데이터의 정확성과 순서를 보장합니다.
  • 흐름 제어와 혼잡 제어: TCP는 데이터의 흐름을 조절하고 네트워크 혼잡을 방지하기 위해 흐름 제어 및 혼잡 제어 메커니즘을 사용합니다.
  • 순차적 데이터 전송: 패킷의 순서를 보장하여 데이터를 원래의 순서대로 수신합니다.
    상대적으로 높은 지연: 연결 설정 및 신뢰성을 위한 추가적인 작업으로 인해 지연이 발생할 수 있습니다.

UDP

  • 비연결 지향적: 데이터 전송 전에 연결을 설정하지 않고, 데이터 그램을 즉시 전송합니다.
  • 신뢰성 없음: 패킷 손실이나 오류가 발생할 경우에도 재전송을 하지 않으므로 데이터 손실이 발생할 수 있습니다.
  • 흐름 제어나 혼잡 제어를 지원하지 않음: UDP는 흐름 제어나 혼잡 제어 메커니즘을 제공하지 않기 때문에 데이터 전송의 품질을 보장하지 않습니다.
  • 높은 성능: TCP에 비해 간단하며, 데이터의 전송 속도가 빠릅니다.
  • 다중 캐스트와 브로드캐스트 지원: UDP는 다중 캐스트와 브로드캐스트를 지원하여 하나의 송신자가 여러 개의 수신자에게 데이터를 전송할 수 있습니다.

Figma를 사용해보셨나요?

백엔드 개발자, 디자이너와 협업해보신적 있으신가요?

Git merge와 Rebase는 무엇일까요?

  • Git merge는 두 개의 독립적인 브랜치의 변경 내용을 하나의 새로운 커밋으로 합치는 작업을 수행합니다.
  • Git rebase는 커밋 히스토리를 재구성하는 작업을 수행합니다.

Git과 Git flow의 차이는 무엇인가요?

  • Git은 분산 버전 관리 시스템으로 개발자들이 협업하고 코드 변경 사항을 추적하는 데 사용되는 도구이며, Git flow는 Git을 기반으로 한 성숙한 브랜치 관리 모델로 개발과 배포를 체계적으로 관리하는 데 사용됩니다. Git flow는 Git의 기능을 사용하여 프로젝트의 개발 생명주기를 정의하는 방법입니다.

컴퓨터공학과를 전공하셨는데 어떤 과목이 제일 기억에 남나요?

컴퓨터공학과 커리큘럼 중에 안드로이드에 대한 수업도 받으셨나요?


개인 의견

그리고 마지막으로 만약 면접보러 가는 회사에서 실제 출시한 앱이 있다면 꼭!!! 설치해보고 사용해보고 가면 좋을 것 같다

저희 회사 앱 사용해 보신 적 있으세요? 라고 할 때 본인이 얼마나 이 회사에 관심이 있는지 보여줄 수 있는 좋은 기회라고 생각한다.

만약 면접관이 먼저 앱 사용 경험을 먼저 물어보지 않았을 땐 회사에 대한 질문을 받는 시간에 꼭

귀사의 앱을 사용해 봤는데~

하면서 먼저 궁금한 점을 적극적으로 물어보는 것도 좋을 것 같다.

1개의 댓글

comment-user-thumbnail
2023년 12월 20일

너무 너무 너무 감사합니다

답글 달기