본문 바로가기
개발이야기

Funtional Programming은 어떻게 가능하게 되었을까?

by janiiiiie 2021. 11. 15.
반응형

 

Overview

Java 8 버전 이상을 사용하는 분들이라면 아마 Functional Programming 을 적극적으로 이용하시는 분들이 많을 거라 생각합니다. 자바 8버전 부터 Stream API와 함께 추가 된 대표적인 기능 중 하나이죠.

 

저 또한 개발 중에 함수형 프로그래밍으로 코드를 많이 짜고 있는데요, 처음 사용했을 때 가장 신기했던 것은 -> (람다식)을 사용하여 추가적인 메서드를 생성하지 않아도 익명함수를 활용하여 내부 값을 불러올 수 있다는 점이었습니다. 그러다보니 자연스럽게 코드도 간결해지게 되었죠.

 

그러다 하나 의문점이 생겨나게 되었는데 그 점은 바로 아무거나 함수형 프로그래밍으로 사용할 수 있는걸까? 하는 궁금증이었습니다.

만약 아무거나 함수형으로 쓸 수 없다면 내부 구현은 어떻게 되어있는지 궁금하여 소스코드를 까보게 되었습니다.

 

 

 

 대표적으로 많이 쓰이는 ForEach 로 확인해보자

보편적으로 많이 쓰는 함수 중에 forEach() 문이 있습니다. 필자도 다른 for문 문법보다 이 방식을 많이 활용을 하고 있습니다. 보통은 아래와 같은 형태로 코드를 짜게 됩니다.

 

createMenuReviewRequestList.forEach(createMenuReviews -> {
            MenuReviews menuReviews = new MenuReviews();
            given(authService.getMemberId(token)).willReturn(memberId);
            given(memberRepository.findById(memberId)).willReturn(Optional.ofNullable(members));
            given(bakeriesRepository.findById(bakeryId)).willReturn(Optional.ofNullable(bakeries));
}
......

 

리스트를 가져와 바로 forEach()로 연결시켜 준다면 내부 값을 알아서 하나씩 호출하여 동작을 시켜줍니다. 이러한 함수형 프로그래밍은 내부에 어떻게 구현되어있을까요?

 

forEach를 까보면 Consumer 라는 인터페이스를 받고 있습니다. 그렇다면 Consumer는 어떤 식으로 짜여져 있을까요?

 

 

Consumer Interface

@Functionallnterface 라는 어노테이션이 보이나요? 함수형 프로그래밍은 바로 이 어노테이션이 붙은 Consumer를 구현 받아야지만 익명함수를 통하여 비로소 이용할 수 있게 됩니다. (이 어노테이션이 붙으면 함수형 프로그래밍 조건에 맞는지도 컴파일 시 모두 확인한다고 합니다.)

 

Consumer의 경우 인자를 받아서 처리할 수 있도록 구현되어 있기 때문에 해당 Interface를 구현받는 forEach는 인자를 받고, 그 대상을 처리하는 식으로 구현되어 있습니다.

 

 

Supplier Interface

Consumer 이외에도 Supplier 라는 것도 들어보셨을 것이라고 생각합니다. 함수형 프로그래밍으로 하다보면 아래와 같이 짜여진 코드도 많이 발견하게 됩니다.

 

BreadCategoryType breadCategoryType = Optional.ofNullable(BreadCategoryType.fromString(category))
                .orElseThrow(() -> new ResponseStatusException(HttpStatus.BAD_REQUEST, "존재하지 않는 빵 카테고리입니다."));

Null 체크에 유용한 Optional 을 사용할 때 많이 보이는 패턴입니다. 이렇게 () -> 식의 코드를 사용하는 경우인데요, 이 orElseThrow의 경우 아래와 같이 Supplier 라는 인터페이스를 받고 있습니다.

 

 

Supplier는 인자를 전달 받지 않아도 되는 특징이 있기 때문에 개발자가 사용할 때는 () -> 식으로만 사용할 수 있는 것입니다.

 

Supplier 인터페이스 또한, Consumer 와 마찬가지고 @FunctionalInterface 가 선언되어 있기 때문에 익명함수로 사용할 수 있는 것입니다 :) 

 

 

 

Referenced by

 

https://www.baeldung.com/java-8-functional-interfaces

 

Baeldung 에 설명이 잘 되어있어 도움이 많이 되었습니다. 한번 같이 읽어보면 좋을 거 같네요 :)

 

반응형