[24.06.18] TIL - 013

0. 오늘은 무엇을 했는가

오늘은 새로운 팀원분들과 함께 하는 안드로이드 기초 주차 입니다.

이제는 팀원분들이 바뀌는 것도 익숙해지고 있습니다.

어쨌든, 코드 카타를 풀고, 아침 스크럼을 진행했습니다.

다들 어색한 분위기도 많이 없어서 좋은 것 같습니다.

이후, 안드로이드 기초 주차 강의를 1~4주차까지 전부 듣고,

업캐스트와 다운캐스트에 대해 다시 복습했습니다.

1. 코드 카타

[ 09:00 ~ 10:00 ]

오늘의 코드 카타는 H-Index 였습니다.

H-Index? 처음 들어보는 단어라, 코딩테스트를 위해 따로 만든 용어인 줄 알았습니다.

근데, 실제로 존재하는 용어 였습니다.

문제를 보시면 조금 이해가 갈 겁니다.

H-Index는 과학자의 생산성과 영향력을 나타내는 지표입니다. 어느 과학자의 H-Index를 나타내는 값인 h를 구하려고 합니다. 위키백과1에 따르면, H-Index는 다음과 같이 구합니다.

어떤 과학자가 발표한 논문 n편 중, h번 이상 인용된 논문이 h편 이상이고 나머지 논문이 h번 이하 인용되었다면 h의 최댓값이 이 과학자의 H-Index입니다.

어떤 과학자가 발표한 논문의 인용 횟수를 담은 배열 citations가 매개변수로 주어질 때, 이 과학자의 H-Index를 return 하도록 solution 함수를 작성해주세요.

과학자의 지표도 나타내는 건 처음 알았습니다. 어쨌든, 저는 이 내용을 보고 잘 이해가 가지 않았습니다.

h번 이상 인용된 논문이 h편 이상이고, 나머지가 h번 이하 인용됐으면 h의 최댓값이 H-Index이다.

솔직히 다시 봐도 이해가 어렵습니다.

그래서 질문하기를 들어가서 어떤 건지 설명해주시는 걸 보고 풀기 시작했습니다.

H-Index 설명 링크

즉, 논문 여러 개를 갖고, 인용 횟수가 10번 이상인 게 1편이면 1, 8번 이상이 2편이면 2, ...

이렇게 해서 인용 횟수와 그 인용된 논문의 개수 중 최소값을 고르고, 이걸 모든 경우에 적용시켜서

최댓값을 구하는 문제였습니다. 정말 이건 국어 문제같습니다.

어쩄든, 문제를 이해한 저는 바로 문제 풀이에 들어갔고, 사실 저 문장만 이해하면 정말 아무것도 없다는 걸 깨달았습니다.

class Solution {
    fun solution(citations: IntArray): Int {
        var answer = 0
        for(i in citations.sortedDescending()) {
            val j = citations.filter { it >= i }.size
            if(j >= i) {
                if(answer < i) answer = i
            }
            else if(answer < j) answer = j
        } 
        return answer
    }
}

앞서 말했듯, 인용 횟수와 그 인용된 논문의 개수 중 최소값을 고르고, 그 값들 중 최댓값을 고르는 문제입니다.

그래서 코드도 되게 짧게 나오게 됐습니다.

2. 안드로이드 앱 개발 입문

[ 12:00 ~ 13:00, 14:00 ~ 17:30 ]

안드로이드 앱 개발 입문 강의를 전부 수강했습니다.

알던 내용도 있었지만, 모르던 내용도 있어, 도움이 많이 되었습니다.

이 내용들을 막 나열해서 다시 복습해보겠습니다.

먼저, 단축키들입니다.

Ctrl + D : 현재 라인 복사
Ctrl + / : 현재 라인 주석
F3 : 북마크 설정
Ctrl + Alt + L : 코드 정렬

정말 유용한 단축키 같습니다.

그리고, aapt 도구라는 개념을 처음 봤는데요.

R.java 에서 기본적으로 리소스 파일 주소를 자동으로 생성해서 리소스 파일을 가져오게 된다고 합니다.

그래서 우리가 리소스 파일을 불러올 때도 R.drawable 처럼 R을 앞에 붙여왔던 거였습니다.

궁금증이 어느 정도 해결됐네요.

그리고, setContentView()라는 함수도 있는데, 이는 뒤에 나오는 부분을 컨텐트 뷰로 사용해 띄워주겠다는 뜻입니다.

다음은 프로젝트 빌드 과정입니다.

소스코드, 리소스 파일, AIDL 파일이 의존성 파일들과 함께 컴파일러를 거쳐서

소스코드는 DEX 파일로, 리소스 파일은 컴파일된 리소스파일로 변경됩니다.

다시, 디버그, 릴리즈 키가 DEX, 컴파일된 리소스 파일과 합쳐져, APK Packager를 만들고, 이를 APK로 만들게 됩니다.

그리고, strings.xml을 쓰는 이유는 다국어 지원에도 도움이 되기 때문입니다.

9-Patch 이미지라는 것도 있습니다. 크기가 늘어나거나 줄어들어도 원본 형태를 유지한다고 합니다.

또, 레이아웃은 ViewGroup의 파생, 위젯은 View의 파생 클래스입니다. 이 부분은 크게 신경쓰지 않았지만,

