SlideShare une entreprise Scribd logo
1  sur  38
Télécharger pour lire hors ligne
자바에서 null을 안전하게 다루는 방법
스프링 사용자 모임/우아한 형제들: 박성철
null null한 자바
스프링 사용자 모임/우아한 형제들: 박성철
자바에서 null을 안전하게 다루는 방법
고쳐쓰는 자바
스프링 사용자 모임/우아한 형제들: 박성철
자바 언어를 확장해서 쓰는 방법
차례
Part 0: null에 대해서
Part 1: null을 안전하게 다루는 방법
Part 2: null에 안전하다고 보장해주는 도구
Part 0: null에 대해서
JVM 언어 전쟁
2000년대 중반 2010년대 중반
2010년 전후
널 안정성
차기 자바의 자리를 두고 실용 언어들 간
경쟁
실론(Ceylon), 코틀린(Kotlin)
함수형 프로그래밍
멀티코어와 대용량 분산 처리가 인기를
뜰면서 함수형 프로그래밍이 주목을 받음
스칼라(Scala), 클로저(Clojure)
동적 타이핑/스크립팅
RoR과 스타트업 붐으로 생산성이 강조
다언어 프로그래밍(Polyglot) 인기
그루비(Groovy), jRuby, Jython
“I call it my billion-dollar mistake. It was the invention of
the null reference in 1965..”
- Tony Hoare
null 참조
● “레코드 핸들링": 객체지향의 시초가 된 논문
● 특별한 값이 없음을 나타내려고 null을 도입했고 이
값을 사용하려고 할 때 오류를 내도록 설계
● 두 참조값이 null일 때 두 참조는 동일하다고 판단
● 의미가 모호함: 초기화되지 않음, 정의되지
않음, 값이 없음, null 값
● 모든 참조의 기본 상태(값?)
● 모든 참조는 null 가능
자바의 null 참조
소프트웨어 결함 통계
Sapienz: Multi-objective Automated Testingfor Android Applications 에서
Part 1: null을 안전하게 다루는 방법
자바 기본 장치
● 단정문(assertion)
● java.util.Objects
● java.util.Optional
자바 기본 장치: 단정문(assertion)
● 부울식인 식1의 거짓이면 AssertionError 발생
● 식2는 AssertionError에 포함될 상세 정보를 만드는 생성식
● 공개 메서드에는 사용하지 말아야 함
● -enableassertions 또는 -ea 옵션으로 활성화
assert 식1 ;
assert 식1 : 식2;
private void setRefreshInterval(int interval)
{
assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval;
……
}
자바 기본 장치: java.util.Objects
자바 8
● isNull(Object obj)
● nonNull(Object obj)
● requireNonNull(T obj)
● requireNonNull(T obj, String message)
● requireNonNull(T obj, Supplier<String> messageSupplier)
자바 9
● requireNonNullElse(T obj, T defaultObj)
● requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
자바 기본 장치: java.util.Optional
Optional - The Mother of All Bikesheds: Stuart Marks
https://www.youtube.com/watch?v=Ej0sss6cq14
1. 절대로 Optional 변수와 반환값에 null을 사용하지 말라
2. Optional에 값이 들어 있다는 걸 확신하지 않는한 Optional.get()을 쓰지 말라
3. Optional.isPresent()이나 Optional.get() 외 API를 가능한 사용하라
4. Optional에서 여러 메서드를 연속해서 호출하고 값을 얻기 위해 Optional을 생성하는 건
권장할만하지 않다
5. Optional로 값을 처리하는 중에 그 안에 중간값을 처리하기 위해 또 다른 Optional이 사용되면 너무
복잡해진다
6. Optional을 필드, 메서드 매개변수, 집합 자료형에 쓰지 말라
7. 집합 자료형(List, Set, Map)을 감싸는 데 Optional을 쓰지 말고 빈 집합을 사용해라.
null 잘 쓰는 법
1. API(매개변수, 반환값)에 null을 최대한 쓰지 말아라
2. 사전 조건과 사후 조건을 확인하라: 계약에 의한 설계(design by contract)
3. (상태와 같이) null의 범위를 지역(클래스, 메서드)에 제한하라.
4. 초기화를 명확히 하라
null 잘 쓰는 법 1: API에 null을 최대한 쓰지 말아라
● null로 지나치게 유연한 메서드를 만들지 말고 명시적인 메서드를 만들어라
● null을 반환하지 말라
○ 반환 값이 꼭 있어야 한다면 null을 반환하지 말고 예외를 던져라.
○ 빈 반환 값은 빈 컬랙션이나 “Null 객체”를 활용하라
○ 반환 값이 없을 수도 있다면 Optional을 반환하라
● 선택적 매개변수는 null 대신 다형성(메서드 추가 정의; overload)를 사용해서 표현하라
null 잘 쓰는 법 1: API에 null을 최대한 쓰지 말아라
Null 객체 (특수 사례 패턴; Special Case Pattern)
● 타입 안전하면서 의미를 표현할 수 있는 동일한 타입의
특수 상황용 객체를 만들어 반환
● 다형성 활용
● 아무 일도 하지 않는 객체; 일종의 더미 객체
● 리스코프 치환 원칙 주의
null 잘 쓰는 법 2: 계약에 의한 설계(Design by Contract)
● API 규약을 소비자와 제공자 사이에 지켜야 할 엄격한 계약으로 여기는 설계 방법
● 형식적 규약 외에 사전 조건과 사후 조건과 유지 조건을 포함
● 베르트랑 마이어(Bertrand Meyer) - 에펠( Eiffel) 프로그래밍 언어 제작
● 개방-폐쇄 원칙의 상위 개념
When quality is pursued, productivity follows - K. Fujino
null 잘 쓰는 법 2: 계약에 의한 설계(Design by Contract)
계약에 의한 설계 class DICTIONARY [ELEMENT]
feature
put (x: ELEMENT; key: STRING) is
-- Insert x so that it will be retrievable through key.
require
count <= capacity
not key.empty
do
......
ensure
has (x)
item (key) = x
count = old count + 1
end
invariant
0 <= count
count <= capacity
end
null 잘 쓰는 법 2: 계약에 의한 설계(Design by Contract)
자바의 계약에 의한 설계
● Interface + Java Doc
● 사전 조건 = 보호절(guard clause)
○ 단정문
○ Objects의 메서드
○ IllegalArgumentException,
NullPointerException,
● 스프링 Assert 클래스
● 구아바 Preconditions 클래스
● valid4j + hamcrest
http://www.valid4j.org/
● AssertJ Preconditions 클래스
● Bean Validation
● Cofoja
https://github.com/nhatminhle/cofoja
null 잘 쓰는 법 3: null의 범위를 지역에 제한하라
● 기본 문제 해결 원칙: 큰 문제는 제어 가능한 작은 문제로 나누어 정복하고 다시 통합한다.
● 상태와 비슷하게 null도 지역적으로 제한할 경우 큰 문제가 안된다.
● 클래스와 메서드를 작게 만들어라
● 설계가 잘 된 코드에서는 널의 위험도 약해진다.
OOP to me means only messaging, local retention and protection and hiding of
state-process, and extreme late-binding of all things. - Alan Kay
1 2
3
null 잘 쓰는 법 4: 초기화를 명확히 하라
● 초기화 시점과 실행 시점이 겹치지 않아야 한다
● 실행 시점엔 초기화되지 않은 필드가 없어야 한다
● 실행 시점에 null인 필드는 초기화되지 않았다는 의미가 아닌, 값이 없다는 의미여야 한다.
● 객체 필드의 생명주기는 모두 객체의 생명주기와 같아야 한다.
● 지연 초기화(lazy initialization) 필드의 경우 팩토리 메서드로 null 처리를 캡슐화 하라
null을 안전하게 다루는 방법 - 요약
● API에 null을 최대한 쓰지 말아라
○ 반환값은 Optional, Null 객체, 빈값, 예외로 처리
○ 매개변수는 명확한 메서드 추가 정의
● 사전 조건과 사후 조건을 확인하라: 계약에 의한 설계(design by contract)
○ 보호절을 통한 사전 조건 확인, 다양한 편의 객체 활용
● (상태와 같이) null의 범위를 지역(클래스, 메서드)에 제한하라.
● 초기화를 명확히 하라
Part 2: null에 안전하다고 보장해주는 도구
“This led me to suggest that the null value is a member
of every type, and a null check is required on every use
of that reference variable, and it may be perhaps a
billion dollar mistake.”
- Tony Hoare
null 안전한 언어들
null을 안전하고 쉽게 다루게 해주는 엘비스 연산자
● C#: null 조건 연산자(?.과 ?[])
● 그루비(Groovy) : def name = person?.name
● 코틀린: ?. 과 ?:
● 스위프트: Optional Chaining & 가드(Guard) 문
null이 예외인 언어
● 코틀린: null 가능 타입과 non-null 타입
● 스위프트: Optional
● C# 8.0 (출시 예정)
자바의 엘비스 연산자(?:) 논의
● 자바 문법 개선 프로젝트인 코인(coin)에서 최종 탈락
○ ?:는 삼항 연산자의 축약형로 자바와 맞지 않다: a != null ? a : b -> a ?: c
○ null 안전한 참조(?.)는 null 사용을 부추긴다: 디미터 법칙(Law of Demeter)
○ 진행 중인 타입 어노테이션(JSR 308) 추천
● ?. 대신 Optional 사용 권유
Optional.ofNullable(house)
.map(house -> house.getFloor(0))
.map(floorZero -> floorZero.getWall(WEST))
.map(wallWest -> wallWest.getDoor())
house?.getFloor()?.getWall(WEST)?.getDoor();
null 안전성을 도와주는 자바 도구
● JSR 305
○ 중단된 미완성 표준 (JSR 리뷰 2006/8/29~2006/9/11)
○ 정적 분석 (findbug 등)
○ IDE 지원 (Intellij, Eclipse, Spring Framework, Android Studio)
○ Nullaway
● JSR 308
○ CheckerFramework
JSR-308 타입 어노테이션
● 선언부가 아닌 타입 지정 위치에 어노테이션 추가 가능
● 어노테이션 프로세싱을 통한 빈약한 자바 타입 시스템을 강화
● 초안 제출 2006/10/17, 최종안 승인 2014/2/18, 자바 8에 추가
● 워싱턴대 마이클 에른스트(Michael Ernst) 교수 주도
● CheckerFramework와 동시에 진행 (버전 0.1.1 2007/6/7 첫 출시)
소스 코드 기본 타입 확인
플러그인
타입 확인
바이트 코드
자바 컴파일러
Checker Framework
● null 안전성 확인
@Nullable, @NonNull, @PolyNull
● Map 키, 잠금, 순차 자료형(배열, List 등) 색인값, 정규식, 문자열 형식, 단위 등
다수 확인 기능 제공
● 자작 확인 기능 추가 가능
● 특정 환경이나 IDE 독립적
@NonNull과 @Nullable
public class Address
{
public final @NonNull String address1;
public final @Nullable String address2;
public final @NonNull String zipcode;
public final @NonNull String city;
public final @NonNull String country;
private Address(@NonNull String address1, @Nullable String address2, @NonNull String zipcode,
@NonNull String city, @NonNull String country)
{
……
}
public static Address of(@NonNull String address1, @NonNull String zipcode,
@NonNull String city, @NonNull String country)
{
return new Address(address1, null, zipcode, city, country);
}
● 과도한 어노테이션 사용 예방
● 기본 @NonNull
필드, 매개변수, 반환값 등
● 예외적 @Nullable
지역 변수, 타입 캐스트 등
● 패키지, 클래스 수준 정책 설정
@DefaultQualifier
기본 null 정책
public class Address
{
public final String address1;
public final @Nullable String address2;
public final String zipcode;
public final String city;
public final String country;
private Address(String address1, @Nullable String address2,
String zipcode, String city, String country)
{
…...
}
public static Address of(String address1, String zipcode, ……
{
return new Address(address1, null, zipcode, city, country);
}
● @DefaultQualifier
● 패키지(package-info.java)나 클래스 전체의 기본 정책 설정
패키지, 클래스 수준 기본 정책 설정
@DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.LOCAL_VARIABLE)
package dev.fupfin.null_safety.strict;
@DefaultQualifier(value = Nullable.class, locations = TypeUseLocation.FIELD)
class MyClass {
Object nullableField = null;
@NonNull Object nonNullField = new Object();
}
● 자바 8 표준 API
● 자바 11 출시 준비 중
● 임의의 API에 어노테이션 설정 가능
어노테이션 달린 자바 표준 API 제공
private static void password()
{
Console console = System.console();
char[] password = console.readPassword();
……
}
Error:(30, 27) java:
[dereference.of.nullable]
dereference of possibly-null
reference console
● 단순한 정적 타입 확인이 아닌 코드 흐름과 실행 결과를 반영
● 코드로 null 확인을 한 경우 @nonNull로 취급
● 메서드 내부로 제한
자동 타입 개선(Automatic type refinement)
private static void password()
{
Console console = System.console();
char[] password = nonNull(console) ? console.readPassword() : new char[0];
……
}
OK
● List, Set, Map, 배열 등 집합 자료형의 요소도 null 확인
● 기본 @NonNull
● 타입 매개변수에 @Nullable 지정
집합 타입 요소의 null 안정성 지원
private static void printList()
{
List<String> names = Arrays.asList("kim", "choi", null, "park", "hwang");
for(String name: names)
out.println(name);
}
Error:(42, 43) java: [assignment.type.incompatible]
incompatible types in assignment.
found : @Initialized @NonNull List<@Initialized
@Nullable String>......
정리
null은 왜 문제인가?
● 모든 참조 타입에 지정 가능한 값(상태?), 언어가 지원할 문제
null을 안전하게 다루는 방법
● API에 null을 최대한 쓰지 말아라 - 반환값은 Optional, Null 객체, 빈값, 예외로 처리
● 사전 조건과 사후 조건을 확인하라: 계약에 의한 설계(design by contract)
● (상태와 같이) null의 범위를 지역(클래스, 메서드)에 제한하라.
● 초기화를 명확히 하라
null에 안전하다고 보장해주는 도구
● JSR 305 계열과 JSR 308 계열
● 가장 성숙한 자바 타입 확인 확장 기술: Checker Framework
● “(원래) 부족한 자바, 고쳐쓰자”
감사합니다.

Contenu connexe

Tendances

実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門Naohiro Fujie
 
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍Chris Ohk
 
DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기beom kyun choi
 
ゼロ幅スペースという悪夢
ゼロ幅スペースという悪夢ゼロ幅スペースという悪夢
ゼロ幅スペースという悪夢swamp Sawa
 
Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신Sungchul Park
 
REST API 설계
REST API 설계REST API 설계
REST API 설계Terry Cho
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기Sang Heon Lee
 
[수정본] 우아한 객체지향
[수정본] 우아한 객체지향[수정본] 우아한 객체지향
[수정본] 우아한 객체지향Young-Ho Cho
 
iOS の通信における認証の種類とその取り扱い
iOS の通信における認証の種類とその取り扱いiOS の通信における認証の種類とその取り扱い
iOS の通信における認証の種類とその取り扱いniwatako
 
Massive service basic
Massive service basicMassive service basic
Massive service basicDaeMyung Kang
 
코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)
코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)
코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)Suhyun Park
 
