본문 바로가기
Blog/TIL

[240528] 백문이 불여일타!

by 코젼 2024. 5. 28.
728x90
반응형

🔶Database

🔶Lambda

🔶application.properties

🔶Spring


목차

    / 오늘의 TIL /


    Database

    Spring <-> Database 연결

    application.yml 작성

    url에 사용할 database를 작성한다. 하단 예제에서는 library database를 사용했다.

    spring:
      datasource:
        url: "jdbc:mysql://localhost/library"
        username: "root"
        password: ""
        driver-class-name: com.mysql.cj.jdbc.Driver

    새로운 database를 생성하고 싶다면 'create database `데이터베이스명`' 을 작성한다.

    'use `데이터베이스명`'으로 해당 데이터베이스를 사용한다.

     

    JdbcTemplate

    사용하는 클래스의 생성자를 만들어서 JdbcTemplate를 DI해준다.

    • insert, update, delete: jdbcTemplate.update(sql, parameter)
      • sql의 변경사항을 저장한다.
      • 데이터의 변경이 있을 때 update를 사용한다.
    • select: jdbcTemplate.query(sql, new RowMapper<T>)
      • RowMapper: 쿼리의 결과를 받아 객체로 반환한다. (익명 클래스 -> 람다식 변경 가능) 
      • mapRow 메서드를 이용해서 실제 값(필드명)을 ResultSet을 통해 가져와 객체를 반환할 수 있다.
      • select 결과가 있는 경우 0으로 반환된다. (List로 반환된다.)
    jdbcTemplate.query(sql, (rs, rowNum) -> 0);

     


    Lambda

    [키워드]

    익명 클래스 / 람다 / 함수형 프로그래밍 / @FunctionalInterface / 스트림 API / 메소드 레퍼런스

    * 함수형 프로그래밍

    더보기

    함수의 순수성과 불변성을 강조한다.

    1. 순수 함수 (Pure Function):
      • 순수 함수는 동일한 입력에 대해 항상 동일한 출력을 반환하며, 함수 외부의 상태를 변경하지 않습니다.
      • 부작용이 없기 때문에 테스트와 디버깅이 용이합니다.
    2. 불변성 (Immutability):
      • 함수형 프로그래밍에서는 상태가 변경되지 않으며, 모든 데이터는 불변입니다.
      • 변수는 한번 할당되면 변경되지 않고, 새로운 값을 생성할 때는 기존 값을 복사하여 새로운 객체를 만듭니다.
    3. 고차 함수 (Higher-Order Function):
      • 고차 함수는 함수를 인자로 받거나 함수를 반환하는 함수입니다.
      • 예를 들어, map, filter, reduce와 같은 함수는 고차 함수입니다.
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    public class FunctionalProgrammingExample {
        public static void main(String[] args) {
            // 순수 함수 예제
            Function<Integer, Integer> addTen = x -> x + 10;
    
            // 고차 함수 예제 (map 사용)
            List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
            List<Integer> doubled = numbers.stream()
                                           .map(x -> x * 2)
                                           .collect(Collectors.toList());
    
            // 불변성 예제
            System.out.println(doubled); // 출력: [2, 4, 6, 8, 10]
            System.out.println(numbers); // 출력: [1, 2, 3, 4, 5] (원본 리스트는 변경되지 않음)
        }
    }

    * @FunctionalInterface: 컴파일러가 해당 인터페이스가 정확히 하나의 추상 메서드를 가지는지 검증한다. 함수형 프로그래밍을 더 안전하고 명확하게 사용할 수 있도록 도와준다.

    * 스트림: 데이터 처리 파이프라인을 사용하여 코드를 더 간결하고 명확하게 만들어준다. 특히, 병렬 처리 같은 성능 최적화를 할 때 스트림이 유용하다.

    * 메소드 레퍼런스: 이미 존재하는 메소드를 직접 참조하여 람다 표현식을 만들지 않고도 함수형 인터페이스에 구현체를 생성할 수 있다.

    더보기

    종류 / 문법

    1. 정적 메소드 레퍼런스 - 클래스명::정적메소드명

    // 람다식
    Function<String, Integer> parseInt = s -> Integer.parseInt(s);
    
    // 정적 메소드 레퍼런스로 변환
    Function<String, Integer> parseIntRef = Integer::parseInt;

    2. 인스턴스 메소드 레퍼런스 - 객체명::인스턴스메소드명

    // 람다식
    BiFunction<String, String, Boolean> startsWith = (str, prefix) -> str.startsWith(prefix);
    
    // 인스턴스 메소드 레퍼런스로 변환
    BiFunction<String, String, Boolean> startsWithRef = String::startsWith;

    3. 생성자 레퍼런스 - 클래스명::new

    // 람다식
    Supplier<StringBuilder> stringBuilderSupplier = () -> new StringBuilder();
    
    // 생성자 레퍼런스로 변환
    Supplier<StringBuilder> stringBuilderSupplierRef = StringBuilder::new;

    람다식이 등장한 이유

    람다식은 익명 함수를 표현하기 위해 사용된다.

    간결하고 명확하게 작성할 수 있고 일회성 함수를 편리하게 사용하기 위해 등장했다.

    람다식과 익명 클래스 간의 관계

    익명 클래스: 기존 클래스를 확장하거나 인터페이스를 구현할 수 있으며, 메서드를 오버라이드할 수 있다.

    람다식: 함수형 인터페이스(하나의 추상 메서드를 가진 인터페이스)를 구현할 때 사용된다. 익명 클래스보다 간단한 문법을 제공한다.

    • 문법의 간결함: 람다식은 익명 클래스에 비해 문법이 간결하다. 코드가 간단해지고 가독성이 높아진다.
    • 타입 제한: 람다식은 함수형 인터페이스만 구현 가능하지만, 익명 클래스는 여러 메서드를 가진 인터페이스나 추상 클래스도 구현할 수 있다.
    • this 참조: 익명 클래스(익명 클래스 자체), 람다식(람다식을 포함하는 클래스의 인스턴스)

    람다식의 문법

    매개 변수가 하나일 경우는 소괄호를 생략할 수 있다.

    (매개변수 목록) -> { 함수 본문 }

    Spring

    application.properties

    설정을 통해 jdbcTemplate로 진행한 sql query를 확인할 수 있다.

    #jdbcTemplate sql log
    logging.level.org.springframework.jdbc=debug

     

    제어의 역전(IoC) + 의존성 주입(DI)

    IoC(Inversion Of Control): 스프링 컨테이너가 제어권을 가진다.

    DI(Dependency Injection): 스프링 컨테이너가 등록되어있는 스프링 빈을 선택해서 넣어준다.

     

    Repository가 interface이므로, 여러 개의 repository 구현체가 스프링 빈으로 등록되어 있다면

    @Primary 어노테이션을 통해 어떤 repository를 service에서 DI 받을지 결정하는 것이 필요하다.

    @Controller <-> @Service <-> @Repository (interface)
                    스프링 컨테이너가 제어권을 가지고 있다.
                    서비스 객체가 new로 Repository를 선택하지 않는다.

     

    빈 등록하기

    스프링 빈 이름은 클래스명의 앞 글자만 소문자로 바뀌어서 등록된다.

    AppleService -> appleService

    위치에 맞게 함께 선언해서 빈을 등록한다.

    클래스: @Configuration

    메서드: @Bean

     

    * @Configuration + @Bean 조합은 외부 라이브러리, 프레임워크에서 만든 클래스를 등록할 때 사용한다. (ex) JdbcTemplate)

    * @Component -> @Controller, @Service, @Repository... 조합은 개발자가 직접 만든 클래스를 스프링 빈으로 등록할 때 사용한다.

     

    빈 주입하기

    • 생성자 + (@Autowired) (권장)
    • setter + @Autowired -> 보안 취약
    • 필드 + @Autowired -> 테스트를 어렵게 만드는 요인

    @Qualifier("스프링 빈 이름"): 여러 개의 후보 구현체가 있을 때, 하나를 특정해서 주입하고 싶은 경우 사용한다.

    또는 @Qualifier("이름") 동일한 "이름"을 구현체와 호출 Controller에 같이 사용하면 서로 연결된다. (사용/등록 모두 가능)

    728x90
    반응형

    'Blog > TIL' 카테고리의 다른 글

    [240530] 도메인 연관 관계의 중요성  (0) 2024.05.30
    [240529] 직접 해봐야 안다  (0) 2024.05.29
    [240527] 코딩테스트 다다익선  (0) 2024.05.27
    [240526] API 개발하기  (0) 2024.05.26
    [240524] 수학 지식을 넓히자  (0) 2024.05.24

    댓글