나중에 가면 왠지 유용하게 사용할 것 같아서 적어놓습니다.

2-1. Linear, Relative, Constraint Layout

튜터님이 이 3개는 자주 사용한다고 해서 다뤄보도록 하겠습니다.

제가 MDC 방식을 쓰면, Constraint Layout을 가장 많이 쓰는데, Linear, Relative는 자주 안 써서 까먹었던 참이었습니다.

먼저, LinearLayout은 선형으로 정렬하는 레이아웃입니다.

oritentation 속성을 사용해 가로, 세로축을 고를 수 있고, 각 자리에 layout_weight를 설정해 비율을 정할 수도 있습니다.

그 다음, RelativeLayout은 서로의 관계를 정해 정렬하는 레이아웃입니다.

layout_toStartOf 처럼 다른 위젯과의 관계를 만들어, 위젯을 정렬합니다.

또한, layout_alignParentEnd=true 처럼 부모의 끝에 관계를 만들 수도 있습니다.

이 2가지 레이아웃을 잘 안 썼던 이유는 이 두 레이아웃을 ConstraintLayout 하나로 다 대신할 수 있기 때문입니다.

ConstraintLayout은 비교적 늦게 나온 기술인데, 제약을 걸어, 위젯을 정렬합니다.

이때, 기본적으로, Relative처럼 위젯-위젯 또는 위젯-부모 관계를 만들고, Linear처럼 Chain을 통해 선형으로 정렬할 수도 있습니다.

아직 자세히 다루지 않았기에, 이 정도로만 정리하고 넘어가겠습니다.

2-2. Intent

사실 이전에 액티비티 관련 내용도 있었지만, 저는 Intent에 대해 더 배운 게 많고, 액티비티 쪽은 알던 내용이 많아서 넘기겠습니다.

Intent는 메시지 객체입니다. 다른 앱 구성요소에 메시지를 보내서, 작업을 요청합니다.

명시적 인텐트는 호출할 이름을 알고, startActivity, startService에 넘깁니다.

암시적 인텐트는 시작할 구성 요소의 이름을 모른 상태에서, 일반적인 작업을 인텐트 객체에 설정해 startActivity에 넘깁니다.

명시적 인텐트는 기본에 쓰던 내용이 주였습니다만, 암시적 인텐트는 처음 들어보는 내용이라 이 부분을 좀 더 다루겠습니다.

안드로이드 시스템은 모든 앱을 검색해서, 전달한 인텐트와 일치하는 인텐트 필터를 찾고, 그 필터들 중에 하나를 골라, 그 앱에서 실행하게 합니다.

Intent(Intent.ACTION_DIAL, Uri.parse("tel:010-0000-0000"))

위를 입력하고, startActivity를 진행하면, 010-0000-0000을 다이얼에 치게 됩니다. ACTION_DIAL의 작업을 하는 인텐트를 찾아서, 그 위에 tel: 뒤의 내용을 치는 것입니다.

Intent(Intent.ACTION_VIEW, Uri.parse("geo:37.565350, 127.01445"))

위 코드는, ACTION_VIEW의 작업을 하는 인텐트를 찾아서, 뒤의 geo: 뒤의 내용인 위도, 경도를 전달합니다.

즉, 앞의 내용은 전달할 인텐트 작업 종류, 뒤는 전달하고자 하는 내용이라고 볼 수 있겠습니다.

이때, Uri.parse를 사용한다는 점도 알아둬야겠습니다.

3. 업캐스트와 다운캐스트

이전에 코틀린 심화 강의를 수강했을 때, 튜터님이 가볍게 넘어가셨던 부분입니다.

업캐스트는 파생 객체를 기반 객체로 바꾸는 것입니다. 이 경우, 다형성을 챙길 수 있습니다.

이 부분은 다뤄주셨지만, 다운캐스트는 가볍게 넘어가셨습니다. 아무래도 얘기할 내용이 많아서인 것 같습니다.

먼저, 다운캐스트는 업캐스트의 반대로, 실행 시점에 타입을 식별합니다.

코틀린은 is로 어떤 객체의 타입을 식별합니다. 그리고, 이를 다운캐스트에 사용합니다.

if(기반 객체 is 파생 객체) 
기반 객체.파생 객체의 멤버 // 가능

즉, 일반적인 기반 객체가 아닌, 파생 객체였던 기반 객체의 경우, is로 그 타입을 확인하고, 다운캐스트를 진행할 수 있습니다.

이런 걸 스마트 캐스트라고 합니다.

반면, as를 통해 강제적으로 다운캐스트를 진행할 수도 있습니다. 다만, 이는 올바르지 않은 값일 수도 있으므로, 안전하지 않습니다.

이를 안전하게 하려면 as? 를 사용하면 됩니다.

4. 끝

이번 팀원분들은 다들 활발하셔서 스크럼이 되게 길었습니다.

다들 화이팅하는 모습을 보니 저도 더 열심히 해야 할 것 같습니다.

내일은 과제, 못했던 코틀린 공부, 안드로이드 공부, 코드 카타 등등

많이 공부하고 싶습니다. 근데 많이 덥네요.

끝.

profile
여기는 공부 기록용 블로그

0개의 댓글