boosting 기법 이해 (bagging vs boosting)
boosting 기법 이해 (bagging vs boosting)boosting 기법 이해 (bagging vs boosting)
boosting 기법 이해 (bagging vs boosting)SANG WON PARK
 
基幹業務もHadoopで!! -ローソンにおける店舗発注業務への Hadoop + Hive導入と その取り組みについて-
基幹業務もHadoopで!! -ローソンにおける店舗発注業務へのHadoop + Hive導入と その取り組みについて-基幹業務もHadoopで!! -ローソンにおける店舗発注業務へのHadoop + Hive導入と その取り組みについて-
基幹業務もHadoopで!! -ローソンにおける店舗発注業務への Hadoop + Hive導入と その取り組みについて-Keigo Suda
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8Talha Ocakçı
 
これからSpringを使う開発者が知っておくべきこと
これからSpringを使う開発者が知っておくべきことこれからSpringを使う開発者が知っておくべきこと
これからSpringを使う開発者が知っておくべきこと土岐 孝平
 
Sentiment Analysis Using Solr
Sentiment Analysis Using SolrSentiment Analysis Using Solr
Sentiment Analysis Using SolrPradeep Pujari
 
객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기Young-Ho Cho
 
traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話infinite_loop
 
Momenti Seminar - A Tour of Rust, Part 1
Momenti Seminar - A Tour of Rust, Part 1Momenti Seminar - A Tour of Rust, Part 1
Momenti Seminar - A Tour of Rust, Part 1Chris Ohk
 
