안드로이드 개발자를 위한 이펙티브 자바 치트시트

한로니
한로니
Aug 26, 2017 · 7 min read

이 글은 Effective Java for Android (cheatsheet)의 번역입니다.

이펙티브 자바(Effective Java)는 장기적으로 유지 보수가 가능하면서 동시에 효과적인 자바 코드를 작성할 때 가장 많이 고려되는 책 중 하나입니다. 이는 자바를 사용하는 안드로이드 앱 개발 시에도 적용 가능함을 의미합니다. 물론 자바의 모든 기능이 안드로이드에 최적화되어 있지 않다는 점과(예: Enums, Serialization 등) 모바일 디바이스의 한계 때문에(Dalvik/ART가 데스크톱 JVM과 다른 부분) 책의 일부분은 적용하기 어려울 수 있습니다. 하지만 저는 이 책 대부분의 패러다임이 여전히 유효하다고 생각합니다. 이를 통해 견고하고, 깨끗하며 유지 보수가 쉬운 코드를 만들 수 있습니다.

이 글은 안드로이드 앱 개발 시 이펙티브 자바의 내용 중 중요하게 여겨지는 항목을 정리한 것입니다. 이미 책을 읽어 본 분들에게는 언급된 항목과 원칙을 다시 한번 떠올려 볼 계기를, 아직 이펙티브 자바를 않은 분들은 이 글을 통해 책의 묘미를 느껴 볼 수 있을 것입니다.

객체 생성 강제하기

Private 생성자로 new 키워드를 이용한 객체 생성을 강제하세요. 이는 특히 정적 함수들만 존재하는 유틸리티 클래스에 유용합니다.

class MovieUtils {  private MovieUtils () {}  static String titleAndYear(Movie movie) {
[…]
}
}

정적 팩토리 메서드 사용하기

new 키워드와 생성자를 사용해 객체를 생성하는 대신 정적 팩토리 메서드를 사용하세요. 이런 팩토리 메서드는 객체의 새로운 인스턴스를 매번 생성할 필요가 없을 때 유용하며(기존의 인스턴스를 재사용할 때) 필요에 따라 서브타입 객체도 반환할 수 있습니다.

class Movie {

[...]
public static Movie create(String title) {
return new Movie(title);
}
}

@stsdema28이 제보한 유용한 팁: 정적 팩토리 메서드는 테스트를 어렵게 만듭니다. 이런 경우는 테스트 시 목(mock) 객체를 사용할 수 있도록 비-정적(non-static) 팩토리를 이용하세요. 또는 팩토리 인터페이스를 통해 가짜 구현을 사용하는 것도 방법입니다.

빌더 패턴 사용하기

생성자가 3개 이상의 파라미터를 필요로 한다면 객체 생성을 위해 빌더 패턴을 사용하세요. 코드가 다소 많아지기는 하지만 빌더를 통해 확장이 용이하고, 읽기 쉬운 코드를 만들 수 있습니다. 벨류타입 클래스를 만드는 경우에는 AutoValue를 적용하는 것도 방법입니다.

class Movie {
static Builder newBuilder() {
return new Builder();
}
static class Builder {
String title;

Builder withTitle(String title) {
this.title = title;
return this;
}
Movie build() {
return new Movie(title);
}
}
private Movie(String title) {
[...]
}
}
// Use like this:
Movie matrix = Movie.newBuilder().withTitle("The Matrix").build();

불변 객체 사용하기

불변 객체는 객체 생성 후 소멸되기까지 동일한 상태를 유지합니다. 객체가 필요로 하는 모든 데이터는 생성 시점에 제공되는데 이러한 방식은 객체의 단순성, 스레드 안전성, 공유 안전성과 같은 다양한 이점을 제공합니다.

class Movie {
[...]

Movie sequel() {
return Movie.create(this.title + " 2");
}
}
// Use like this:
Movie toyStory = Movie.create("Toy Story");
Movie toyStory2 = toyStory.sequel();

