스프링 프레임워크의 내장 객체인 CommonsMultipartResolver 를 이용한 파일 업로드 방식이다.


1. pom.xml 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 
    <!-- MultipartHttpServletRequset -->
    <dependencies>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.0.1</version>
        </dependency>
 
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.2</version>
        </dependency>
    </dependencies>
 
</project>
cs

pom.xml 파일에서

ㄱ. commons-io.jar

ㄴ. commons-fileupload.jar

두 가지 .jar를 추가한다.



2. context.xml 설정

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- MultipartResolver -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="100000000"/>
        <property name="maxInMemorySize" value="100000000"/>
    </bean>
 
</beans>
cs

context.xml에서 CommonsMultipartResolver 객체를 추가한다.


CommonsMultipartResolver는 스프링 프레임워크에 내장되어 있는 MultipartResolver 이다.


* maxUploadSize : 한 번에 최대 올릴 수 있는 파일 사이즈

  maxInMemorySize : 해당 경로에 최대로 저장할 수 있는 파일 사이즈



3. form 파일 업로드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<html>
<head>
    <title>title</title>
</head>
<body>
 
    <!-- form enctype="multipart/form-data" 을 꼭 적어줘야 함 -->
    <form class="form-horizontal" method="post" action="<c:url value='/re/add'/>" enctype="multipart/form-data">
        <!-- input type="file" 이라고 꼭 저어줘야 함 -->
        <input type="file" class="form-control1" id="uploadFile" name="uploadFile" style="border:0px solid black;"/>
        
        <button type="submit" class="btn btn-default">등록</button>
        <button type="reset" class="btn btn-default">취소</button>
    </form>
 
</body>
</html>
cs

form enctype="multipart/form-data"라고 꼭 적어줘야 한다. 그렇지 않으면 form이 전송되지 않는다.

마찬가지로 전송할 파일 타입도 file이라고 적어줘야 한다.



4. MultipartResolver 클래스 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.cafe24.smart.util;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Map;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.view.AbstractView;
 
import com.cafe24.smart.approve.domain.Draft;
import com.cafe24.smart.reward.domain.Reward;
 
// @Component > @Service
//              : 스프링 프레임워크가 관리하는 컴포넌트의 일반적 타입 
//              : 개발자가 직접 조작이 가능한 클래스의 경우 해당 어노테이션을 붙임
//              : ( <=> @Bean : 개발자가 조작이 불가능한 외부 라이브러리를 Bean으로 등록시 사용)
@Component
public class UtilFile {
    String fileName = "";
    
//  프로젝트 내 지정된 경로에 파일을 저장하는 메소드
//  DB에는 업로드된 전체 경로명으로만 지정되기 때문에(업로드한 파일 자체는 경로에 저장됨)
//  fileUpload() 메소드에서 전체 경로를 리턴받아 DB에 경로 그대로 저장   
    public String fileUpload(MultipartHttpServletRequest request,
                                        MultipartFile uploadFile, Object obj) {
        String path = "";
        String fileName = "";
        
        OutputStream out = null;
        PrintWriter printWriter = null;
        
        try {
            fileName = uploadFile.getOriginalFilename();
            byte[] bytes = uploadFile.getBytes();
            path = getSaveLocation(request, obj);
            
            System.out.println("UtilFile fileUpload fileName : " + fileName);
            System.out.println("UtilFile fileUpload uploadPath : " + path);
            
            File file = new File(path);
            
//          파일명이 중복으로 존재할 경우
            if (fileName != null && !fileName.equals("")) {
                if (file.exists()) {
//                    파일명 앞에 업로드 시간 초단위로 붙여 파일명 중복을 방지
                    fileName = System.currentTimeMillis() + "_" + fileName;
                    
                    file = new File(path + fileName);
                }
            }
            
            System.out.println("UtilFile fileUpload final fileName : " + fileName);
            System.out.println("UtilFile fileUpload file : " + file);
            
            out = new FileOutputStream(file);
            
            System.out.println("UtilFile fileUpload out : " + out);
            
            out.write(bytes);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (printWriter != null) {
                    printWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        
        return path + fileName;
    }
    
//  업로드 파일 저장 경로 얻는 메소드
//  업로드한 파일의 경로가 도메인 별로 달라야 했기 때문에 도메인의 형을 비교하여 파일 저장 정로를 다르게 지정함
    private String getSaveLocation(MultipartHttpServletRequest request, Object obj) {
        
        String uploadPath = request.getSession().getServletContext().getRealPath("/");
        String attachPath = "resources/files/";
        
//      Reward인 경우
        if (obj instanceof Reward) {
            attachPath += "reward/";
//      Approval인 경우
        } else if(obj instanceof Draft) {
            attachPath += "approval/";
//      Document인 경우            
        } else {
            attachPath += "document/";
        }
        
        System.out.println("UtilFile getSaveLocation path : " + uploadPath + attachPath);
        
        return uploadPath + attachPath;
    }
}
cs

시간이 촉박했기 때문에 파일의 경로를 암호화하는 UUID 객체는 사용하지 않았다.


getSaveLocation() 메소드에서 저장될 경로를 지정할 때 해당 프로젝트의 경로를 변수 uploadPath로 값 복사하였는데

로컬에서는 (본인의 컴퓨터) 에서는 아무리 해당 경로를 찾아봐도 업로드 했던 파일이 나오지 않는다.

그러나 cafe24 같은 서버에 프로젝트를 호스팅 하면 지정 경로로 업로드가 잘 되니 걱정하지 않아도 된다.



5. form에서 보낸 파일 업로드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Controller
public class RewardController {
//  파일을 업로드하는 컨트롤러 클래스 메소드
    @RequestMapping(value = "re/add", method = RequestMethod.POST)
//  인자로 MulfiPartFile 객체, MultipartHttpServletRequest 객체, 업로드 하려는 도메인 클래스를 받는다
    public String reAddProCtrl(@RequestParam("uploadFile") MultipartFile uploadFile,
                                    MultipartHttpServletRequest request, Reward reward) {
        
        System.out.println("RewardController reAddProCtrl uploadFile : " + uploadFile);
        System.out.println("RewardController reAddProCtrl reward : " + reward);
        
//      UtilFile 객체 생성
        UtilFile utilFile = new UtilFile();
        
//      파일 업로드 결과값을 path로 받아온다(이미 fileUpload() 메소드에서 해당 경로에 업로드는 끝났음)
        String uploadPath = utilFile.fileUpload(request, uploadFile, reward);
        
//      해당 경로만 받아 db에 저장
        int n = rewardService.reAddServ(uploadPath, reward);
        
        System.out.println("RewardController reAddProCtrl n : " + n);
        System.out.println("RewardController reAddProCtrl uploadPath : " + uploadPath);
        
        return "redirect:listAll";
    }
}
cs

이로서 업로드가 끝난다.

'BackEnd > Java' 카테고리의 다른 글

LinkedHashMap  (0) 2017.06.29
RSA 암호화 구현  (0) 2017.03.14
가변인수 (Java 5.0 이상)  (0) 2017.02.13
Java :: 열거형 (Enumeration) (Java 5.0 이상)  (0) 2017.02.13
초기화 블록 (Initialization block)  (0) 2017.02.13

호스트 한 개로 여러 프로젝트 올리는 법

 

1. .war 파일 업로드

tomcat > webapps > 에 해당 프로젝트를 .war 파일로 export 하여 업로드 한다.

 

 

2. putty 실행

putty를 다운로드 하고 해당 계정을 적은 뒤 Open 버튼을 누른다.

 

 

로그인을 한 뒤, cmd 창에

 

 tomcat/bin/shutdown.sh

명령어를 입력하여 톰캣을 중지시킨 뒤

 

 tomcat/bin/startup.sh

명령어를 입력하여 톰캣을 재부팅 시킨다.

 

 

3. ftp tool 새로고침

ftp 툴을 새로고침 하면 .war 파일명과 똑같은 이름으로 프로젝트가 컴파일된다.

 

 

4. 주소 입력

 계정.cafe24.com/Book

이라고 입력하면 해당 프로젝트 경로로 되어있는 파일들이 실행될 것이다.

1. 정의

필요에 따라 인자(매개변수) 갯수를 가변적으로 조정할 수 있는 기술.

가변인수가 없던 때에는 Collection이나 Array를 이용하여 가변인수를 대체하여 사용했었다.



2. 원리
인자로 ...이라는 표시를 해두면 컴파일러가 배열 형식으로 바꿔 인식한다.

그리고 인자로 주어지는 가변인수들을 모아 배열 객체로 만들어 처리한다.


1
2
3
4
5
// 원본
public static void display (String... str) {
 
// 컴파일러 변환 
public static void display (String as[]) {
cs



3. 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.Vector;
 
public class VarArgs {
    public static void display (Vector v) {
        for (Object s : v) {
            System.out.println("컬렉션 형태 : " + s);
        }
    }
    
//  가변인수를 받는 메소드
    public static void display (String... str) {
        for (String s : str) {
            System.out.println("가변 배열 형태 : " + s);
        }
    }
}
 
import java.util.Vector;
 
public class VarArgsMain {
    public static void main(String[] args) {
        VarArgs varArgs = new VarArgs();
        Vector vector = new Vector();
        
        vector.add("Hello");
        vector.add("World");
        vector.add("Korea");
        
        varArgs.display(vector);
//      인자로 여러 개를 입력
        varArgs.display("Hello""World""Korea");
    }
}
cs


'BackEnd > Java' 카테고리의 다른 글

RSA 암호화 구현  (0) 2017.03.14
Java :: Spring 파일 업로드 (multipart-form/data)  (2) 2017.03.14
Java :: 열거형 (Enumeration) (Java 5.0 이상)  (0) 2017.02.13
초기화 블록 (Initialization block)  (0) 2017.02.13
AWT vs 스윙 (Swing)  (0) 2017.02.10

1. 정의

final과 같이 자바에서 상수값을 만드는 방법 중 하나이다.


enum은 관련 있는 상수들의 집합이며, 해당 클래스가 상수만으로 작성되어 있을 경우 반드시 class로 선언할 필요 없이 enum으로 선언하면 된다.


일반적인 데이터 타입의 경우 변수를 만든 뒤 형에 맞는 아무 값이나 넣을 수 있으나, 열거형 타입으로 변수를 선언하는 것은 일반 데이터 타입과는 동일하지만 열거형을 선언할 때 명시한 값을 넣을 수 있다.


열거형을 사용하는 가장 큰 이유는 숫자 상수를 사용하는 것보다 열거형 상수를 사용하는 것이 훨씬 직관적이기 때문이다.

열거형은 상수를 묶어서 관리할 수 있다는 큰 장점도 가지고 있고 상수는 상수 자체가 형이 아니기 때문에 형 안정성을 보장할 수 없었으나 자바 5.0 이후로는 열거형을 통해 상수의 형 안정성을 보장하고 있다.



2. 특징

순번

특징

 1

 코드가 단순하고, 가독성이 높음

 2

 인스턴스를 생성할 수 있고 상속을 방지할 수 있음

 3

 enum이라는 키워드를 사용하기 때문에 의도가 분명하게 나타남



3. 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import java.util.HashMap;
import java.util.Map;
 
public enum Sample {
    PASSED(1"Passed""The test has passed."),
    FAILED(-1"Failed""The test was executed but failed."),
    DID_NOT_RUN(0"Did not run""The test did not start.");
    
//  변수, Map 생성
    int code;
    String label;
    String description;
    static Map<Integer, Sample> map;
    
//  생성자 메소드로 변수들 초기화
    private Sample (int code, String label, String description) {
        this.code = code;
        this.label = label;
        this.description = description;
        
        System.out.println("console> code : " + code);
        System.out.println("console> label : " + label);
        System.out.println("console> description : " + description);
    }
    
//  정수를 넣으면 해당하는 상수 값을 Sample 클래스에 담아 리턴하는 메소드
    public static Sample getStatus(int i) {
//      main 메소드에서 getStatus() 호출하는 경우 Map에 들어있는게 없기 때문에
//      initMapping() 메소드를 무조건 호출하게 됨
        if (map == null) {
            initMapping();
        }
        
        System.out.println("console> getStatus get(i)) : " + map.get(i));
        
        return map.get(i);
    }
    
    private static void initMapping() {
        map = new HashMap<Integer, Sample>();
        
//      Sample 클래스에 선언되어 있는 상수들을 모두 돌림
        for (Sample sample : values()) {
            map.put(sample.code, sample);
            
            System.out.println("console> map.get = " + sample);
        }
    }
    
    public int getCode() {
        return code;
    }
    
    public String getLabel() {
        return label;
    }
    
    public String getDescription() {
        return description;
    }
    
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder();
        
        sb.append("Status");
        sb.append("{code = ").append(code);
        sb.append(", label = '").append(label).append('\'');
        sb.append(", description = '").append(description).append('\'');
        sb.append('}');
        
        return sb.toString();
    }
    
    public static void main(String[] args) {
        System.out.println(Sample.PASSED);
        System.out.println(Sample.getStatus(-1));
    }
}
cs


1. 정의

클래스의 초기화와 관련된 작업을 수행하고, 생성자보다 먼저 호출되며 클래스 초기화 블록과 인스턴스 초기화 블록으로 구분된다.

 

 

2. 분류

분류 

설명 

 클래스 초기화 블록

 클래스 파일이 JVM에 로드 되는 시점에 실행됨

 인스턴스 초기화 블록

 클래스의 인스턴스가 생성되고, 생성자가 호출되기 전에 실행됨

 

 

3. 예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class Hello {
    
    //class initialization block
    static {
        System.out.println("클래스 초기화 블록");
    }
    
    //instance initialization block
    {
        System.out.println("인스턴스 초기화 블록");
    }
    
    //default constructor
    Hello () {
        System.out.println("디폴트 생성자");
    }
    
    Hello (int value) {
        System.out.println("생성자 오버로딩");
    }
}
 
public class HelloMain {
    final static boolean LOG_ENABLE = false;
    
    public static void main(String[] args) {
        Hello hello = new Hello();
        Hello hello2 = new Hello(0);
    }
}
cs

 

 


'BackEnd > Java' 카테고리의 다른 글

가변인수 (Java 5.0 이상)  (0) 2017.02.13
Java :: 열거형 (Enumeration) (Java 5.0 이상)  (0) 2017.02.13
AWT vs 스윙 (Swing)  (0) 2017.02.10
람다식과 함수형 프로그래밍 (Java 8.0 이상)  (0) 2017.02.09
자바 기본 정리  (0) 2017.02.09

자바에서 사용 가능한 GUI (Graphic User Interface) 객체의 종류로는 두 가지를 꼽을 수 있는데, AWT와 스윙이다.

GUI는 입출력과 결과값 리턴을 Command 창에서만 할 수 있었으나 하나의 윈도우 창을 띄운 뒤 버튼과 라벨 등으로 꾸밀 수 있는 것을 말한다.

 

 

1. AWT (Abstract Window Toolkit)

해당 시스템에서 실행될 시 해당 컴포넌트를 사용하는 GUI이다.

자바 시스템에서 실행된다고 할 경우에는 자바 컴포넌트를 사용하기 때문에 여러 컴포넌트에서 AWT를 사용한다고 할 경우

실행하는 컴포넌트의 모습이 서로 달라 일관된 화면을 제공하는 데에 어려움이 따른다. 자바 초기 버전에 제공되던 GUI이다.

 

 

2. 스윙 (Swing)

자바에서 컴포넌트를 작성시 화면이 일관되게 나오는 GUI이다.

AWT로 GUI를 사용했던 시절에는 버튼의 롤오버나 풍선말 등을 AWT로 구현하지 못했기 때문에

가장 큰 단계의 컨테이너만을 운영체제(AWT) 로 지원하고, 그 하부의 컴포넌트들은 직접 자바 코드로 그렸었다.

그러한 불편함을 해소하기 위해 등장한 GUI가 스윙이며, 스윙은 운영체제가 대신 해주던 일을

JVM (Java Virtual Machine)이 대신 해줘야 하기 때문에 AWT와는 확연히 다른 구조를 가지며 주로 GUI 구성에서 많이 사용된다.

화면이 일관적이기 때문에 현재는 스윙 사용을 권장하는 편이다.

 

스윙의 컴포넌트는 대부분이 javax.swing.JComponent 클래스로부터의 상속을 받아 구현한다.

(AWT와 구분을 하기 위해 클래스명 맨 앞에 J~가 붙음)

 

* Container > JComponent > Swing


* Swing 특징

순번

 특징

 1

 더블 버퍼링 지원

 2

 각 컴포넌트의 속성값 설정 가능

 3

 컴포턴트에 투명 효과를 줄 수 있음

 4

 Tool tip / border 지원

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.awt.Color;
 
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
 
//JFrame을 상속받는 Pizza 클래스
public class Pizza extends JFrame {
    
//  Constructor method
    public Pizza() {
//      frame size settting
        setSize(500150);
//      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); : 메인 프레임 닫을 때,
//                                                프로그램 또한 안정적으로 종료됨
//                                                지정하지 않을 시 메인프로그램은 닫혀도
//                                                JFrame 객체는 JVM에서 계속 살아 있음
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//      frame title setting
        setTitle("Frame Test");
        
//      panel 객체 생성
        JPanel panel = new JPanel();
        JPanel panel1 = new JPanel();
        JPanel panel2 = new JPanel();
        
//      panel 색상 설정
        panel.setBackground(Color.BLUE);
        panel1.setBackground(Color.CYAN);
        panel2.setBackground(Color.GREEN);
        
//      라벨 객체 생성, panel1에 라벨 추가
        JLabel label = new JLabel("피자 종류를 선택하세요.");
        
        panel1.add(label);
        
//      버튼 객체 생성
        JButton button1 = new JButton("치즈");
        JButton button2 = new JButton("불고기");
        JButton button3 = new JButton("포테이토");
        
//      panel2에 button1, 2, 3 추가
        panel2.add(button1);
        panel2.add(button2);
        panel2.add(button3);
        
//      panel에 panel1, panel2 추가
        panel.add(panel1);
        panel.add(panel2);
        
//      프레임에 panel 추가
        add(panel);
        
        setVisible(true);
    }
}
 
 
public class PizzaMain {
    public static void main(String[] args) {
        Pizza pizza = new Pizza();
    }
}
cs

 

 

 

3. AWT vs 스윙 비교

 특징

AWT 

Swing 

 무게

 중량 컴포넌트

 (컴포넌트를 운영체제의 GUI와 연결시키므로,

운영체제에 따라 다른 모양과 배치를 띔)

 경량 컴포넌트

 (직접 컴포넌트를 만들어 구현함)

 패키지

 java.awt.*;

javax.swing.*;

 장점

 각 운영체제에서의 구현이 쉬움

 운영체제간 버그를 자동적으로 해결함


이클립스와 아톰에서 Git을 push하는 것이 여간 번거로워 git을 더 편하게 사용하기 위한 툴인 소스트리를 설치해봤다.

소스트리는 Atlassian사에서 제공하는 프로그램이며, 맥에서만 지원을 해주다가 얼마 전부터 윈도우용 베타 배포를 시작하였다.

소스트리는 윈도우7 이상에서만 사용할 수 있기 때문에 유의해야 한다.



1. 홈페이지 접속


홈페이지 https://www.sourcetreeapp.com/ 주소로 접속하여 자신이 사용하고 있는 OS에 맞게 exe 파일을 설치한다.



2. exe 파일 실행

다운로드 받은 exe 파일을 실행한다.

Atlassian 계정이 없는 상태였기 때문에 Go to My Atlassian 버튼을 누르고, 홈페이지로 들어가  계정을 생성하였다.


계정을 생성한 후 왼쪽 버튼을 눌러 계정에 접속한다.


다음과 같은 창이 추가로 뜨면 계정을 입력하면 된다.


접속에 성공하면 다음과 같은 화면으로 전환된다.


소스트리와 연결할 사이트를 맞게 클릭하고, 인증 부분을 Basic으로 고른 후 사용자명과 비밀번호를 입력하고 계속 버튼을 누른다.



초기 저장소를 지정할 생각이 없어 설정을 건너 뛰었다.

1. 람다식 (Java Lambda Expression)

함수를 변수처럼 사용하는 것.

파라미터로 함수를 다른 메소드의 인자로 전달할 수 있고, 리턴 값으로 함수를 받을 수도 있다.

객체지향 언어인 자바에 함수형 프로그래밍의 개념을 대입하기 위한 인터페이스.

 

자바 람다식은 함수형에 대해 새로 정의한게 아닌, 기존에 존재하는 인터페이스의 형태를 받아 람다식을 표현하기 때문에 함수형 프로그래밍의 장점을 완전히 가지지는 못하고 있다.

 

순번 

장점 

단점 

 1

 코드가 간결해짐

 람다식 호출을 위해 직접 메소드를 불러야 함

 - 타 함수의 파라미터로 전달할 때에는 문제가 없으나, 람다식을 실행할 때에는 인터페이스에 선언된 메소드를 호출해야 함

 2

 병렬 프로그래밍이 가능해짐

 - 반복 대상을 사용자 코드에서 직접 지정하기 않기 때문에 Collection API가 크게 효과적으로 개선됨

 재귀 람다식의 호출이 까다로움

 - 람다식 안에서는 람다식을 가리키는 변수를 참조할 수 없기 때문에 람다식 안에서 자신을 다시 호출하기가 까다로움.

 (배열 등의 트릭을 사용하여 가능하게 할 수는 있음)

 3

 메소드로 행동 방식을 전달 가능

 - 행동 방식 그 자체를 람다식으로 구현하여 전달함

 클로저가 지원되지 않음

 - 자바에서는 외부 변수에 대해 사실상 final 형태로서만 참조가 가능

 (일반적 함수형 프로그램에서는 클로져 형태로 외부 변수의 라이프 사이클 연장 가능)

 4

 의도의 명확성

 - 코드에서 드러내고자 하는 개발자의 의도를 함축적이면서도 추상화시켜 나타낼 수 있음

 함수 외부의 값을 변경함

 - 자바는 기본적으로 객체 모델로서, 함수 안의 값이 타 객체의 영향을 받는 경우 같은 입력 값에 대해 다른 출력 값을 출력할 수 있어 병렬형 프로그래밍에 불리한 방식을 보임

 

<예제1>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class RamdaMain {
    public static void main(String[] args) {
        
//      기존 익명 클래스 방식
        new Thread(new Runnable() {
            public void run() {
                System.out.println("Annoymous Thread");
            }
        }).start();
        
//      람다 표현식 방식
//      () : 파라미터. run()이라는 익명 클래스의 메소드가 아무런 파라미터도 취하지 않는다는 의미
//      -> : 람다식 시작 전에 나타나는 람다식 시작 토큰
//           뒤에는 한 줄짜리 람다식, 혹은 { } 안에 포함된 여러 람다식이 올 수 있음
//      System.~ : 람다식의 내용 부분. 안에는 () 안의 파라미터 값이 사용될 수 있음
        new Thread(()->System.out.println("Lambda Thread")).start();
    }
}
cs

 

<예제2>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//@FunctionalInterface : 인터페이스 형태를 이용하여 람다 클래스임을 선언할 수 있기 때문에
//                         해당 주석을 달아 람다 인터페이스임을 선언함.
// 람다식은 그 자체를 입력 값으로 사용할 수 있지만,
// 받아서 실제로 런타임 시 사용할 때에는 반드시 인터페이스의 형태를 거쳐야 함
@FunctionalInterface
public interface Test {
    public abstract void run();
}
 
public class TestMain {
    public static Test lambdaTest(Test test) {
        test.run();
        return () -> System.out.println("return lambda");
    }
    
    public static void main(String[] args) {
        lambdaTest(() -> System.out.println("input lambda")).run();
    }
}
cs

 

 

2. 함수형 프로그래밍 (<=> 명령형 프로그래밍)

자바는 객체 지향적인 언어이기 때문에(객체지향 : 각각 독립적일 수 있는 것) 그간 익명 함수(일회성 함수)를 사용하지 못했었는데,

Java8 이상부터 람다 표현식이 사용 가능해짐에 따라 함수를 변수처럼 사용할 수 있는 함수형 프로그래밍을 자바에서도 사용 가능할 수 있게 되었다.

 

보통 함수형 프로그래밍의 대표적인 언어라고 하면 자바스크립트를 들 수 있다.

 

함수형 프로그래밍이 도입된 이후로 자바에서도 절차 지향적인 부분을 조금이라도 구현 가능할 수 있게 되었다.

(일회성으로 순서대로 사용하고 말아버리고, 독립된 객체가 아니기 때문에 절차 지향이라고 표현하였음)

 

람다 표현식은 익명 함수를 만들 때 사용하지만, 자바 언어에서는 함수라는 개념이 존재하지 않기 때문에

추상 메소드만 있는 형태의 인터페이스를 만들어 이 인터페이스의 익명 클래스를 만들면서 메소드 오버라이딩에 람다식을 이용하는 인터페이스를 제공한다.

=> 함수형 인터페이스 ( <예제2> 참고)

'BackEnd > Java' 카테고리의 다른 글

초기화 블록 (Initialization block)  (0) 2017.02.13
AWT vs 스윙 (Swing)  (0) 2017.02.10
자바 기본 정리  (0) 2017.02.09
Java :: startsWith() vs indexOf() vs charAt()  (0) 2016.12.26
Java :: Reflection 리플렉션  (0) 2016.12.18

1. 클래스

객체를 정의해 놓은 것. 객체를 생성하는데 사용한다.

실제로 존재하는 사물인 객체를 프로토타입으로 명세화 시킨 것이 클래스이다.

 

* 구성 요소

ㄱ. 클래스 헤더  : 클래스명

클래스 선언부. class라는 예약어를 중심으로 오른쪽은 클래스명이고, 왼쪽은 접근 제한자와

클래스의 형태, 클래스의 종류를 나타냄.

ㄴ. 멤버 필드 : 변수, 상수 등의 속성

객체가 만들어질 때 해당 객체의 특징적 속성을 담게 됨.

ㄷ. 멤버 메소드 : 동작하는 메소드

메소드는 특정한 기능을 수행하는 행위를 의미함

 

 

2. 객체

실제로 존재하는 사물, 또는 실제로 존재하는 개념 등.

속성과 기능의 집합. 이 두 개를 객체의 멤버라고 부른다.

속성과 기능에 따라 용도는 천차만별로 달라질 수 있고, 정의된 클래스로 객체를 생성할 수 있다.

 

 

3. 인스턴스

객체 > 인스턴스.

클래스로부터 인스턴스를 생성하여 인스턴스화 시킨다고 말할 수 있다.

클래스 -> 인스턴스화 -> 인스턴스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//Human 클래스
public class Human {
//  변수 선언
    String name;
    String gender;
    int age;
    
    public Human() { }
    
    public Human(String name) {
        this.name = name;
    }
    
    public Human(String name, String gender, int age) {
        this.name = name;
        this.gender = gender;
        this.age = age;
    }
    
    public void eat(String some) {
        System.out.println("console> age : " + age +
                    ", name : " + name + ", some : " + some + "을 먹는 중.");
    }
    
    public void sleep() {
        System.out.println("console> age : " + age +
                    ", name : " + name + "이가 자는 중.");
    }
}
 
//HumanMain 클래스
public class HumanMain {
    public static void main(String[] args) {
//      Human이라는 클래스 주소를 human이라는 이름의 인스턴스에 주소값을 복사하여 객체화함
        Human human = new Human();
        
        human.name = "사람1";
        human.gender = "여";
        human.age = 100;
        
        human.eat("과자");
        human.sleep();
        
        Human human1 = new Human("사람2""남"99);
        Human human2 = new Human("사람3");
        
        human1.eat("껌");
        human2.eat("커피");
    }
}
cs


MongoDB를 다루기 위하여 구글에 여러 관련 툴을 검색해 보았고 그 중 Robomongo를 많이 사용하는 것 같아 나도 Robomongo를 사용하기로 하였다.



1. 다운로드


https://robomongo.org/download

홈페이지에 접속하여 각자의 OS에 맞게 선택하여 다운로드 한다.



2. 파일 실행








3. DB 생성

생성되어 있는 DB가 없기 때문에 데이터를 저장할 DB를 생성한다.


DB명만 입력하고 Test 버튼을 누른다.


해당 문구가 나오면 연결에 성공한 것이다.

(MongoDB 연결이 되어 있어야 한다.)


만든 DB를 클릭하고 Connect 버튼을 클릭한다.



4. Collection 생성

컬렉션은 sql 용어로 변환하여 생각해보면 테이블 개념과 유사하다.



local > Collection > Create Collection



생성할 컬렉션명을 입력하고 Create 클릭.


+ Recent posts