JSON:APIについてざっくり入門
JSON:APIについてざっくり入門JSON:APIについてざっくり入門
JSON:APIについてざっくり入門iPride Co., Ltd.
 

Tendances (20)

実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門実装して理解するLINE LoginとOpenID Connect入門
実装して理解するLINE LoginとOpenID Connect入門
 
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
인프콘 2022 - Rust 크로스 플랫폼 프로그래밍
 
DDD로 복잡함 다루기
DDD로 복잡함 다루기DDD로 복잡함 다루기
DDD로 복잡함 다루기
 
ゼロ幅スペースという悪夢
ゼロ幅スペースという悪夢ゼロ幅スペースという悪夢
ゼロ幅スペースという悪夢
 
Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신Beyond Java: 자바 8을 중심으로 본 자바의 혁신
Beyond Java: 자바 8을 중심으로 본 자바의 혁신
 
REST API 설계
REST API 설계REST API 설계
REST API 설계
 
[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기[NDC2016] TERA 서버의 Modern C++ 활용기
[NDC2016] TERA 서버의 Modern C++ 활용기
 
[수정본] 우아한 객체지향
[수정본] 우아한 객체지향[수정본] 우아한 객체지향
[수정본] 우아한 객체지향
 
iOS の通信における認証の種類とその取り扱い
iOS の通信における認証の種類とその取り扱いiOS の通信における認証の種類とその取り扱い
iOS の通信における認証の種類とその取り扱い
 
Massive service basic
Massive service basicMassive service basic
Massive service basic
 
코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)
코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)
코딩 테스트 및 알고리즘 문제해결 공부 방법 (고려대학교 KUCC, 2022년 4월)
 
