람다 표현식이란?


자바 8에 추가된 함수형 프로그래밍 요소

객체지향이 객체의 필드에 데이터를 저장하고 그를 다루는데에 반해,

함수형 프로그래밍은 선언적이어서 statement보다 선언, 혹은 표현식을 사용한다.

 

자바8의 람다식은 다음과 같은 형태를 가진다


parameters -> expression body

ex ) Comparator comparator = (a, b) -> a.compareTo(b)



람다 표현식의 특징


  1. 타입 선언이 선택적이다 .

  2. 싱글 파라미터의 경우 괄호가 필요 없다.

  3. 중괄호 선택 : 한문장일 경우 중괄호가 필요 없다

  4. return 키워드 선택 : 한문장일 경우 생략 가능하다, 다만 중괄호를 포함한 경우 무조건 return 포함해야한다.

 

람다식을 이용하려면 오버라이드 할 메서드가 포함된 함수형 인터페이스가 필요하다.

함수형 인터페이스는 함수를 하나만 가지는 인터페이스에, 함수형 인터페이스 어노테이션(@FunctionalInterface)를 붙여 명시한다.

자바 API에 내장된 대표적인 함수형 인터페이스로는 Runable이나 Comparator가 있다.

 



Java 8 이전 방식과 람다 표현식


1. 클래스 생성

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("I have implemented Runnable");
    }
 
    public static void main(String args[]) {
        MyRunnable runnable = new MyRunnable();
        runnable.run();
    }
}
2. 익명 클래스

Runnable runnable = new Runnable() {
  @Override
  public void run() {
    System.out.println("I have implemented Runnable");
  }
};
runnable.run();

3. 람다식 사용

Runnable runnable = () -> System.out.println("I have implemented Runnable");
runnable.run();



함수형 인터페이스

 

람다를 사용하기 위해선 추상메서드를 하나만 가지는 함수형 인터페이스가 필요하다.

함수형 메서드의 추상 메서드 시그너처를 함수 디스크립터라고 한다.

 

자바8에는 java.util.function에 Predicate, Consumer, Function 등, 그 외 여러 인터페이스가 이미 구현되어있다.

 

대표적인 함수형 인터페이스


함수형 인터페이스

함수 디스크립터

Predicate<T>

T->boolean

Consumer<T>

T->void

Function<T, R>

T->R

Supplier<T>

()->T

UnaryOperator<T>

T->T

BinaryOperator<T>

(T, T)->T

BiPredicate<L, R>

(L, R)->boolean

BiConsumer<L, R>

(L, R)->void

BiFunction<T, U, R>

(T, U,)->R


  • autoboxing에 대한 리소스를 줄이기 위해 각 함수형 인터페이스엔 기본형 특화 인터페이스가 존재하며, 인터페이스 네임 서두에 자료형을 붙인 형태이다.

  • Function같은 경우 파라미터와 반환형을 명시하기 위해 ToIntFunction, DoubleToIntFunction등이 존재한다.

 

형식 검사


컴파일러는 람다가 사용되는 컨텍스트를 기반으로 람다의 형식을 추론한다.

어떤 컨텍스트에서 기대되는 람다 표현식의 형식을 대상 형식이라고 부른다.

형식을 검사하는 순서는 다음과 같다.


  1. 람다 선언부 확인(람다가 매서드 파라미터로 사용시 매서드 선언부 확인)

  2. 선언부에서 대상형식 확인.

  3. 대상형식이 함수형 인터페이스인지 확인.

  4. 대상형식의 추상 메서드 확인.

  5. 추상메서드의 함수 디스크립터와 람다의 시그니처를 비교하여 형식 검사를 완료한다.

 

형식 추론


자바 컴파일러는 콘텍스트를 통해 람다 표현식과 관련된 함수형 인터페이스를 추론한다..

즉 형식 검사를 통해 함수 디스크립터를 알 수 있으므로, 컴파일러는 람다의 시그니처 또한 추론 할 수 있다.

람다의 시그니쳐 추론을 통해 람다 표현식의 파라미터 형식에 접근 할 수 있으므로 파라미터의 형식이 생략 가능하다.

(앞서 정리한 특징 중 '1. 타입 선언이 선택적이다'에 해당한다.)

 

 


람다 표현식의 유효 범위


람다표현식은 java에서 정의된 명명규칙인 name conflicts와 shadowing 규칙이 똑같이 적용된다.

즉 람다 파라미터나 람다 표현식 내에 람다가 선언되는 지역의 지역변수와 똑같은 이름의 변수를 선언 할 수 없다.

this키워드 또한 람다표현식 내에서 사용할 경우, 람다 표현식이 선언되는 메서드의 this 파라미터를 의미한다.


 

