함수형 자바스크립트를 위한 기초

|

Spring JDBC와 Classic JDBC의 차이

Classic JDBC

  • 안정적이고, 유연한 기술이지만 SQL 준비, 바인딩, 실행결과 받아서 처리하는과정이 코드가 너무 길고 반복적입니다.
  • Connection pool 관리를 잘못하면, 시스템 리소스가 바닥이 날 수 있습니다.
  • transaction 처리 과정이 반복적이며, 프로그래머가 일일이 commit, rollback을 해줘야합니다.

스프링 JDBC

  • SQL 준비, 바인딩, 실행하는 반복적인 작업을 SPRING이 대신 실행합니다
  • 기존 JDBC에 비해 SQL문 오류 결과를 확인하기 편합니다 ( RuntimeException으로 확인이 가능 )
  • Connection을 관리해줍니다 ( Spring에서 datasource 부분을 bean으로 등록해야합니다 )
  • transaction에 관한 부분을, spring이 aop 기술을 통해서 commit,rollback을 해줍니다

JDBC TEMPLATE

  • SQL문에 관련된 작업을 도와줍니다
  • update 메소드 : insert, update, delete에 대한 작업을 도와줍니다
  • query 메소드 : select로 여러개의 row 결과값을 가져 올 때 사용합니다
  • queryForObject : 한건의 row 결과값을 가져 올 때 사용합니다

금일 공부한 키워드

  • jdbc
  • jdbc template

람다표현식

|

자바람다식 = 익명함수 = 자바(익명메소드,익명객체를 말합니다)

람다식은 일반적으로 익명함수를 뜻한다

  • 익명함수는 말그대로 이름이 없는 함수이다 ( 다른 말로는 1급 객체라고 말한다. )
  • 반대의 뜻으로 선언적함수가 있다. 함수의 이름을 선언하는걸 선언적 함수라고 한다.

그럼 1급 객체의 조건은 무엇인가

  1. 변수(variables)에 담을수 있다.
  2. 인자(parameter)로 전달할 수 있다.
  3. 반환값(return)값으로 전달할 수 있다.
  • 자바에서 1급 시민은 객체입니다. 객체는 변수에 담을수 있고, 인자로 전달 될 수 있으며, 반환값으로 전달될 수 있습니다.
  • 즉 언어들중 람다표현법을 사용하는 언어들은 서로 비슷한 형태의 1급 시민을 가지고 있습니다.

자바에서 인터페이스중 메소드를 하나만 가지고 있는 인터페이스를 함수형 인터페이스 = 람다 인터페이스라고 부릅니다.

  • 자바에서 메소드만 매개변수로 전달할수 없기 때문에 객체를 인스턴스로 만들어서 전달합니다.
  • 그렇기 때문에 만약 객체가 아닌 구현하고 싶은 메소드만 전달 할 수 있었다면 얼마나 좋았을까?
  • 이런 이유로 도입된 것이 자바 8부터 지원이 가능한 람다식입니다.

// 기존 표현식

new Thread(new Runnable() {
@Override
public void run() { // Runnable 인터페이스 있는 run 메소드 오버라이딩해서 실행합니다.
System.out.println("Hello World.");
}
}).start();

// 람다표현식

new Thread(()->{
// new Runnalbe() { @Override run 메소드 구현 하는 부분이 사라졌습니다.
// 이게 가능한 이유는 Runnable이 한개의 메소드만 가진 함수형 인터페이스 이기 때문에 가능합니다.
// 즉 기본적으로 람다식을 위한 인터페이스에서 추상 메소드는 반드시 하나여야합니다.
// 예외로 Object로 상속받는 equals, compareTo, toString 등등은 추상메소드와 같이 사용할 수 있습니다.

System.out.println("Hello World.");
}).start();

  • 또한 @FunctionalInterface 어노테이션을 사용하면, 해당 인터페이스에 메소드가 2개 이상 선언되면
  • 에러가 발생합니다.

금일 공부한 키워드

  • 리플렉션 ( 스프링에서 구현하고 있는 자바기술 -> xml config파일 설정을 읽어오거나 DI 컨테이너를 구현하는 기술 )
  • 프록시
  • 람다표현식
  • 다이나믹 프락시 ( 스프링 AOP에서 프록시 기반의 기술을 구현하고 있습니다 )
  • 1급 객체

