나를 기록하다
article thumbnail
반응형

자바를 공부하고 사용한 지 어느덧 5개월이 넘었으나, 람다식에 대해서 제대로 공부를 하지 않았다. 그로 인해 알고리즘이나 기타 강의 등에서 람다식이 등장하면 종종 헷갈리곤 했다. 확실하게 개념을 정리하여 습득할 수 있도록 기록하려 한다.

 

우선 람다식에 대해서 정확하게 이해하려면 함수형 인터페이스를 먼저 알아야 한다.

이번 글에서는 프로그래밍 패러다임부터 시작해서 함수형 프로그래밍에 대해 알아보겠다.

[프로그래밍 패러다임(Programming Paradigm)]

programming paradigm

  • 프로그래밍 스타일을 의미하고 전체적인 프로그래밍 방식을 말한다.
  • 프로그래밍 패러다임은 프로그래머에게 관점을 갖게 해 주고, 결정하는 역할을 한다.
  • 프로그래밍은 순차, 분기, 반복, 참조로 구성되어지고 프로그램 개발을 위하여 전략을 수립해야 함.
  • 전략이란, 어떤 언어를 사용하고, 규약 등을 수립하게 되는데 이러한 전략에 해당하는 내용들이 프로그래밍 패러다임이다.

1) 명령형 프로그래밍 - How

무엇을(What)보다 어떻게(How)를 설명하는 방식

a. 절차(순차)지향 프로그래밍

  • 수행되어야 할 순차적인 처리 과정을 포함하는 방식(C, C++)
  • 단어 그대로 절차적인 명령 수행뿐만 아니라, 프로시저 호출의 개념을 바탕으로 하고 있는 프로그램 패러다임.
  • 데이터와 함수가 분리되지 않고 순차적으로 실행됨.
  • 코드 유지보수가 어려울 수 있음
#include <stdio.h>

// 절차지향 방식으로 두 수를 더하는 함수
int add(int a, int b) {
    return a + b;
}

int main() {
    int x = 5;
    int y = 3;
    int result = add(x, y);
    printf("Result: %d\n", result);
    return 0;
}

b. 객체지향 프로그래밍

  • 객체들의 집합으로 프로그램의 상호작용을 표현(C++, Java, C#)
  • 최소 단위가 객체이며, 객체를 만들고 이 객체를 사용하여 데이터와 메서드를 묶고 소통하는 프로그래밍
  • 상속, 다형성, 캡슐화 등의 개념을 활용하여 직관적이며 코드의 재사용성과 유지보수성을 증가시킴.
// 객체지향 방식으로 두 수를 더하는 클래스
class Calculator {
    int add(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        int x = 5;
        int y = 3;
        int result = calc.add(x, y);
        System.out.println("Result: " + result);
    }
}

2) 선언형 프로그래밍 - What

어떻게(How)보다 무엇(What)을 설명하는 방식

a) 함수형 프로그래밍

  • 최소 단위가 함수이고 함수를 통하여 새로운 데이터를 만들어가며 파이프 형태로 프로그래밍하는 방식
    (Haskell, Lisp, JavaScript (일부 기능))
  • 모든 데이터의 처리를 수학적 함수(function)의 계산으로 취급하여 결과값을 받아보고자 하는 패러다임
  • 함수 단위로 나눠지므로 재사용성이 높음
  • 불변성(Immutability)를 지향하고 순수 함수를 사용하여 동작 예측이 쉽고 Side Effect를 방지
  • 함수에 변수를 할당하고 매개변수로 전달할 수 있음(일급 함수)
  • 재귀와 고차 함수를 활용하여 문제를 해결
// 함수형 방식으로 두 수를 더하는 함수
const add = (a, b) => a + b;

const x = 5;
const y = 3;
const result = add(x, y);
console.log(`Result: ${result}`);

명령형 프로그래밍 vs 선언형 프로그래밍

How vs What

명령형(절차지향) vs 선언형(객체지향)


[함수형 프로그래밍(Functional Programming)]

배경

초기 명령형 프로그래밍 기반으로 개발했던 개발자들은 소프트웨어의 크기가 커짐에 따라 복잡하게 엉킨 스파게티 코드를 유지보수하는 것이 매우 어렵다는 것을 깨달았다. 그리고 이를 해결하기 위해 함수형 프로그래밍이라는 프로그래밍 패러다임에 관심을 가지게 되었다.

함수형 프로그래밍은 거의 모든 것을 순수 함수로 나누어 문제를 해결하는 기법.

작은 문제를 해결하기 위한 함수를 작성하여 가독성을 높이고 유지보수를 용이하게 해준다.

클린코드의 저자 로버트 C.마틴은 함수형 프로그래밍을 대입문 없는 프로그래밍이라 정의하였다.

 

방식

  • 순수 함수를 보조 함수와 조합하고 소프트웨어를 만드는 방식
  • 로직 내에 복잡성을 해결하고 변수 사용을 억제하여 상태 변경을 피하려는 프로그래밍 패러다임

 

특징

부수효과가 없는 순수 함수를 1급 객체로 간주하여 파라미터나 반환값으로 사용할 수 있으며, 참조 투명성을 지킬 수 있다.

키워드: 부수효과, 순수함수, 1급객체, 참조투명성

1. 부수효과(Side Effect)

  1. 변수의 값이 변경됨
  2. 자료 구조를 제자리에서 수정
  3. 객체나 필드값을 설정
  4. 예외나 오류가 발생하며 실행 중단
  5. 콘돌 또는 파일 I/O가 발생

2. 순수 함수(Pure Function)