외부 유효범위의 변수 접근


람다 표현식 외부에 있는 변수를 람다가 사용할 경우, 해당 변수를 자유 변수라 부른다.

람다가 자유변수를 capture하기 위해서

자유 변수는 final이거나 변하지 않는 effectivley final 변수여야 한다.




참조 : https://dzone.com/articles/a-little-lambda-tutorial, 카이호스트만 코어 자바 8

웹개발을 시작하기 전부터 질리도록 들었던 단어가 있다. 바로 MVC 패턴으로, 이는 웹개발 관련 블로그나 커뮤니티에서 하루도 빠짐없이 언급 될 정도로 웹 개발 하면 필수적으로 알아야 할 디자인 패턴이다. MVC패턴에 대해 설명하기 전에 모델 1 구조와 모델 2 구조를 먼저 설명하고자 한다.

JSP로 구성할 수 있는 웹 어플리케이션의 아키텍쳐는 크게 모델 1, 모델 2로 나뉜다. 이 두 모델의 큰 차이점은 JSP가 결과의 출력 뿐만 아니라 요청에 대한 모든 로직들을 처리하냐, JSP는 결과의 출력만 담당하냐의 차이이다.


1. 모델 1 구조


모델 1은 뷰와 로직을 모두 JSP 페이지 하나에서 처리하는 구조를 말하며, 위 사진과 같은 구성을 띈다. 모델 1을 구성하는 요소는 크게 나누면 다음과 같다.

1. JSP

2. 자바빈 혹은 서비스 클래스

 JSP 페이지 내에 로직 처리르 위한 자바 코드가 출력을 위한 코드와 함께 섞여 삽입된다. 브라우져에서 요청이 들어오면 JSP 페이지는 자신이 직접 자바빈이나 따로 작성한 서비스 클래스를 이용하여 작업을 처리하고, 그 처리한 정보를 클라이언트에 출력한다. 과거에 가장 많이 사용되었던 아키텍쳐로, 간단한 페이지를 구성하거나 여러 책의 초반 예제로 많이 사용되기때문에 익숙한 방식이다. 모델 1은 다음과 같은 장점과 단점을 가지고있다.


 장점

 단점

- 구조가 단순하여 익히기가 쉽다.

- 위와 같은 이유로 숙련된 개발자가 아니더라도 구현이 용이하다.

- 출력을 위한 뷰 코드와 로직 처리를 위한 자바 코드가 함께 섞이기 때문에 JSP 코드 자체가 복잡해진다.

- JSP 코드에서 백엔드와 프론트엔드가 혼재되기 때문에 분업이 용이하지 않다.

- 코드가 복잡해져 유지보수가 어렵다.



2. 모델 2 구조



모델 2는 모든 처리를 JSP 페이지 하나가 담당하는것과는 달리 JSP페이지와 서블릿, 그리고 로직을 위한 클래스가 나뉘어 브라우저 요청을 처리한다. 모델 2를 구성하는 요소는 다음과 같다.

1. 서블릿

2. JSP

3. 자바빈 혹은 서비스 클래스

  요청이 들어오면 요청에 대한 로직 처리는 이를 처리할 모델(Model)인 서비스클래스 혹은 자바빈이 담당하고, 요청 결과는 유저에게 결과를 보여줄 뷰(View)단인 JSP에 출력되며,  이를 위한 모든 흐름 제어는 컨트롤러(Controller)서블릿에서 담당한다.



3. MVC 패턴과 모델2

즉 모델 2 구조란 MVC(Model-View-Controller) 패턴을 웹 개발에 도입한 구조이며. 모델 2와 MVC 패턴의 형태는 완전히 같은 형태를 가진다.

MVC 패턴

모델 2

 

Model

서비스 클래스 or 자바빈 

 비즈니스 로직을 처리하는 모든것들이 모델에 속한다. 컨트롤러로부터  특정 로직에 대한 처리 요청(ex: 게시판 글쓰기, 회원가입, 로그인 등)이 들어오면 이를 수행하고 수행 결과를 컨트롤러에 반환한다. 필요한 정보는 request 객체나 session 객체에 저장하기도 한다.

View 

JSP 페이지 

 클라이언트에 출력되는 화면을 말한다. 모델1과 달리 로직 처리를 위한 코드가 내포되어 있지 않다. 요쳥 결과의 출력 뿐만 아니라 컨트롤러에 요청을 보내는 용도로도 사용된다. request 객체나 session 객체에 저장된 정보를 토대로 화면을 출력한다.

Controller 

