1. 객체 지향 프로그래밍이란 무엇인가
객체 지향 프로그래밍 (OOP)이란?
OOP는 프로그램을 "객체" 단위로 나누어 구성하는 방법이다. 각 객체는 데이터를 가지고 있으며, 데이터를 처리하는 동작도 함께 정의된다. 안드로이드 앱을 생각해 보면, 여러 화면(Activity)이나 UI 요소(Button, TextView 등)들이 모두 객체이다. 버튼 객체는 "누른다"와 같은 동작을 가지고, 화면 객체는 "보여준다" 같은 동작을 한다. 이렇게 객체가 서로 소통하고 협력하면서 앱이 동작하게 된다.
객체 지향 프로그래밍의 주요 개념과 안드로이드 예시
- 캡슐화 (Encapsulation)
class UserViewModel : ViewModel() { private val _userName = MutableLiveData<String>() val userName: LiveData<String> get() = _userName fun updateUserName(newName: String) { _userName.value = newName } }
- 객체 지향에서 캡슐화란 데이터를 보호하고, 필요한 경우에만 외부에 공개하는 것이다. 안드로이드에서는 ViewModel을 예로 들 수 있다. ViewModel은 Activity나 Fragment에 데이터를 전달하되, 필요한 메서드를 통해서만 데이터를 수정할 수 있다. 이렇게 함으로써 UI와 데이터가 독립적으로 유지되고, 오류를 줄일 수 있다.
- 상속 (Inheritance)예를 들어, BaseActivity를 만들어 두고 다른 Activity들이 이를 상속하도록 할 수 있다.이제 개별 Activity들이 BaseActivity를 상속받아서 공통 기능을 그대로 사용할 수 있다.이렇게 하면 공통 기능을 BaseActivity에서 한 번만 정의해 놓고, 필요한 Activity에서 재사용할 수 있어서 코드 중복을 줄일 수 있다. BaseActivity가 변경되면 이를 상속받는 모든 Activity에도 적용되기 때문에 유지보수도 훨씬 편리해진다.
- // MainActivity: BaseActivity를 상속받아 공통 기능을 활용 class MainActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 공통 기능 사용 showLoading() logEvent("MainActivity Created") } }
- // BaseActivity: 공통 기능을 담은 부모 Activity open class BaseActivity : AppCompatActivity() { fun showLoading() { // 로딩 화면 표시 로직 } fun hideLoading() { // 로딩 화면 숨김 로직 } fun logEvent(eventName: String) { // 이벤트 로깅 처리 Log.d("EventLogger", "Event: $eventName") } }
- 안드로이드에서 BaseActivity를 만들어서 공통 기능을 상속받는 것도 객체 지향의 상속 개념을 잘 활용하는 예시다. BaseActivity를 하나 만들어두면, 여러 Activity들이 반복적으로 사용하는 공통 기능(예: 로딩 화면 처리, 로그 기록, 권한 요청 등)을 이 클래스에 정의해 놓고, 이를 상속받아 각 Activity에서 재사용할 수 있다.
- 다형성 (Polymorphism)
class MyAdapter : RecyclerView.Adapter<MyViewHolder>() { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_view, parent, false) return MyViewHolder(view) } // 아이템 종류에 따라 표시할 내용을 다르게 설정 }
- 다형성은 같은 메서드가 다른 방식으로 동작하는 것을 말한다. 안드로이드에서 RecyclerView.Adapter를 여러 방식으로 사용하는 예시가 있다. RecyclerView.Adapter는 리스트 아이템을 표시하는 메서드를 가지고 있는데, 어떤 아이템을 표시하느냐에 따라 다양한 Adapter를 만들 수 있다.
- 추상화 (Abstraction)
abstract class Animal { abstract fun sound() // 공통 기능 정의 } class Dog : Animal() { override fun sound() { println("Bark") } }
- 추상화는 불필요한 세부 사항은 숨기고, 중요한 동작만 공개하는 것이다. 안드로이드에서 View 클래스는 다양한 UI 요소들의 공통적인 기능을 정의하고, 실제로 사용할 때는 Button, TextView 등으로 구체화된 객체를 사용한다.
2. RESTful API 란
REST는 HTTP 프로토콜을 기반으로 자원을 정의하고, 자원에 대한 CRUD(Create, Read, Update, Delete) 작업을 수행하는 방식이다. RESTful API는 주로 웹 애플리케이션에서 서버와 클라이언트 간에 데이터를 주고받을 때 사용된다.
REST의 주요 원칙
- 자원(Resource)
- REST에서는 서버의 모든 데이터(예: 사용자, 게시물 등)를 "자원"으로 정의한다. 각 자원은 고유한 URI로 식별된다. 예를 들어, /users는 사용자 목록을 나타내고, /users/1은 특정 사용자를 나타낸다.
- HTTP 메서드 활용
- GET: 자원을 조회한다.
- POST: 자원을 생성한다.
- PUT: 자원을 업데이트한다.
- DELETE: 자원을 삭제한다.
- REST는 자원에 대한 작업을 HTTP 메서드로 표현한다. 주요 메서드는 다음과 같다.
- 무상태성(Stateless)
- RESTful API는 무상태(stateless) 방식으로 설계된다. 서버는 클라이언트의 상태를 저장하지 않으며, 모든 요청은 필요한 정보를 모두 포함하여 독립적으로 처리된다. 이렇게 하면 확장성과 유지보수성이 높아진다.
- 계층화 구조
- REST 아키텍처는 클라이언트와 서버 사이에 프록시, 로드 밸런서와 같은 중간 계층을 둘 수 있는 계층화된 구조를 지원한다. 이렇게 하면 시스템의 안정성과 보안성이 향상된다.
- 캐싱(Caching)
- HTTP의 캐싱 기능을 활용해 자주 조회되는 자원을 클라이언트 측에 캐시해 둘 수 있다. 이를 통해 네트워크 성능을 최적화할 수 있다.
RESTful API의 예시
RESTful API를 사용하여 사용자 정보를 가져오는 예를 들어보자.
- GET /users → 모든 사용자 목록을 조회한다.
- GET /users/1 → ID가 1인 사용자의 정보를 조회한다.
- POST /users → 새로운 사용자를 생성한다. (요청 본문에 사용자 데이터가 포함됨)
- PUT /users/1 → ID가 1인 사용자의 정보를 업데이트한다.
- DELETE /users/1 → ID가 1인 사용자를 삭제한다.
RESTful API의 장점
- 표준화: HTTP 메서드를 활용해 자원에 대한 작업을 표준화할 수 있다.
- 유연성: 클라이언트와 서버가 독립적으로 개발되고 유지보수될 수 있다.
- 확장성: 서버가 상태를 저장하지 않기 때문에 확장이 용이하다.
RESTful API는 이러한 원칙과 방식으로 설계되어 있어 개발자들이 직관적으로 API를 이해하고 사용할 수 있도록 돕는다.
3. TDD 란 무엇이며 어떠한 장점이 있는가
TDD(Test-Driven Development)는 "테스트 주도 개발" 방식으로, 코드를 작성하기 전에 테스트를 먼저 작성하고, 그 테스트를 통과하는 코드를 작성하는 개발 방법론이다. TDD는 "테스트 -> 코드 작성 -> 리팩토링"의 반복적인 사이클을 통해 이루어진다. 이 과정에서 테스트는 코드의 요구사항을 명확히 정의하며, 개발자는 요구사항에 맞게 코드를 작성하게 된다.
TDD의 기본 사이클 (Red-Green-Refactor)
- Red (테스트 작성 및 실패 확인)
- 먼저, 특정 기능에 대한 테스트 코드를 작성하고 실행한다. 이때 코드는 아직 작성되지 않았으므로 테스트는 당연히 실패한다.
- Green (코드 작성 및 테스트 통과)
- 테스트를 통과하기 위해 필요한 최소한의 코드를 작성하고 테스트를 다시 실행한다. 목표는 테스트가 통과(Green 상태)하는 것이다.
- Refactor (리팩토링)
- 테스트를 통과하는 코드가 준비되면, 코드의 구조나 성능을 개선하는 리팩토링을 진행한다. 테스트가 있기 때문에 코드가 변경되어도 기능에 문제가 생기지 않는지 빠르게 확인할 수 있다.
TDD의 장점
- 높은 코드 품질 보장
- TDD는 테스트를 먼저 작성하므로, 요구사항을 정확히 반영하고 코드가 의도한 대로 작동하는지 지속적으로 확인할 수 있다. 또한, 작은 단위의 테스트를 통해 버그를 초기에 발견할 수 있어 코드 품질이 높아진다.
- 리팩토링의 용이성
- TDD는 테스트 코드를 기반으로 리팩토링을 진행하기 때문에, 코드 변경 후에도 기존 기능이 정상적으로 작동하는지 쉽게 확인할 수 있다. 이는 리팩토링에 대한 두려움을 줄여주고, 코드를 개선할 수 있는 유연성을 제공한다.
- 개발 속도 향상
- 초반에는 테스트 작성에 시간이 걸릴 수 있지만, 테스트가 코드의 요구사항을 명확히 해주기 때문에 기능 개발 중 발생할 수 있는 예외 상황을 줄이고, 이후 단계에서 발생할 수 있는 버그 수정을 줄여 결과적으로 개발 속도가 빨라진다.
- 문서화 효과
- 테스트 코드는 해당 기능이 어떻게 동작하는지 보여주는 예시 역할을 한다. 이는 새로운 개발자나 팀원들이 코드를 이해하는 데 도움을 주어, 코드의 문서화 효과도 제공한다.
- 신뢰성 있는 배포
- TDD를 통해 작성된 테스트는 코드가 제대로 작동하는지 보장하기 때문에, 배포 시 예기치 않은 버그 발생을 줄이고 안정성을 높인다.
'공부' 카테고리의 다른 글
[Android] PlayStore 앱 업데이트 과정 정리. (0) | 2024.11.23 |
---|---|
[Kotlin] 기본 문법 공부를 다시 시작해보자. (0) | 2024.11.22 |
[i in We X AWS] 멘토링 후기 (2) | 2024.11.18 |
Output과 Outcome의 차이 (0) | 2024.10.23 |