Spring, Spel, java Config, xml config

|

1. 스프링에서 사용하는 기술

  • java 의 리플렉션이란 기술을 이용하면 interface를 구현하는 인스턴스를 동적으로 생성할 수 있다. - Java Proxy
  • java 기본으로 제공하는 기술로는 특정 클래스를 상속받는 인스턴스를 동적으로 생성할 수 없다. 오픈소스로 가능
  • 대표적인 프로젝트가 cglib

  • Spring이 java config를 읽어들이면, 해당 java config 클래스를 상속받는 객체를 동적으로 생성한다.
  • 클래스파일 없이 인스턴스를 만들수있다 -> 메모리상에만 클래스파일을 만들어서 처리한다 (다만 실제로 디스크상에는 존재하지 않는다)
class DiceConfig$$EnhancerBySpringCGLIB$$2b1a2b2f
        extends DiceConfig{
    @Bean
    public Dice dice(){
        // 처음호출되었느냐? 아니냐?
        // 처음호출되었을 경우엔
        return super.dice();
        // 처음이 아닐 경우
        // id가 Dice가 이미 저장되어 있으니 해당 dice를 리턴.
    }
}
  • Spring은 @Configuration이 붙어있는 클래스를 Java Config로 인식한다.
  • Bean을 생성하는 메소드에는 @Bean 애노테이션이 붙는다. ( @Bean이 생성된 메소드는 컨테이너가 관리하는 객체라는 뜻이다)
  • Spring이 xml,java config파일을 읽어올때 위에서 아래로 순서대로 읽는게 아닌, 필요순서에 따라서 읽는다.

@Configuration
public class DiceConfig {

    /*

    빈을 생성하는 메소드에는 @Bean 애노테이션이 붙는다.
    메소드 이름이 id값이 된다.

    ex) config.xml
    <bean id="dice" class="soundsystem.Dice">
        <constructor-arg value="6"/>
    </bean>

    */

    @Bean
    public Dice dice(){
        System.out.println("dice() --------------------------");
        System.out.println(getClass().getName());
        return new Dice(6);
    }

    /*
    스프링 컨테이너가 kim이란 메소드를 호출하는데 파라미터로 Dice객체를 자동으로 넣어준다.
     */
    @Bean
    public Player kim(){
        System.out.println("kim()");
        Player player = new Player();
        player.setDice(dice());
        player.setName("kim");
        return player;
    }

    @Bean
    public Player kang(){
        System.out.println("kang()");
        Player player = new Player();
        player.setDice(dice());
        player.setName("kang");
        return player;
    }

    @Bean
    public Game game(){
        System.out.println("Game()");
        Game game = new Game();
        List<Player> list = new ArrayList<>();
        list.add(kim());
        list.add(kang());
        list.add(lee());
        game.setPlayerList(list);
        return game;
    }
}


// java config로 hikaricp 연동파일 예시

@Configuration // configuration이 붙었기 때문에 해당 클래스의 정보를 모두 config로 읽어들인다
@PropertySource("classpath:datasource.properties")
// classpath(resource) 에서 datasource.properties라는 파일을 읽어온다.

public class DataSourceConfig {
    // db 설정파일 처럼 외부에 유출되면 안되는 정보는 외부에서 읽어온다.
    @Value( "${jdbcUrl}" )
    private String jdbcUrl;
    @Value( "${driverClassName}" )
    private String driverClassName;
    @Value( "${username}" )
    private String username;
    @Value( "${password}" )
    private String password;

    @Bean
    public HikariConfig hikariConfig(){
        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setJdbcUrl(jdbcUrl);
        hikariConfig.setDriverClassName(driverClassName);
        hikariConfig.setUsername(username);
        hikariConfig.setPassword(password);
        return hikariConfig;
    }

    @Bean
    public DataSource dataSource(HikariConfig hikariConfig){
        return new HikariDataSource(hikariConfig);
    }
}


2. Spring Expression Language

  • 스프링은 3.0부터 SpEL(Spring Expression Language)를 지원한다. 다른 언어의 el ( expression language) 방식과 유사하다.
  • SpEL은 강력한 표현언어로 XML이나 JAVA CONFIG 파일에 많이 사용된다.
  • SpEL 표현식은 # 기호로 시작하고 {expression} 중괄호로 묶입니다. 속성은 $로 시작하고, ${property.name}와 같이 중괄호로 묶인 유사한 방식으로 참조될 수 있습니다.