서블릿 

 MVC 패턴(모델 2)모든 흐름 제어를 맡는다. 브라우져로부터 요청이 들어오면, 어떤 요청인지를 분석하여 이 요청을 처리하기 위한 모델을 사용하여 처리한다. 사용한 모델로부터 처리 결과를 받으면 추가로 처리하거나 가공해야할 정보가 있다면 처리 후 request 객체나 session객체에 저장하고, 뷰(JSP 페이지)를 선택하여 foward나 redirect 하여 클라이언트에 출력한다.


모델 2(MVC 패턴)은 모델1의 단점에 의해 탄생했기 때문에, 모델1이 가지고있는 모든 단점들을 해소하였지만 반대로 다루기 어렵다는 단점이 있다.


 장점

 단점

- 출력을 위한 뷰 코드와 로직 처리를 위한 자바 코드를 분리하기 때문에 JSP 모델1에 비해 코드가 복잡하지 않다.

- 뷰, 로직처리에 대한 분업이 용이하다.

- 기능에 따라 분리되어있기 때문에 유지보수가 용이하다.

- 구조가 복잡하여 습득이 어렵고 작업량이 많다.

- JAVA에 대한 깊은 이해가 필요하다.


모델 1 VS 모델 2

모델 2가 뒤늦게 나왔다고 무조건 장점만 가지고 있는 것은 아니다. 모델 2는 규모가 큰 프로젝트나 업데이트가 빈번한 프로젝트엔 용이할지는 모른다. 하지만 규모가 많이 크지 않고 업데이트가 적은 프로젝트일 경우엔 쓸대없이 복잡한 형태로 작업량이 늘어날 뿐이다. 이 경우에는 간단한 모델 1으로 개발하는게 더 나을수도 있다. 모델 1과 모델 2은 완전히 다른 장점과 단점을 가지고 있으므로 하나만 무조건적으로 사용한다기보단 상황에따라 적절한 선택이 필요할 것 같다. 


'JAVA > JSP,Servlet' 카테고리의 다른 글

커넥션풀(Connection Pool) - DBCP 예제  (0) 2016.02.08


커넥션 풀이란 db와 연결하는 커넥션을 미리 생성해두고 풀에 저장해두었다 필요할때 꺼내쓰고, 사용후에는 다시 풀에 반환하는 기법을 말한다.
(멀티쓰레드의 쓰레드풀과 유사하다.)
커넥션을 미리 생성해두기 때문에 커넥션을 사용자가 db를 사용할때마다 매번 생성을 하는것보다 더 빠른 속도를 보장한다.
또한 커넥션의 최대 생성 갯수도 제어해주기 때문에 많은 사용자가 몰려도 과부화를 방지할 수 있다.



커넥션 풀의 오픈소스에는 대표적으로 DBCP와 C3P0이 있는데 여기선 DBCP를 사용하였다. DBCP는 아파치 사이트에서 받을수 있는데, 그 외에 DBCP에서 사용한 Pool인 Commons Pool이 필요하고, 부가적으로 로그 기록에 사용되는 Commons Logging도 필요하다.
각각의 API는 아래 링크에서 받을 수 있다.



1. DBCPInit.java
package jdbc;

import java.sql.DriverManager;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.commons.dbcp2.ConnectionFactory;
import org.apache.commons.dbcp2.DriverManagerConnectionFactory;
import org.apache.commons.dbcp2.PoolableConnection;
import org.apache.commons.dbcp2.PoolableConnectionFactory;
import org.apache.commons.dbcp2.PoolingDriver;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class DBCPInit extends HttpServlet {

    @Override
    public void init() throws ServletException {
            loadJDBCDriver();
            initConnectionPool();
    }
    private void loadJDBCDriver() {
        try {
            //커넥션 풀에서 사용할 jdbc 드라이버를 로딩
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException("fail to load JDBC Driver", ex);
        }
    }
    private void initConnectionPool() {
        try {
            String jdbcUrl = "jdbc:mysql://localhost:3306/chap14?" + "useUnicode=true&characterEncoding=utf8";
            String username = "phs1116";
            String pw = "1234";
            
            //커넥션팩토리 생성. 커넥션 팩토리는 새로운 커넥션을 생성할때 사용한다.
            ConnectionFactory connFactory = new DriverManagerConnectionFactory(jdbcUrl, username, pw);
            
            //DBCP가 커넥션 풀에 커넥션을 보관할때 사용하는 PoolableConnectionFactory 생성
            //실제로 내부적으로 커넥션을 담고있고 커넥션을 관리하는데 기능을 제공한다. ex)커넥션을 close하면 종료하지 않고 커넥션 풀에 반환
            PoolableConnectionFactory poolableConnFactory = new PoolableConnectionFactory(connFactory, null);
            //커넥션이 유효한지 확인할때 사용하는 쿼리를 설정한다.
            poolableConnFactory.setValidationQuery("select 1");
            
            
            //커넥션 풀의 설정 정보를 생성한다.
            GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
            //유휴 커넥션 검사 주기
            poolConfig.setTimeBetweenEvictionRunsMillis(1000L * 60L * 1L);
            //풀에 있는 커넥션이 유효한지 검사 유무 설정
            poolConfig.setTestWhileIdle(true);
            //커넥션 최소갯수 설정
            poolConfig.setMinIdle(4);
            //커넥션 최대 갯수 설정
            poolConfig.setMaxTotal(50);

            //커넥션 풀 생성. 인자로는 위에서 생성한  PoolabeConnectionFactory와 GenericObjectPoolConfig를 사용한다.
            GenericObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnFactory,
                    poolConfig);
            
            //PoolabeConnectionFactory에도 커넥션 풀을 연결
            poolableConnFactory.setPool(connectionPool);
            
            //커넥션 풀을 제공하는 jdbc 드라이버를 등록.
            Class.forName("org.apache.commons.dbcp2.PoolingDriver");
            
 
            PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");
            //위에서 커넥션 풀 드라이버에 생성한 커넥션 풀을 등룍한다. 이름은 cp이다.
            driver.registerPool("cp", connectionPool);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}


2. web.xml에 서블릿 실행 설정
    <servlet>
        <servlet-name>DBCPInit</servlet-name>
        <servlet-class>jdbc.DBCPInit</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>


3. 커넥션 사

String jdbcDriver = "jdbc:apache:commons:dbcp:cp";
...
conn = DriverManager.getConnection(jdbcDriver);

커넥션을 사용할땐 기존 db 주소가 아닌 커넥션 풀의 주소를 사용한다.


'JAVA > JSP,Servlet' 카테고리의 다른 글

JSP 모델1과 모델2, 그리고 MVC 패턴  (2) 2016.02.15


//적용 방법 1

JLayeredPane layered1 = new

JLayeredPane(); jframe.add(layered1);

//적용 방법 2

JLayeredPane layered2 = this.getLayeredPane(); //컴퍼넌트 추가방법중 하나 layered.add(Compnent comp, int index);

 


JLayeredPane는 JFC나 Swing의 컨테이너에 깊이(depth)를 적용하여 컨테이너들을 겹쳐서 사용할 수 있도록 하는 컨테이너 객체이다.


add 메서드의 매개변수중 index의 크기에 따라서 깊이가 달라지는데, 크기가 클수록 더욱 상위에 위치한다.


JLayeredPane 클래스에는 이를 위해 몇가지 static final integer값이 선언되어있다.



 

 DEFAULT_LAYER

 new Integer(0)

 PALETTE_LAYER 

 new Integer(100)

 MODAL_LAYER

 new Integer(200)

 POPUP_LAYER

 new Integer(300)

 DRAG_LAYER

 new Integer(400)


자세한 깊이 정도는 위의 그림 참조.




http://docs.oracle.com/javase/8/docs/api/javax/swing/JLayeredPane.html



Method NameDescription
showConfirmDialogAsks a confirming question, like yes/no/cancel.
showInputDialogPrompt for some input.
showMessageDialogTell the user about something that has happened.
showOptionDialogThe Grand Unification of the above three.

//메세지 다이얼로그

JOptionPane.showMessageDialog(parentComponent, message);

JOptionPane.showMessageDialog(parentComponent, message, title, messageType);

JOptionPane.showMessageDialog(parentComponent, message, title, messageType, icon);


 

JDialog를 이용해서 다이얼로그를 생성할 수 있지만


JOptionPane를 이용하면 제한적인 기능을 가진 다이얼로그를 간단하게 생성 할 수 있다.



JOptionPane.showMessageDialog(null, "ID,비밀번호를  모두 입력해주세요.");





http://docs.oracle.com/javase/6/docs/api/javax/swing/JOptionPane.html




loginButton = new JButton(new ImageIcon("img/btLogin_hud.png")); // 버튼 배경 이미지 설정

loginButton.setBorderPainted(false); // 버튼 테두리 설정

loginButton.setContentAreaFilled(false); // 버튼 영역 배경 표시 설정

loginButton.setFocusPainted(false); // 포커스 표시 설정


loginField.setBorder(javax.swing.BorderFactory.createEmptyBorder());//테두리 없애는 방법 1

 

passwordField = new JPasswordField(15){ //테두리 없애는 방법 2

public void setBorder(Border border){ } };



setBorder 메서드에 비어있는 border객체를 생성해 전달해주거나


setBorder 메서드를 비어둔 상태로 오버라이딩 해주면 된다.


+ Recent posts