boosting 기법 이해 (bagging vs boosting)
boosting 기법 이해 (bagging vs boosting)boosting 기법 이해 (bagging vs boosting)
boosting 기법 이해 (bagging vs boosting)
 
基幹業務もHadoopで!! -ローソンにおける店舗発注業務への Hadoop + Hive導入と その取り組みについて-
基幹業務もHadoopで!! -ローソンにおける店舗発注業務へのHadoop + Hive導入と その取り組みについて-基幹業務もHadoopで!! -ローソンにおける店舗発注業務へのHadoop + Hive導入と その取り組みについて-
基幹業務もHadoopで!! -ローソンにおける店舗発注業務への Hadoop + Hive導入と その取り組みについて-
 
Functional programming with Java 8
Functional programming with Java 8Functional programming with Java 8
Functional programming with Java 8
 
これからSpringを使う開発者が知っておくべきこと
これからSpringを使う開発者が知っておくべきことこれからSpringを使う開発者が知っておくべきこと
これからSpringを使う開発者が知っておくべきこと
 
Sentiment Analysis Using Solr
Sentiment Analysis Using SolrSentiment Analysis Using Solr
Sentiment Analysis Using Solr
 
객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기객체지향적인 도메인 레이어 구축하기
객체지향적인 도메인 레이어 구축하기
 
traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話
 
Momenti Seminar - A Tour of Rust, Part 1
Momenti Seminar - A Tour of Rust, Part 1Momenti Seminar - A Tour of Rust, Part 1
Momenti Seminar - A Tour of Rust, Part 1
 
JSON:APIについてざっくり入門
JSON:APIについてざっくり入門JSON:APIについてざっくり入門
JSON:APIについてざっくり入門
 

Similaire à 자바에서 null을 안전하게 다루는 방법

Java null survival guide
Java null survival guideJava null survival guide
Java null survival guideSungchul Park
 
I phone 2 release
I phone 2 releaseI phone 2 release
I phone 2 releaseJaehyeuk Oh
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509영석 조
 
0.javascript기본(~3일차내)
0.javascript기본(~3일차내)0.javascript기본(~3일차내)
0.javascript기본(~3일차내)Sung-hoon Ma
 
Use JavaScript more strictly (feat. TypeScript, flow)
Use JavaScript more strictly (feat. TypeScript, flow)Use JavaScript more strictly (feat. TypeScript, flow)
Use JavaScript more strictly (feat. TypeScript, flow)Mark Lee
 
자바8 나머지 공개
자바8 나머지 공개자바8 나머지 공개
자바8 나머지 공개Sungchul Park
 