위와 같은 부수효과를 제거한 함수들을 순수 함수라고 부르며, 함수형 프로그래밍에서 사용하는 함수는 이러한 순수 함수이다.

  1. 메모리 또는 I/O의 관점에서 부수효과(Side Effect)가 없는 함수
  2. 함수의 실행이 외부에 영향을 끼치지 않는 함수
  3. 동일한 입력에 항상 같은 값 반환
  4. 함수 자체가 독립적이며 부수 효과가 없기 때문에 스레드에 안정성을 보장받을 수 있음.
  5. 스레드에 안정성을 보장받아 병렬 처리를 동기화 없이 진행할 수 있음

 

3. 1급 객체(First-Class Object)

사용할때 다른 요소와 아무런 차별이 없는 객체 (자바스크립트 함수는 객체, 일급함수)

  1. 변수나 데이터 구조 안에 담을 수 있음
  2. 파라미터로 전달 가능
  3. 반환값(return value)로 사용 가능
  4. 할당에 사용한 이름과 관계없이 고유한 구별이 가능
  5. 동적으로 프로퍼티 할당이 가능
  6. 비교연산이 가능

 

4. 참조 투명성(Referential Transparency)

  1. 동일한 인자에 대해 항상 동일한 결과를 반환
  2. 참조 투명성을 통해 기존의 값은 변경되지 않고 유지(불변성; immutable)

 

5. 고차 함수

람다 계산법에서 만들어진 용어로 함수는 함수를 파라미터로 전달할 수 있어야하며 함수의 반환값으로 함수를 사용할 수 있다.
(일급 객체의 부분집합)

(React의 고차컴포넌트는 컴포넌트를 이용하여 위의 조건을 만족하는 컴포넌트를 말한다)

 

6. 합성 함수

새로운 함수를 만들거나 계산하기 위해서는 둘 이상의 함수를 조합하는 과정을 말한다.

함수형 프로그래밍은 작은 여러개의 함수들로 이루어져 있기에 이러한 함수들을 연쇄적으로 또는 병렬로 호출해서 더 큰 함수를 만드는 과정으로 전체 프로그래밍을 구축한다.


함수형 프로그래밍 예시

import java.util.List;
import java.util.stream.Collectors;
import java.util.Arrays;

public class StringFunctionalProgrammingExample {
    public static void main(String[] args) {
        // 문자열 리스트 생성
        List<String> words = Arrays.asList("apple", "banana", "cherry", "date", "fig", "grape");


        String result = words.stream()
                .filter(word -> word.length() >= 5) // 1. 문자열 길이가 5 이상인 단어만 필터링
                .map(String::toUpperCase) // 2. 각 단어를 대문자로 변환
                .map(w -> w.substring(0, 1)) // 3. 각 단어의 첫 글자만 잘라냄
                .collect(Collectors.joining(" ")); // 4. 첫 글자들을 스페이스 간격으로 이어붙임
                
        assertThat(result).isEqualTo("A B C G");
    }
}

기존의 for문을 사용하면 지역변수가 필요함 → 함수형 기반의 Stream API에서는 필요 없음

이를 통해 상태를 바꾸는 지역변수를 없앰으로써 부수효과를 제거하여 의도치 않은 문제 해결

 

사용할 함수를 변수로 선언하는 것도 가능하며 함수를 반환하는 것도 가능

@Test
void customFunction() {
    Function<String, String> function = word -> word.toUpperCase();
    assertThat(function.apply("text")).isEqualTo("TEXT");
}

참고자료

https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D_%ED%8C%A8%EB%9F%AC%EB%8B%A4%EC%9E%84

 

프로그래밍 패러다임 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 프로그래밍 패러다임(programming paradigm)은 프로그래밍의 패러다임 형태이다. 소프트웨어 공학을 할 때의 패러다임 형태인 방법론과 비교된다. 프로그래밍 패러

ko.wikipedia.org

https://velog.io/@codenmh0822/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8C%A8%EB%9F%AC%EB%8B%A4%EC%9E%84

 

프로그래밍 패러다임

간단하게 프로그래밍 스타일을 의미하며 전체적인 프로그래밍 방식을 말한다.프로그램은 순차, 분기, 반복, 참조로 구성되어지며 프로그램 개발을 위하여 전략을 수립해야 한다.위에서 말한 전

velog.io

https://khj93.tistory.com/entry/JAVA-%EB%9E%8C%EB%8B%A4%EC%8B%9DRambda%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EA%B3%A0-%EC%82%AC%EC%9A%A9%EB%B2%95

 

[JAVA] 람다식(Lambda)의 개념 및 사용법

람다함수란? 람다 함수는 프로그래밍 언어에서 사용되는 개념으로 익명 함수(Anonymous functions)를 지칭하는 용어입니다. 현재 사용되고 있는 람다의 근간은 수학과 기초 컴퓨터과학 분야에서의 람

khj93.tistory.com

https://bcp0109.tistory.com/313

 

Java 8 함수형 인터페이스 (Functional Interface)

Overview 함수형 인터페이스란 1 개의 추상 메소드를 갖는 인터페이스를 말합니다. Java8 부터 인터페이스는 기본 구현체를 포함한 디폴트 메서드 (default method) 를 포함할 수 있습니다. 여러 개의 디

bcp0109.tistory.com

https://mangkyu.tistory.com/111

 

[프로그래밍] 함수형 프로그래밍(Functional Programming) 이란?

1. 함수형 프로그래밍(Functional Programming)에 대한 이해 [ 프로그래밍 패러다임(Programming Paradigm) ] 프로그래밍 패러다임(Programming Paradigm)은 프로그래머에게 프로그래밍의 관점을 갖게 하고 코드를

mangkyu.tistory.com

 

반응형
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...