// SpEL은 기본적인 사칙연산, 제곱 등 MATH 에 관련된 기능을 제공해줍니다.

@Value("#{19 + 1}") // 20
private double add;

@Value("#{'String1 ' + 'string2'}") // "String1 string2"
private String addString;

@Value("#{20 - 1}") // 19
private double subtract;

@Value("#{10 * 2}") // 20
private double multiply;

@Value("#{36 / 2}") // 19
private double divide;

@Value("#{36 div 2}") // 18, the same as for / operator
private double divideAlphabetic;

@Value("#{37 % 10}") // 7
private double modulo;

@Value("#{37 mod 10}") // 7, the same as for % operator
private double moduloAlphabetic;

@Value("#{2 ^ 9}") // 512
private double powerOf;

@Value("#{(2 + 2) * 2 + 9}") // 17
private double brackets;

// 또한 기본적인 관계연산자 및 논리연산자도 제공해줍니다.
// XML에서는 <,<=,>,>= 같은 논리연산자를 사용할 수 없지만 대신에 lt,le,gt,ge를 사용할 수 있습니다.

@Value("#{1 == 1}") // true
private boolean equal;

@Value("#{1 eq 1}") // true
private boolean equalAlphabetic;

@Value("#{1 != 1}") // false
private boolean notEqual;

@Value("#{1 ne 1}") // false
private boolean notEqualAlphabetic;

@Value("#{1 < 1}") // false
private boolean lessThan;

@Value("#{1 lt 1}") // false
private boolean lessThanAlphabetic;

@Value("#{1 <= 1}") // true
private boolean lessThanOrEqual;

@Value("#{1 le 1}") // true
private boolean lessThanOrEqualAlphabetic;

@Value("#{1 > 1}") // false
private boolean greaterThan;

@Value("#{1 gt 1}") // false
private boolean greaterThanAlphabetic;

@Value("#{1 >= 1}") // true
private boolean greaterThanOrEqual;

@Value("#{1 ge 1}") // true
private boolean greaterThanOrEqualAlphabetic;

// SpEL은 기본적인 논리연산 또한 제공해줍니다.

@Value("#{250 > 200 && 200 < 4000}") // true
private boolean and;

@Value("#{250 > 200 and 200 < 4000}") // true
private boolean andAlphabetic;

@Value("#{400 > 300 || 150 < 100}") // true
private boolean or;

@Value("#{400 > 300 or 150 < 100}") // true
private boolean orAlphabetic;

@Value("#{!true}") // false
private boolean not;

@Value("#{not true}") // false
private boolean notAlphabetic;

// 삼항연산자
@Value("#{2 > 1 ? 'a' : 'b'}") // "a"
private String ternary;

@Value("#{someBean.someProperty != null ? someBean.someProperty : 'default'}")
private String ternary;

// 정규표현식 지원

@Value("#{'100' matches '\\d+' }") // true
private boolean validNumericStringResult;

@Value("#{'100fghdjf' matches '\\d+' }") // false
private boolean invalidNumericStringResult;

@Value("#{'valid alphabetic string' matches '[a-zA-Z\\s]+' }") // true
private boolean validAlphabeticStringResult;

@Value("#{'invalid alphabetic string #$1' matches '[a-zA-Z\\s]+' }") // false
private boolean invalidAlphabeticStringResult;

@Value("#{someBean.someValue matches '\d+'}") // true if someValue contains only digits
private boolean validNumericValue;

  • 논리, 관계, 계산식, 인터페이스 구현등 대부분의 형식을 지원한다.
  • 이외에도 Expression 인터페이스에도 사용이 가능하다. 스프링내에서 사용할 수 있는 강력한 언어 표현식이다.

서블릿 필터란?

|

서블릿 필터란?

서블릿 <-> 서블릿필터 <-> 브라우저

  • 서블릿 필터는 서블릿과 브라우저 사이에서 동작한다.
  • Request, Response 할때마다 서블릿과 브라우저 사이에서 필터 역활을 수행해준다.

  • 예시로 서블릿 필터가 있을경우 기본적으로 브라우저와 서블릿이 통신할 때 서블릿에서 처리했던 작업들을 필터에서 모두 처리해줄 수 있다.

  • 필터를 사용하는 목적은 서블릿 상단에서 모든걸 처리하는 것 자체가 비생산적이다.
  • 결국 중복코드를 쓰지 않도록 지양하고, 재사용성과 응집도가 높은 코드를 지향하기 위해서 사용하는것이다.

package my.examples.jdbcboard.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

// /* : 어떤 url로 서블릿에 접근하든간에 무조건 이 필터를 거치게 됨. 
@WebFilter(filterName="RequestEncodingFilter", urlPatterns = {"/*"})
public class RequestEncodingFilter implements Filter {
    @Override // 초기화
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("RequestEncodingFilter init!");
    } 

    @Override // 필터
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        servletRequest.setCharacterEncoding("UTF-8");
        System.out.println("RequestEncodingFilter doFilter start!!");
        filterChain.doFilter(servletRequest, servletResponse); 
        // 필터체인을 통해서 여러가지 필터를 통하게 할 수 있다.
        // ex) 로그인 체크 -> url 경로 기억 -> 로그인시 그전 url 경로로 이동 등등
        // 다음 필터를 호출
        // 서블릿 응답후
        System.out.println("RequestEncodingFilter doFilter end!!");
    }

    @Override // 종료
    public void destroy() {
        System.out.println("RequestEncodingFilter destroy!");
    }
}

함수형프로그래밍란?

|

프레임워크란?

  • 프레임워크는 Application 개발시 코드의 품질, 필수적인 코드, 알고리즘, 암호화, 데이터베이스 연동 같은 기능들을
  • 어느정도 구성이 되어있는 뼈대(구조)를 제공하도록 만들어진걸 프레임워크라고합니다.
  • 개발 구조나 설계 시 제공되는 인터페이스의 집합입니다. 완성된 어플리케이션은 아니지만
  • 어느정도 프로그래머가 제공된 프레임워크의 구조에서 어플리케이션을 개발해야합니다.

Library란?

  • 라이브러리는 특정기능에 대한 API를 모은 집합을 라이브러리라고 합니다.
  • 그 기능을 사용하기 위해 불러와서 호출하는 방식을 사용합니다.

Framework와 Library의 차이

  • 토비의 스프링에서 말하는 프레임워크와 라이브러리의 차이
프레임워크는 단지 미리 만들어 둔 반제품이나, 확장해서 사용할 수 있도록 준비된 
추상 라이브러리의 집합이 아니다. 프레임워크가 어떤 것인지 이해하려면 라이브러리와 
프레임워크가 어떻게 다른지 알아야 한다.
라이브러리를 사용하는 애플리케이션 코드는 애플리케이션 흐름을 직접 제어한다. 
단지 동작하는 중에 필요한 기능이 있을 때 능동적으로 라이브러리를 사용할 뿐이다.
반면에 프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 의해 사용된다.
프레임워크에는 분명한 제어의 역전 개념이 적용되어 있어야 합니다.
애플리케이션 코드는 프레임워크가 짜놓은 틀에서 수동적으로 동작해야 합니다.
  • 어플리케이션의 flow을 누가 제어하느냐에 따라서 프레임워크인지 라이브러리 인지 구별할 수 있었습니다.
  • 제어흐름(flow)에 대한 주도성이 누군가에게 있느냐에 달려있습니다.
  • 라이브러리는 톱,망치,삽같은 연장입니다. 사용자가 용도에 맞게 혹은 다르게 사용 할수도 있습니다.
  • 들고 내려치고 파도 되고, 급하면 망치를 다른용도로 쓸 수 도 있습니다.

  • 프레임워크는 차나 비행기 배같은 것입니다. 차를 타고 하늘을 날 수는 없습니다.
  • 용도가 분명히 정해져있고, 차를 타고 바다를 건널수는 없습니다. 그저 정해진 규칙과, 규정에 따라서 사용해야합니다.
  • 라이브러리와 다르게 프레임워크는 프로그래밍의 규칙이 정해져있으며, XML에 어떤 태그를 사용해야 하는지,
  • DB 연동을 하기 위해서 어떻게 해야하는지 등등 사람이 마치 자동차를 운전하듯이 사용방법이 정해져있습니다.
  1. [링크1] (https://webclub.tistory.com/458)
  2. [링크2] (https://kldp.org/node/124237)
  3. [링크3] (https://web-front-end.tistory.com/63)