[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어NAVER D2
 
Java 강의자료 ed11
Java 강의자료 ed11Java 강의자료 ed11
Java 강의자료 ed11hungrok
 
[Osxdev]4.swift
[Osxdev]4.swift[Osxdev]4.swift
[Osxdev]4.swiftNAVER D2
 
프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js functionYoung-Beom Rhee
 
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initializationEunjoo Im
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdfHyosang Hong
 
Cryptol 수업자료
Cryptol 수업자료Cryptol 수업자료
Cryptol 수업자료arundine
 

Similaire à 자바에서 null을 안전하게 다루는 방법 (20)

Java null survival guide
Java null survival guideJava null survival guide
Java null survival guide
 
I phone 2 release
I phone 2 releaseI phone 2 release
I phone 2 release
 
Node.js 기본
Node.js 기본Node.js 기본
Node.js 기본
 
Sonarqube 20160509
Sonarqube 20160509Sonarqube 20160509
Sonarqube 20160509
 
0.javascript기본(~3일차내)
0.javascript기본(~3일차내)0.javascript기본(~3일차내)
0.javascript기본(~3일차내)
 
Use JavaScript more strictly (feat. TypeScript, flow)
Use JavaScript more strictly (feat. TypeScript, flow)Use JavaScript more strictly (feat. TypeScript, flow)
Use JavaScript more strictly (feat. TypeScript, flow)
 
자바8 나머지 공개
자바8 나머지 공개자바8 나머지 공개
자바8 나머지 공개
 
[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어[1B1]스위프트프로그래밍언어
[1B1]스위프트프로그래밍언어
 
Java 강의자료 ed11
Java 강의자료 ed11Java 강의자료 ed11
Java 강의자료 ed11
 
Java to Kotlin
Java to KotlinJava to Kotlin
Java to Kotlin
 
C++에서 Objective-C까지
C++에서 Objective-C까지C++에서 Objective-C까지
C++에서 Objective-C까지
 
[Osxdev]4.swift
[Osxdev]4.swift[Osxdev]4.swift
[Osxdev]4.swift
 
프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function프론트엔드스터디 E04 js function
프론트엔드스터디 E04 js function
 
Swift3 subscript inheritance initialization
Swift3 subscript inheritance initializationSwift3 subscript inheritance initialization
Swift3 subscript inheritance initialization
 
javascript01
javascript01javascript01
javascript01
 
4-1. javascript
4-1. javascript4-1. javascript
4-1. javascript
 
Javascript 교육자료 pdf
Javascript 교육자료 pdfJavascript 교육자료 pdf
Javascript 교육자료 pdf
 
Java script
Java scriptJava script
Java script
 
Cryptol 수업자료
Cryptol 수업자료Cryptol 수업자료
Cryptol 수업자료
 
Java the good parts
Java the good partsJava the good parts
Java the good parts
 

Plus de Sungchul Park

애자일 안한 이야기
애자일 안한 이야기애자일 안한 이야기
애자일 안한 이야기Sungchul Park
 
자바 테스트 자동화
자바 테스트 자동화자바 테스트 자동화
자바 테스트 자동화Sungchul Park
 
변경에 강한 애플리케이션, 유기적 애플리케이션
변경에 강한 애플리케이션, 유기적 애플리케이션변경에 강한 애플리케이션, 유기적 애플리케이션
변경에 강한 애플리케이션, 유기적 애플리케이션Sungchul Park
 
자바 서버 애플리케이션 아키텍처 안티 패턴
자바 서버 애플리케이션 아키텍처 안티 패턴자바 서버 애플리케이션 아키텍처 안티 패턴
자바 서버 애플리케이션 아키텍처 안티 패턴Sungchul Park
 
스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기Sungchul Park
 
스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처
스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처 스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처
스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처 Sungchul Park
 
스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용
스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용
스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용Sungchul Park
 
스프링 코어 강의 1부 - 봄 맞이 준비 운동
스프링 코어 강의 1부 - 봄 맞이 준비 운동스프링 코어 강의 1부 - 봄 맞이 준비 운동
스프링 코어 강의 1부 - 봄 맞이 준비 운동Sungchul Park
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개Sungchul Park
 
java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰Sungchul Park
 
Open Source가 바꾼 자바
Open Source가 바꾼 자바Open Source가 바꾼 자바
Open Source가 바꾼 자바Sungchul Park
 

Plus de Sungchul Park (16)

애자일 안한 이야기
애자일 안한 이야기애자일 안한 이야기
애자일 안한 이야기
 
Java.next
Java.nextJava.next
Java.next
 
자바 테스트 자동화
자바 테스트 자동화자바 테스트 자동화
자바 테스트 자동화
 
변경에 강한 애플리케이션, 유기적 애플리케이션
변경에 강한 애플리케이션, 유기적 애플리케이션변경에 강한 애플리케이션, 유기적 애플리케이션
변경에 강한 애플리케이션, 유기적 애플리케이션
 
자바 서버 애플리케이션 아키텍처 안티 패턴
자바 서버 애플리케이션 아키텍처 안티 패턴자바 서버 애플리케이션 아키텍처 안티 패턴
자바 서버 애플리케이션 아키텍처 안티 패턴
 
스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기스프링보다 중요한 스프링 이야기
스프링보다 중요한 스프링 이야기
 
Geeks at SK Planet
Geeks at SK PlanetGeeks at SK Planet
Geeks at SK Planet
 
스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처
스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처 스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처
스프링 코어 강의 3부 - 웹 애플리케이션 아키텍처
 
스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용
스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용
스프링 코어 강의 2부 - Java 구성을 활용한 스프링 코어 사용
 
스프링 코어 강의 1부 - 봄 맞이 준비 운동
스프링 코어 강의 1부 - 봄 맞이 준비 운동스프링 코어 강의 1부 - 봄 맞이 준비 운동
스프링 코어 강의 1부 - 봄 맞이 준비 운동
 
자바8 람다 나머지 공개
자바8 람다 나머지 공개자바8 람다 나머지 공개
자바8 람다 나머지 공개
 
팀장 잔소리
팀장 잔소리팀장 잔소리
팀장 잔소리
 
java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰java 8 람다식 소개와 의미 고찰
java 8 람다식 소개와 의미 고찰
 
Open Source가 바꾼 자바
Open Source가 바꾼 자바Open Source가 바꾼 자바
Open Source가 바꾼 자바
 
Work With Engineer
Work With EngineerWork With Engineer
Work With Engineer
 
DDD 산책
DDD 산책DDD 산책
DDD 산책
 

자바에서 null을 안전하게 다루는 방법

  • 1. 자바에서 null을 안전하게 다루는 방법 스프링 사용자 모임/우아한 형제들: 박성철
  • 2. null null한 자바 스프링 사용자 모임/우아한 형제들: 박성철 자바에서 null을 안전하게 다루는 방법
  • 3. 고쳐쓰는 자바 스프링 사용자 모임/우아한 형제들: 박성철 자바 언어를 확장해서 쓰는 방법
  • 4. 차례 Part 0: null에 대해서 Part 1: null을 안전하게 다루는 방법 Part 2: null에 안전하다고 보장해주는 도구
  • 5. Part 0: null에 대해서
  • 6. JVM 언어 전쟁 2000년대 중반 2010년대 중반 2010년 전후 널 안정성 차기 자바의 자리를 두고 실용 언어들 간 경쟁 실론(Ceylon), 코틀린(Kotlin) 함수형 프로그래밍 멀티코어와 대용량 분산 처리가 인기를 뜰면서 함수형 프로그래밍이 주목을 받음 스칼라(Scala), 클로저(Clojure) 동적 타이핑/스크립팅 RoR과 스타트업 붐으로 생산성이 강조 다언어 프로그래밍(Polyglot) 인기 그루비(Groovy), jRuby, Jython
  • 7. “I call it my billion-dollar mistake. It was the invention of the null reference in 1965..” - Tony Hoare
  • 8. null 참조 ● “레코드 핸들링": 객체지향의 시초가 된 논문 ● 특별한 값이 없음을 나타내려고 null을 도입했고 이 값을 사용하려고 할 때 오류를 내도록 설계 ● 두 참조값이 null일 때 두 참조는 동일하다고 판단 ● 의미가 모호함: 초기화되지 않음, 정의되지 않음, 값이 없음, null 값 ● 모든 참조의 기본 상태(값?) ● 모든 참조는 null 가능 자바의 null 참조
  • 9. 소프트웨어 결함 통계 Sapienz: Multi-objective Automated Testingfor Android Applications 에서
  • 10. Part 1: null을 안전하게 다루는 방법
  • 11. 자바 기본 장치 ● 단정문(assertion) ● java.util.Objects ● java.util.Optional
  • 12. 자바 기본 장치: 단정문(assertion) ● 부울식인 식1의 거짓이면 AssertionError 발생 ● 식2는 AssertionError에 포함될 상세 정보를 만드는 생성식 ● 공개 메서드에는 사용하지 말아야 함 ● -enableassertions 또는 -ea 옵션으로 활성화 assert 식1 ; assert 식1 : 식2; private void setRefreshInterval(int interval) { assert interval > 0 && interval <= 1000/MAX_REFRESH_RATE : interval; …… }
  • 13. 자바 기본 장치: java.util.Objects 자바 8 ● isNull(Object obj) ● nonNull(Object obj) ● requireNonNull(T obj) ● requireNonNull(T obj, String message) ● requireNonNull(T obj, Supplier<String> messageSupplier) 자바 9 ● requireNonNullElse(T obj, T defaultObj) ● requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
  • 14. 자바 기본 장치: java.util.Optional Optional - The Mother of All Bikesheds: Stuart Marks https://www.youtube.com/watch?v=Ej0sss6cq14 1. 절대로 Optional 변수와 반환값에 null을 사용하지 말라 2. Optional에 값이 들어 있다는 걸 확신하지 않는한 Optional.get()을 쓰지 말라 3. Optional.isPresent()이나 Optional.get() 외 API를 가능한 사용하라 4. Optional에서 여러 메서드를 연속해서 호출하고 값을 얻기 위해 Optional을 생성하는 건 권장할만하지 않다 5. Optional로 값을 처리하는 중에 그 안에 중간값을 처리하기 위해 또 다른 Optional이 사용되면 너무 복잡해진다 6. Optional을 필드, 메서드 매개변수, 집합 자료형에 쓰지 말라 7. 집합 자료형(List, Set, Map)을 감싸는 데 Optional을 쓰지 말고 빈 집합을 사용해라.
  • 15. null 잘 쓰는 법 1. API(매개변수, 반환값)에 null을 최대한 쓰지 말아라 2. 사전 조건과 사후 조건을 확인하라: 계약에 의한 설계(design by contract) 3. (상태와 같이) null의 범위를 지역(클래스, 메서드)에 제한하라. 4. 초기화를 명확히 하라
  • 16. null 잘 쓰는 법 1: API에 null을 최대한 쓰지 말아라 ● null로 지나치게 유연한 메서드를 만들지 말고 명시적인 메서드를 만들어라 ● null을 반환하지 말라 ○ 반환 값이 꼭 있어야 한다면 null을 반환하지 말고 예외를 던져라. ○ 빈 반환 값은 빈 컬랙션이나 “Null 객체”를 활용하라 ○ 반환 값이 없을 수도 있다면 Optional을 반환하라 ● 선택적 매개변수는 null 대신 다형성(메서드 추가 정의; overload)를 사용해서 표현하라
  • 17. null 잘 쓰는 법 1: API에 null을 최대한 쓰지 말아라 Null 객체 (특수 사례 패턴; Special Case Pattern) ● 타입 안전하면서 의미를 표현할 수 있는 동일한 타입의 특수 상황용 객체를 만들어 반환 ● 다형성 활용 ● 아무 일도 하지 않는 객체; 일종의 더미 객체 ● 리스코프 치환 원칙 주의
  • 18. null 잘 쓰는 법 2: 계약에 의한 설계(Design by Contract) ● API 규약을 소비자와 제공자 사이에 지켜야 할 엄격한 계약으로 여기는 설계 방법 ● 형식적 규약 외에 사전 조건과 사후 조건과 유지 조건을 포함 ● 베르트랑 마이어(Bertrand Meyer) - 에펠( Eiffel) 프로그래밍 언어 제작 ● 개방-폐쇄 원칙의 상위 개념 When quality is pursued, productivity follows - K. Fujino
  • 19. null 잘 쓰는 법 2: 계약에 의한 설계(Design by Contract) 계약에 의한 설계 class DICTIONARY [ELEMENT] feature put (x: ELEMENT; key: STRING) is -- Insert x so that it will be retrievable through key. require count <= capacity not key.empty do ...... ensure has (x) item (key) = x count = old count + 1 end invariant 0 <= count count <= capacity end
  • 20. null 잘 쓰는 법 2: 계약에 의한 설계(Design by Contract) 자바의 계약에 의한 설계 ● Interface + Java Doc ● 사전 조건 = 보호절(guard clause) ○ 단정문 ○ Objects의 메서드 ○ IllegalArgumentException, NullPointerException, ● 스프링 Assert 클래스 ● 구아바 Preconditions 클래스 ● valid4j + hamcrest http://www.valid4j.org/ ● AssertJ Preconditions 클래스 ● Bean Validation ● Cofoja https://github.com/nhatminhle/cofoja
  • 21. null 잘 쓰는 법 3: null의 범위를 지역에 제한하라 ● 기본 문제 해결 원칙: 큰 문제는 제어 가능한 작은 문제로 나누어 정복하고 다시 통합한다. ● 상태와 비슷하게 null도 지역적으로 제한할 경우 큰 문제가 안된다. ● 클래스와 메서드를 작게 만들어라 ● 설계가 잘 된 코드에서는 널의 위험도 약해진다. OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things. - Alan Kay 1 2 3
  • 22. null 잘 쓰는 법 4: 초기화를 명확히 하라 ● 초기화 시점과 실행 시점이 겹치지 않아야 한다 ● 실행 시점엔 초기화되지 않은 필드가 없어야 한다 ● 실행 시점에 null인 필드는 초기화되지 않았다는 의미가 아닌, 값이 없다는 의미여야 한다. ● 객체 필드의 생명주기는 모두 객체의 생명주기와 같아야 한다. ● 지연 초기화(lazy initialization) 필드의 경우 팩토리 메서드로 null 처리를 캡슐화 하라
  • 23. null을 안전하게 다루는 방법 - 요약 ● API에 null을 최대한 쓰지 말아라 ○ 반환값은 Optional, Null 객체, 빈값, 예외로 처리 ○ 매개변수는 명확한 메서드 추가 정의 ● 사전 조건과 사후 조건을 확인하라: 계약에 의한 설계(design by contract) ○ 보호절을 통한 사전 조건 확인, 다양한 편의 객체 활용 ● (상태와 같이) null의 범위를 지역(클래스, 메서드)에 제한하라. ● 초기화를 명확히 하라
  • 24. Part 2: null에 안전하다고 보장해주는 도구
  • 25. “This led me to suggest that the null value is a member of every type, and a null check is required on every use of that reference variable, and it may be perhaps a billion dollar mistake.” - Tony Hoare
  • 26. null 안전한 언어들 null을 안전하고 쉽게 다루게 해주는 엘비스 연산자 ● C#: null 조건 연산자(?.과 ?[]) ● 그루비(Groovy) : def name = person?.name ● 코틀린: ?. 과 ?: ● 스위프트: Optional Chaining & 가드(Guard) 문 null이 예외인 언어 ● 코틀린: null 가능 타입과 non-null 타입 ● 스위프트: Optional ● C# 8.0 (출시 예정)
  • 27. 자바의 엘비스 연산자(?:) 논의 ● 자바 문법 개선 프로젝트인 코인(coin)에서 최종 탈락 ○ ?:는 삼항 연산자의 축약형로 자바와 맞지 않다: a != null ? a : b -> a ?: c ○ null 안전한 참조(?.)는 null 사용을 부추긴다: 디미터 법칙(Law of Demeter) ○ 진행 중인 타입 어노테이션(JSR 308) 추천 ● ?. 대신 Optional 사용 권유 Optional.ofNullable(house) .map(house -> house.getFloor(0)) .map(floorZero -> floorZero.getWall(WEST)) .map(wallWest -> wallWest.getDoor()) house?.getFloor()?.getWall(WEST)?.getDoor();
  • 28. null 안전성을 도와주는 자바 도구 ● JSR 305 ○ 중단된 미완성 표준 (JSR 리뷰 2006/8/29~2006/9/11) ○ 정적 분석 (findbug 등) ○ IDE 지원 (Intellij, Eclipse, Spring Framework, Android Studio) ○ Nullaway ● JSR 308 ○ CheckerFramework
  • 29. JSR-308 타입 어노테이션 ● 선언부가 아닌 타입 지정 위치에 어노테이션 추가 가능 ● 어노테이션 프로세싱을 통한 빈약한 자바 타입 시스템을 강화 ● 초안 제출 2006/10/17, 최종안 승인 2014/2/18, 자바 8에 추가 ● 워싱턴대 마이클 에른스트(Michael Ernst) 교수 주도 ● CheckerFramework와 동시에 진행 (버전 0.1.1 2007/6/7 첫 출시) 소스 코드 기본 타입 확인 플러그인 타입 확인 바이트 코드 자바 컴파일러
  • 30. Checker Framework ● null 안전성 확인 @Nullable, @NonNull, @PolyNull ● Map 키, 잠금, 순차 자료형(배열, List 등) 색인값, 정규식, 문자열 형식, 단위 등 다수 확인 기능 제공 ● 자작 확인 기능 추가 가능 ● 특정 환경이나 IDE 독립적
  • 31. @NonNull과 @Nullable public class Address { public final @NonNull String address1; public final @Nullable String address2; public final @NonNull String zipcode; public final @NonNull String city; public final @NonNull String country; private Address(@NonNull String address1, @Nullable String address2, @NonNull String zipcode, @NonNull String city, @NonNull String country) { …… } public static Address of(@NonNull String address1, @NonNull String zipcode, @NonNull String city, @NonNull String country) { return new Address(address1, null, zipcode, city, country); }
  • 32. ● 과도한 어노테이션 사용 예방 ● 기본 @NonNull 필드, 매개변수, 반환값 등 ● 예외적 @Nullable 지역 변수, 타입 캐스트 등 ● 패키지, 클래스 수준 정책 설정 @DefaultQualifier 기본 null 정책 public class Address { public final String address1; public final @Nullable String address2; public final String zipcode; public final String city; public final String country; private Address(String address1, @Nullable String address2, String zipcode, String city, String country) { …... } public static Address of(String address1, String zipcode, …… { return new Address(address1, null, zipcode, city, country); }
  • 33. ● @DefaultQualifier ● 패키지(package-info.java)나 클래스 전체의 기본 정책 설정 패키지, 클래스 수준 기본 정책 설정 @DefaultQualifier(value = NonNull.class, locations = TypeUseLocation.LOCAL_VARIABLE) package dev.fupfin.null_safety.strict; @DefaultQualifier(value = Nullable.class, locations = TypeUseLocation.FIELD) class MyClass { Object nullableField = null; @NonNull Object nonNullField = new Object(); }
  • 34. ● 자바 8 표준 API ● 자바 11 출시 준비 중 ● 임의의 API에 어노테이션 설정 가능 어노테이션 달린 자바 표준 API 제공 private static void password() { Console console = System.console(); char[] password = console.readPassword(); …… } Error:(30, 27) java: [dereference.of.nullable] dereference of possibly-null reference console
  • 35. ● 단순한 정적 타입 확인이 아닌 코드 흐름과 실행 결과를 반영 ● 코드로 null 확인을 한 경우 @nonNull로 취급 ● 메서드 내부로 제한 자동 타입 개선(Automatic type refinement) private static void password() { Console console = System.console(); char[] password = nonNull(console) ? console.readPassword() : new char[0]; …… } OK
  • 36. ● List, Set, Map, 배열 등 집합 자료형의 요소도 null 확인 ● 기본 @NonNull ● 타입 매개변수에 @Nullable 지정 집합 타입 요소의 null 안정성 지원 private static void printList() { List<String> names = Arrays.asList("kim", "choi", null, "park", "hwang"); for(String name: names) out.println(name); } Error:(42, 43) java: [assignment.type.incompatible] incompatible types in assignment. found : @Initialized @NonNull List<@Initialized @Nullable String>......
  • 37. 정리 null은 왜 문제인가? ● 모든 참조 타입에 지정 가능한 값(상태?), 언어가 지원할 문제 null을 안전하게 다루는 방법 ● API에 null을 최대한 쓰지 말아라 - 반환값은 Optional, Null 객체, 빈값, 예외로 처리 ● 사전 조건과 사후 조건을 확인하라: 계약에 의한 설계(design by contract) ● (상태와 같이) null의 범위를 지역(클래스, 메서드)에 제한하라. ● 초기화를 명확히 하라 null에 안전하다고 보장해주는 도구 ● JSR 305 계열과 JSR 308 계열 ● 가장 성숙한 자바 타입 확인 확장 기술: Checker Framework ● “(원래) 부족한 자바, 고쳐쓰자”