모든 클래스를 불변으로 만드는 것은 어려울 수 있습니다. 이런 경우는 private final 필드를 사용하거나 final 클래스를 사용해 가능한 한 불변으로 만드세요. 불변 객체는 가변 객체보다 성능상 이점이 있으며 객체의 복사나 비교 단순화에 도움이 됩니다.

정적 멤버 클래스 사용하기

외부 클래스에 의존성이 없는 내부 클래스를 정의한다면 static 키워드를 사용해 정적 멤버 클래스로 만드세요. 정적 멤버 클래스는 외부 클래스에 대한 참조를 갖고 있지 않기 때문에 이로 인해 발생 가능한 메모리 누수 문제를 미리 방지할 수 있습니다.

class Movie {
[...]

static class MovieAward {
[...]
}
}

제네릭 사용하기

(자바스크립트와 달리) 자바가 타입 안전성을 제공한다는 것에 우리는 감사해야 합니다. 가능하다면 원시 타입 또는 Object 타입의 사용을 피하세요. 제네릭은 컴파일 타임 시 코드의 타입 안전성을 유지하는 메커니즘을 제공합니다.

// DON'T
List movies = Lists.newArrayList();
movies.add("Hello!");
[...]
String movie = (String) movies.get(0);
// DO
List<String> movies = Lists.newArrayList();
movies.add("Hello!");
[...]
String movie = movies.get(0);

함수의 매개 변수와 반환 값에 제네릭을 사용할 수 있다는 것을 잊지 마세요.

// DON'T
List sort(List input) {
[...]
}
// DO
<T> List<T> sort(List<T> input) {
[...]
}

바운드 와일드카드는 제네릭의 허용 범위를 확장해 코드에 좀 더 높은 유연성을 부여합니다.

// Read stuff from collection - use "extends"
void readList(List<? extends Movie> movieList) {
for (Movie movie : movieList) {
System.out.print(movie.getTitle());
[...]
}
}
// Write stuff to collection - use "super"
void writeList(List<? super Movie> movieList) {
movieList.add(Movie.create("Se7en"));
[...]
}

빈 값 반환하기

리스트나 컬렉션을 반환하는 함수에서 결과가 존재하지 않을 때 null 대신에 빈 컬렉션을 반환하세요. 이는 실수로 NPE가 발생하는 것을 방지할 수 있으며 null 반환에 대한 추가적인 문서화 및 주석이 필요 없습니다. 빈 컬렉션을 반환할 때는 새로운 컬렉션을 생성하는 것보다는 다음과 같이 반환하는 것이 좋습니다.

List<Movie> latestMovies() {
if (db.query().isEmpty()) {
return Collections.emptyList();
}
[...]
}

반복문에서 StringBuilder 사용하기

문자열을 조합하는 경우 + 연산자를 사용하는 것은 유용합니다. 하지만 반복문 내에서 많은 문자열을 조합할 때는 + 연산자보다 StringBuilder를 사용하는 것이 성능상 이점이 있습니다.

String latestMovieOneLiner(List<Movie> movies) {
StringBuilder sb = new StringBuilder();
for (Movie movie : movies) {
sb.append(movie);
}
return sb.toString();
}

복구 가능한 에러는 예외 활용하기

저는 에러 발생 시 예외를 발생시키는 것을 좋아하는 편은 아니지만 만일 예외를 던져야 한다면 checked 예외를 사용해 에러가 복구 가능함을 알려주는 것이 좋습니다.

List<Movie> latestMovies() throws MoviesNotFoundException {
if (db.query().isEmpty()) {
throw new MoviesNotFoundException();
}
[...]
}

맺으며

제가 작성한 내용은 이펙티브 자바의 일부분이며 완전한 설명이라기보다는 안드로이드 개발 시 적용해볼 만한 유용한 팁, 치트시트에 가깝습니다. :)

)

 by the author.

한로니

Written by

한로니

컴퓨터 앞에 앉아있는 시간이 많지만 모니터 밖 이야기들, 주로 사람답게 사는 작은 즐거움에 대해서도 관심이 많은 괴발자. 활동적이지는 않지만 어째서인지 자전거를 타고 세계 곳곳을 여행하는 상상을 종종 합니다.🤞

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade