달력

11

« 2024/11 »

  • 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
2018. 7. 30. 20:13

스프링부트 Mybatis+H2 연동하기 (JPA 미사용) WEB2018. 7. 30. 20:13

1. 개요

    스프링부트를 사용하여 Mybatis 기본 설정(JPA 사용 X) 
    (h2의 경우 내장 DB로 pom.xml 추가 외 별도 설정 불필요)


2. 프로젝트 구조(이클립스 JAVA EE perspective의 Project Explorer 기준)
    /MyProject
        /src/main/java
            /com.example.demo
                MyProjectApplication.java
            /com.example.demo.controller
                TestController.java
            /com.example.demo.mapper
                TestMapper.java
        /src/main/resource
            /mapper
                TestMapper.xml
            /static
            /templates
            application.properties
            mybatis-config.xml
            data.sql
            schema.sql        
        pom.xml


3. pom.xml 설정
    <?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/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>com.example</groupId>
        <artifactId>MyProject</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>

        <name>MyProject</name>
        <description>Demo project for Spring Boot</description>

        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.0.3.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>

        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>

        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.2</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>com.h2database</groupId>
                <artifactId>h2</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>     

 

4. application.properties 설정
    spring.h2.console.enabled=true
    mybatis.config-location=classpath:mybatis-config.xml
    mybatis.mapper-locations=classpath:mappers/*.xml


5. DB 스키마 / 데이터 작성
    <schema.sql>
        create table student(
           id integer not null,
           name varchar(255) not null,
           passport_number varchar(255) not null,
           primary key(id)
        );
    <data.sql>
        insert into student values(10001,'Ranga', 'E1234567');
        insert into student values(10002,'Ravi', 'A1234568');


6. mybatis-config.xml 설정
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <mappers>
            <mapper resource="mapper/TestMapper.xml"/>
        </mappers>      
    </configuration>


7. TestController.java 작성
    @RestController
    @RequestMapping("/test/*")
    public class Test {

        @Autowired
        TestMapper testMapper;        
       
        @GetMapping("/info")
        public List<Map<String,Object>> test() {            
            return testMapper.test();
        }
    }
    
8. TestMapper.java 작성
    @Mapper
    public interface TestMapper {        
        List<Map<String,Object>> test();
    }    
    
9. TestMapper.xml 작성
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.example.demo.mapper.TestMapper">
        <select id="test" resultType="java.util.Map">
            select * from student
        </select>
    </mapper>


10. 테스트 
    가. 스프링부트 프로젝트 기동    
    나. 브라우저 실행
    다. h2 콘솔 접속(http://localhost:8080/h2-console > JDBC URL 칸에 jdbc:h2:mem:testdb 입력 > Connect 클릭) 후 Student 테이블 유무 확인       
    라. 주소창에 요청 입력 및 리턴 값 확인
        요청 - http://localhost:8080/test/info
        응답 - [{"PASSPORT_NUMBER":"E1234567","ID":10001,"NAME":"Ranga"},{"PASSPORT_NUMBER":"A1234568","ID":10002,"NAME":"Ravi"}]
   

'WEB' 카테고리의 다른 글

WebSocket 기초  (0) 2018.07.13
SSL 작동 원리  (0) 2018.07.04
:
Posted by SK
2018. 7. 13. 20:24

WebSocket 기초 WEB2018. 7. 13. 20:24

(레퍼런스: http://www.oracle.com/technetwork/articles/Java/jsr356-1937161.html)


Java WebSocket(웹소켓) API


1.  웹소켓 정의: 생략


2.  웹소켓 등장배경(소켓, HTTP, Polling, 웹소켓의 차이): 생략


3.  웹소켓 개발 환경(Java EE 7 등): 생략


4.  웹소켓 라이프사이클 이벤트(Java 매서드와 매핑)
    가. 클라이언트가 HTTP 핸드쉐이크 요청을 보내 연결을 시작한다
    나. 서버는 핸드쉐이크 응답을 보낸다
    다. 연결이 구성되고, 이제는 HTTP가 아닌 웹소켓으로 통신한다(서버-클라이언트가 대칭상태)
    라. 두 피어 모두 메시지를 보내고 받는다
    마. 두 피어 중 하나가 연결을 닫는다  


5.  웹소켓 프로그래밍
    가. 어노테이션 방식
        POJO에 @ServerEndpoint 어노테이션을 설정하여 웹소켓 요청을 받는 endpoint로 만든다.
        @ServerEndpoint에는 웹소켓 endpoint의 경로를 넣는다.
        ex) @ServerEndpoint("/test")
            public class TestEndpoint{...}

        위 예제 코드를 보면, "test"라는 상대경로로 endpoint가 지정되는데, 

         애플리케이션이 배포되면 ws://localhost:8080/root/test와 같은 주소로 접근가능하다.
        경로에는 내부 메서드에서 사용할 수 있는 파라미터를 포함할 수 있다. ex) "/test/{userid}"
        
        웹소켓을 시작하는 POJO(클라이언트)는 @ClientEndpoint 어노테이션을 지정해야한다. 

         클라이언트 측에서는 요청을 받지 않기 때문에 @ClientEndpoint에 경로를 넣지 않는다.        
        ex) @ClientEndpoint
            public class TestClientEndpoint{...}

            
        웹소켓 연결은 다음과 같은 코드로 수행되며, 이후 @ServerEndpoint나 @ClientEndpoint가 endpoint로 호출된다.
        ex) javax.websocket.WebSocketContainer container = javax.websocket.ContainerProvider.getWebSocketContainer();
            container.connectToServer(TestClientEndpoint.class, new URI("ws://localhost:8080/mytestserver/endpoint"));

            
        웹소켓 연결이 구성되면, Session(Session 인스턴스는 웹소켓이 닫히기 전까지 유효)이 생성되고 

         @OnOpen 어노테이션이 붙은 endpoint가 호출된다. 
        이 매서드는 다음과 같은 파라미터를 포함할 수 있다.         
        - javax.websocket.Session 파라미터 (생성된 Session)
        - EndpointConfig 인스턴스 (endpoint configuration에 대한 정보를 포함)
        - @PathParam 어노테이션이 붙은 String 파라미터 (0개 이상, endpoint 경로의 파라미터를 참조)
        ex) @OnOpen
            public void testOnOpen (Session session) {
                System.out.println (session.getId());
            }

        
        웹소켓 endpoint가 메시지를 수신하면 @OnMessage 어노테이션이 붙은 매서드가 호출 된다. 

         해당 매서드는 다음과 같은 파라미터를 포함할 수 있다.
        - javax.websocket.Session 파라미터
        - @PathParam 어노테이션이 붙은 String 파라미터 (0개 이상, endpoint 경로의 파라미터를 참조)
        - 메시지 그 자체
        ex) 송신자에게 메시지를 수신만 하는 경우
            @OnMessage
            public void testOnMessage (String txt){
                System.out.println (txt);
            }

        ex) 송신자에게 리턴 값을 주는 경우
            @OnMessage
            public String testOnMessage (String txt){
                return "I got a msg: "+txt;
            }        

        
        웹소켓을 통해 메시지를 보내는 두번째 방법은, 라이프사이클의 callback 매서드(ex @OnOpen 등의)에서 얻을 수 있는 

         Session 오브젝트를 활용하는 방법이다.
        Session 인스턴스의 getBasicRemote() 매서드는 WebSocket의 상대 쪽인 RemoteEndpoint를 리턴한다. 

         RemoteEndpoint 인스턴스는 아래와 같이 메시지를 보내는데 사용할 수 있다.
        ex) RemoteEndpoint.Basic remote = session.getBasicRemote();
            remote.sendText("hi there");

        
        웹소켓 연결이 닫힐 때, @OnClose 어노테이션이 붙은 매서드가 호출된다. 

         해당 매서드는 다음과 같은 파라미터를 포함할 수 있다.
        - javax.websocket.Session 파라미터 (WebSocket이 닫히면 사용 불가. 즉, @OnClose 매서드 리턴 후에는 사용 불가)
        - javax.websocket.CloseReason 파리미터 (웹소켓 종료의 원인이 정상종료인지 프로토콜에러인지 등)
        - @PathParam 어노테이션이 붙은 String 파라미터 (0개 이상, endpoint 경로의 파라미터를 참조)
        ex) @OnClose
            public void testOnClose (CloseReason reason) {
                System.out.println(reason.getReasonPhrase());
            }

        
        만일 에러가 수신되면 @OnError가 붙은 매서드가 호출된다.
        
    나. 인터페이스 방식
        인터페이스 방식은 어노테이션 방식과 다르게 javax.websocket.EndPoint를 상속하고 

         onOpen, onClose, onError를 오버라이드하여 구현한다.
        ex) public class testEndPoint extends javax.websocket.Endpoint{
                public void opOpen(Session session, EndpointConfig config){...}
                public void opClose(Session session, CloseReason reason){...}
                public void opError(Session session, Throwable throw){...}
            }

        
        메시지를 다루기 위해서는 다음과 같이 javax.websocket.MessageHandler를 onOpen 매서드에 등록해야한다.
        ex) public void onOpen (Session session, EndpointConfig config){
                session.addMessageHandler (new MessageHandler(){...});
            }

        
        MessageHandler는 두 개의 하위 인터페이스를 가진 인터페이스다. 

         하나는 MessageHandler.Partial 인터페이스로 메시지의 부분 전송을 알아차리고 싶을때 사용하고
        또 다른 인터페이스인 MessageHandler.Whole은 완전한 메시지의 수신을 알아차리고 싶을 때 사용한다.
        ex) public void onOpen (Session session, EndpointConfig config){
                final RemoteEndpoint.Basic remote = session.getBasicRemote();
                session.addMessageHandler (new MessageHandler.Whole<String>(){
                    public void onMessage (String txt){
                        try{
                            remote.sendString ("this is test msg: "+txt);
                        }catch (IOException e){
                            ...
                        }                        
                    }
                });                
            }


6.  메시지 유형 / 인코더 및 디코더
    가. 메시지 타입
        - 텍스트 기반 메시지
        - 바이너리 메시지
        - 퐁 메시지 (웹소켓 연결 자체에 대한 메시지)
        
    나. 메지시 유형 사용
        1) 어노테이션 방식
            각 메시지 유형마다 하나의 @OnMessage 매서드가 허용된다. 메시지 유형에 따라 허용되는 파라미터가 다르다.
            가) 매서드가 텍스트 메시지를 다루는 경우
                - 전체 메시지를 수신하는 String 
                - 전체 메시지를 수신하는 Java primitive, class
                - 부분 메시지를 수신하는 String, boolean 쌍
                - blocking 시스템에서 전체 메시지 수신하는 Reader
                - 텍스트 디코더(Decoder.Text 및 Decoder.TextStream)를 가지고 있는 endpoint를 위한 모든 object 파라미터
            나) 매서드가 바이너리 메시지를 다루는 경우
                - 전체 메시지를 수신하는 byte[] 또는 ByteBuffer
                - 부분 메시지를 수신하는 byte[], boolean 쌍 또는 ByteBuffer, boolean 쌍
                - blocking 시스템에서 전체 메시지를 수진하는 InputStream
                - 바이너리 디코더(Decoder.Binary 및 Decoder.BinaryStream)를 가지고 있는 endpoint를 위한 모든 object 파라미터
            다) 매서드가 pong 메시지를 다루는 경우
                - pong 메시지 핸들링을 위한 PongMessage
        2) 인터페이스 방식과
            각 세션은 메시지 유형마다 하나의 MessageHandler를 등록할 수 있다.
    
    다. 인코더 및 디코더
        모든 Java 오브젝트는 텍스트 기반 또는 바이너리 메시지로 인코딩될 수 있다. 
        메시지는 다른 피어로 전송되며, Java 오브젝트도 다시 디코딩되거나 웹소켓 라이브러리로 인터프리트될 수 있다.
        XML이나 JSON이 웹소켓 메시지로 사용되기도 하는데 인코딩 및 디코딩을 통해 

         Java 오브젝트를 JSON, XML로 바꾸거나 그 반대를 수행할 수 있다.
        
        인코더는 javax.websocket.Encoder 인터페이스를 구현하여 정의하고, 

         디코더는 javax.websocket.Decoder 인터페스를 구현하여 정의한다.
        endpoint 인스턴스는 가능한 인코더 및 디코더가 무엇인지 알아야한다. 
        어노테이션 방식을 사용하면, @ClientEndpoint와 @ServerEndpoint에 있는 인코더 및 디코더 엘리먼트를 통해 

         인코더 및 디코더 목록이 전달된다.
        아래 코드는 TestJavaObject 인스턴스를 텍스트 메시지로 전환하는 MessageEncoder 클래스를 어떻게 등록하는지 보여준다.
        ex) @ServerEndpoint(value = "/endpoint", encoders = MessageEncoder.class, decoders = Messagedecoder.class)
            public class TestEndpoint {
                ...
            }
            
            class MessageEncoder implements Encoder.Text<TestJavaObject>{
                @Override
                public String encode (TestJavaObject obj) throws EncodingException {
                    ...
                }
            }
          
            class MessageDecoder implements Decoder.Text<TestJavaObject>{
                @Override
                public TestJavaObject decode (String src) throws DecodeException {
                    ...
                }
                
                @Override 
                public boolean willDecode (String src){
                    // 전달 받은 String이 TestJavaObject 인스턴스로 디코딩 되어야 한다면 true 리턴
                }
            }

            
        Encoder 인터페이스는 다음과 같은 하위 인터페이스를 가지고 있다.
        - Encoder.Text (Java 오브젝트를 텍스트 메시지로 변환)
        - Encoder.TextStream (Java 오브젝트를 캐릭터 스트림에 add 함)
        - Encoder.Binary (Java 오브젝트를 바이너리 메시지로 변환)
        - Encoder.BinaryStream (Java 오브젝트를 바이너리 스트림에 add 함)

        Decoder 인터페이스는 다음과 같은 하위 인터페이스를 가지고 있다.
        - Decoder.Text (텍스트 메시지를 Java 오브젝트로 변환)
        - Decoder.TextStream (캐릭터 스트림으로부터 Java 오브젝트를 read 함)
        - Decoder.Binary (바이너리 메시지를 Java 오브젝트로 변환)
        - Decoder.BinaryStream (바이너리 스트림으로부터 Java 오브젝트를 read 함)       

'WEB' 카테고리의 다른 글

스프링부트 Mybatis+H2 연동하기 (JPA 미사용)  (0) 2018.07.30
SSL 작동 원리  (0) 2018.07.04
:
Posted by SK
2018. 7. 8. 11:27

MAVEN 기초 JAVA2018. 7. 8. 11:27

사내에서는 인터넷 차단이 되어있기 때문에 메이븐이나 그래들 같은 건 사용할 수 없다. 

다만, 책 등을 보면서 혼자 뭘 해보려하면 다들 기본으로 깔고 들어가기 때문에 기초정도는 알아둘 필요가 있을 것 같다.



메이븐 프로젝트 시작해보기


메이븐 프로젝트를 생성하는 과정은 다음과 같다

1. 이클립스에서 신규 프로젝트를 만들때 Maven Project를 선택한다

2. 처음 설정 창에서 Create a simple project에 체크해주고 Next 클릭

3. 다음 설정 창에서 Group Id에 com.test , Artifact Id에 testPjt로 적고 Finish 클릭

                    

기본적인 구조는 아래와 같다.

PROJECT/

src/main/java                    <- 일반 프로젝트의 src에 해당하는 곳이다(프로덕션 코드)

src/main/resources            <- 프로덕션 코드에서 사용할 자원들이 위치한다

src/test/java                     <- 테스트 코드

src/test/resources              <- 테스트 코드의 자원

src/ 

main/

webapp/               <- 웹 프로젝트에서 JSP, JS 등의 웹 애플리케이션 컨텐츠가 위치하는 곳에 해당한다 (WEB-INF 등)

target/                             <- 메이븐 빌드 시, 빌드 된 jar 파일 등이 생성된다

pom.xml                           <- 메이븐의 설정파일


위 구조에서 제일 중요한 것은 pom.xml이다. 여기서 필요한 의존성을 설정할 수 있다. 

예를 들어 JUnit을 추가로 사용한다고 하면, 

<dependencies>

<dependency>

<groupId>junit</groupId>

<artifactId>junit</artifactId>

<version>4.12</version>

</dependency>

</dependencies>

위와 같은 코드만 pom.xml에 추가하면된다.(이클립스에서는 pom.xml을 더블클릭하여 오픈하고, 하단 탭에서 pom.xml 선택)  
그러면 사용자 폴더(나의 경우는 C:\Users\user\.m2\repository)를 로컬 레파지토리로 하여 해당 라이브러리를 다운받고 프로젝트에 추가한다.
C:\Users\user\.m2\repository에 가보면 <groupId>\<artifactId>\<version>으로 된 폴더가 생성되어 있고 그 안에 라이브러 관련 파일이 있는 것을 확인할 수 있다. 
필요한 라이브러리는 <dependencies></dependencies> 태그 안에 계속 추가하면 되는데, 추가할 내용은 

https://search.maven.org에 접속하여 원하는 라이브러리 검색후 클릭해보면 dependency information이라는 부분에 무슨 내용을 넣어야하는지 친절하게 나와있다.


그런데 JUnit을 추가시켜보면 이클립스 기준으로 Maven Dependencies에 JUnit의 jar뿐 아니라 hamcrest-core라는 녀석도 추가되어 있는 것을 볼 수 있다.

이 jar는 JUnit을 사용하기 위해서 필요한 라이브러리로 Maven에서 JUnit을 추가할 때 자동으로 추가한 녀석이다. 

이클립스에서 pom.xml을 열어보면, Dependency Hierarchy탭에 각 라이브러리간의 상관관계를 한눈에 확인 할 수 있다.

또 로컬 레파지토리로 이동하여 해당하는 라이브러리 폴더를 뒤져보면 <library-name>.pom 파일이 있다.

이 파일을 메모장으로 열어서 <dependencies></dependencies> 태그 내용을 살펴보면 해당 라이브러리가 종속되어 있는 것이 무엇인지 보인다.

(이를 transitive dependencies 의존성 전이 라고 한다)


만약 프로젝트에서 JUnit의 다른 특정한 버전이 필요하다고 한다면 어떻게 될까?

그 때는 <version></version> 태그 안에 필요한 버전만 적어 넣으면 maven에서 알아서 다운로드하여 프로젝트에 주입시킨다.



'JAVA' 카테고리의 다른 글

Singleton Pattern(싱글톤 패턴)  (0) 2019.02.13
람다식 기본  (0) 2019.02.10
:
Posted by SK
2018. 7. 4. 21:34

SSL 작동 원리 WEB2018. 7. 4. 21:34

○ SSL 매커니즘

보안과 성능상 이유로 아래 두 가지 기법을 혼용하여 사용

- 대칭키

· 동일한 키로 암호화와 복호화를 같이 하는 방식

· 대칭키 유출 시 암호의 내용을 복호화할 수 있기 때문에 암호를 주고받는 사람들 사이에서 대칭키 전달이 어려움 -> 공개키로 해결

- 공개키

· 두 개의 키로 암호화, 복호화를 하는 방식(A키로 암호화 시 B키로 복호화, 그 역도 성립)

-> 두 개의 키를 각각 비공개키, 공개키로 설정하여 비공개키는 자신만 가지고 있고 타인이 공개키로 암호화한 내용을 비공개키로 복호화

-> 비공개키로 암호화 후 공개키와 함께 암호화된 정보 전송하여 데이터가 공개키와 쌍을 이루는 비공개키로 암호화 된 것을 증명(전자서명)

○ SSL 인증서

- SSL 인증서 기능

· 통신 내용이 공격자에게 노출되는 것을 방지

· 클라이언트가 접속한 서버가 신뢰 할 수 있는 서버임을 보장

  (CA(Certificate Authority 또는 Root Certificate)라는 기업들에 의해 수행

  ex) Symantec, Comodo 등)

· SSL 통신에 사용할 공개키를 클라이언트에게 제공

- SSL 인증서 내용

· 서비스의 정보(인증서를 발급한 CA, 서비스의 도메인 등)

· 서버 측 공개키(공개키의 내용, 공개키의 암호화 방법)

 -> CA는 자신의 비공개키를 이용하여 서버가 제출한 인증서를 암호화

○ SSL의 동작

- 신뢰할 수 있는 서비스 증명: 웹브라우저가 서버에 접속 > 서버가 인증서 제공 > 제공된 인증서의 CA가 브라우저에 내장된 CA리스트내에 있는지 확인 > CA의 공개키를 이용해 인증서 복호화 > 복호화가 되면 인증서가 해당 CA의 비공개키에 의해 암호화된 것이므로 신뢰할 수 있는 서비스인 것이 증명

- 데이터 암호화: 네트워크 통신(악수 → 전송 → 세션종료)시 SSL이 데이터를 암호화함(실제 데이터는 대칭키로, 대칭키의 키는 공개키로 암호화)

· 악수(handshake):

1) 클라이언트가 서버에 접속(Client Hello) 및 주고받는 데이터:

 ☞ 클라이언트 측에서 생성한 랜덤 데이터

 ☞ 클라이언트가 지원하는 암호화 방식(클라이언트와 서버가 지원하는 암호화 방식이 달라, 어떤 암호화 방식을 사용할 것인지 협상 필요)

 ☞ 세션 아이디: 추후 악수 과정을 생략하기 위해 사용자 세션을 서버로 전송

2) 서버 측 응답(Server Hello) 및 주고받는 데이터

 ☞ 서버 측에서 생성한 랜덤 데이터

 ☞ 서버가 선택한 클라이언트 암호화 방식

 ☞ 인증서

3) 클라이언트가 내장된 CA리스트 확인 및 해당 CA의 공개키를 통한 복호화 과정을 거쳐 신뢰할 수 있는 서버인지 확인 > 클라이언트가 클라이언트 랜덤 데이터와 서버 랜덤 데이터를 조합하여 대칭키(pre master secret)를 생성 > 서버로부터 받은 인증서에 들어있는 공개키를 이용해서 pre master secret값을 암호화 후 서버로 전송

4) 서버가 전송받은 pre master secret값을 자신의 비공개키로 복호화(서버와 클라이언트 모두 pre master secret을 공유) > 서버가 pre master secret값을 일련의 과정을 거쳐 master secret값으로 생성 > master secret이 session key를 생성 > session key값을 이용하여 클라이언트와 서버간 데이터를 대칭키 방식으로 암호화하여 전송(서버와 클라이언트 모두 session key를 공유)

5) 클라이언트와 서버가 악수단계 종료를 서로에게 알림

· 세션(정보를 주고 받는 단계): 정보를 상대방에게 전송시 session key값을 이용해 대칭키 방식으로 암호화, 상대방은 해당 대칭키를 통해 복호화

* 공개키 방식이 많은 컴퓨터 파워를 사용하기 때문에 많은 접속이 물리는 서버에 큰 부하를 가져오며, 대칭키 전송시 암호화 되지 않는 인터넷을 통해서 전송하는 것은 위험

-> 속도는 느리지만 데이터를 안전하게 주고받을 수 있는 공개키로 대칭키를 암호화하여 실제 데이터 전송시에는 대칭키를 사용

· 세션종료: 데이터 전송이 끝나면 SSL통신이 끝났음을 서로에게 알리고 session key 폐기



□ HTTP vs HTTPS(Hypertext Transfer Protocol Over Secure Socket Layer)

○ 차이점

HTTP의 보안을 강화한 것이 HTTPS로 SSL프로토콜 위에서 돌아가는 프로토콜임. HTTP는 암호화되지 않은 방법으로 데이터를 전송하기 때문에 서버와 클라이언트 간의 메시지를 감청당할 위험이 있음.

○ 모든 웹사이트가 HTTPS를 쓰지 않는 이유

- 보안인증 비용, SSL(or TLS) 키 교환 시 호출시간 소요(웹 서버 부하),

- 불특정 다수에게 공개해도 상관없는 페이지는 http로, 메일이나 로그인 등의 페이지는 https로 하는 것이 효율적

'WEB' 카테고리의 다른 글

스프링부트 Mybatis+H2 연동하기 (JPA 미사용)  (0) 2018.07.30
WebSocket 기초  (0) 2018.07.13
:
Posted by SK
2018. 5. 7. 12:06

Framework7 시작 Android2018. 5. 7. 12:06

안드로이드 앱 개발을 하려다 보니, 네이티브를 배우기 너무 귀찮다. 안그래도 할 것도 많고.

웹개발은 어느정도 지식이 있으니 Phonegap을 이용해서 개발하자 싶었는데, 이것도 은근히 할게 많다.(디자인이라든지...)

관련해서 프레임워크, 부트스트랩 류의 것들이 뭐가 있나 찾아보다가 Framework7라는 녀석을 알게됐다. 

jQuery와 비슷한 문법으로 DOM 이벤트 처리도 가능하고, Ionic이나 다른 것보다 이리저리 다른 것들에 비해서 편해보인다(학습 곡선이 낮아보인다). 

일단 이녀석을 가지고 해보기로 결정.

그런데 튜토리얼이 꽤 부실하고 커뮤니티가 잘 안되어 있어서 걱정도 된다. 

https://framework7.io/ 


'Android' 카테고리의 다른 글

Flutter 페이지 이동(navigation)  (0) 2019.05.18
Flutter sqlite 연동하기  (0) 2019.05.14
Flutter Future 설명  (0) 2019.04.22
:
Posted by SK

한국 경제는 미국 경제 상황에 큰 영향을 받는다. 또한 미국의 경기 악화는 중국 등 BRICs 국가들에게는 더 큰 영향을 미친다. 때문에 미국 경제 불안으로 촉발된 경기 부진을 중국 시장에서 커버한다는 발상은 넌센스다. 

미국 GDP의 70%가 소비지출에 발생하는데, 만일 인플레이션 등으로 소비자 구매력이 떨어지면 가장 먼저 오락/유흥 등 서비스 항목을 줄이며 이는 GDP 항목에서 가장 큰 비중을 차지한다. 그 다음으로는 자동차, 골프채 등의 내구재(구입 후 1년 이상 사용하는 품목) 소비이며, 마지막은 필수소비재(비내구재) 항목이다. 

한국의 경우 자동차나 전자제품 등 미국에 내구재를 수출하는 비중이 크기 때문에 미국의 내구재의 수주 상황에 영향을 받는 것이다. 내구재 수주는 소비심리와 밀접하고 금리에 민감하다(미국의 경우 리스 등의 할부금융이 발달했기 때문). 내구재 수주는 금리 상황을 3 ~ 6개월 시차를 두고 반응하며, 또한 3 ~ 6개월 우리나라 수출기업 실적에 영향을 준다. 따라서 미국 금리 인상시 1년 이내에 한국 기업 수출에 영향을 준다는 소리다. 다만, 감세 등의 효과로 인해서 주식시장의 상황과는 다르게 움직일 때도 있다.

결론적으로 서비스지출의 감소가 주가 하락과 동행할 경우, 주가 조정이 일시적이 아니라 추세의 시작임을 짐작할 수 있다. 한국의 소비자지출 통계가 없어 소비자심리지표를 이용하지만 미국의 경우는 통계지표가 잘 되어 있는 편이다. 대표적으로 미시간 소비자신뢰지수(University of Michigan Consumer Sentiment Survey)를 들 수 있는데, 이는 미래에 대한 전망과 고용상태, 6개월 내의 내구재 구매 계획 등을 포함한다. (참고: http://www.sca.isr.umich.edu/)


'경제_경영_재테크' 카테고리의 다른 글

주식투자를 위한 거시경제지표(한국)  (0) 2017.10.26
:
Posted by SK

주식/펀드를 투자하는 입장에서 여기저기서 정보를 접하면서 정리해둘 필요성을 느껴서 적어둔다.


주식시장 역시 거시경제의 흐름에 따라 맥을 같이 하기 때문에 거시경제지표에 대한 기본적인 이해가 필요하다. 특히 주식시장에 선행하는 지표를 읽고 해석하는 능력이 중요하다.

한국의 경제지표 

   (각 지표는 http://www.index.go.kr/main.do, http://ecos.bok.or.kr/, http://kosis.kr/index/index.jsp 등에서 찾을 수 있다)

   1) 소비자동향지수 

       100을 기준으로 100 보다 높으면 경기를 긍정적으로 평가하는 가구가 많고 100 보다 낮으면 경기를 부정적으로 평가하는 가구가 많다는 뜻이다(2017년 현재 그 비교대상은 1999년 1월부터 2008년 1월까지의 평균치이다). 소비자동향지수는 소비자기대지수와 소비자평가지수를 합성하여 만들어진다고 하는데, 지금은 별도 통계를 보여주는 것 같지 않다(못 찾는 건지...).

       여기서 소비자기대지수는 현재와 비교하여 6개월 후의 경기, 생활형편, 소비지출에 대한 소비자의 기대를 나타낸다. 즉 소비자가 예측하는 미래경기이다. 반면, 소비자평가지수는 6개월 전과 비교한 현재에 대한 평가이다. 

       소비자심리지수라는 것도 있는데 소비자 동향지수 중 관련 경제지표와 연관성이 높은 항목을 골라 합성한 지수라고 한다.

       소비자지수가 중요한 이유는 결국 소비 지출이 기업의 투자와 기업의 재고, 고용 시장에 긍정적인 영향을 주는 선행지표이기 때문이다. 또한 소비감소는 재산상황이 좋지 못하다는 의미이미로 투자자들이 적극적으로 투자에 나서기 힘들다는 측면도 있다. 따라서, 고용지표나 설비투자 감소에 따른 주식시장 침체 우려는 때늦은 걱정이라는 결론이 나온다.

   2) 경기종합지수

       경기종합지수는 종합주가지수(코스피, 코스닥 등)와 동일한 흐름을 보인다. 경기종합지수는 선행(leading)종합지수, 동행(coincident)종합지수, 후행(lagging)종합지수로 이루어지는데 주식시장이 경기에 대한 기대를 선반영한다는 사실을 고려할 때 동행종합지수와 후행종합지수는 주식투자에 큰 의미는 없다. 다만, 주식시장에 불안한 움직임이 있거나 정체기일 때 이것이 실제 경기상황인지 확인하는 용도로 쓰일 수 있다. 

       선행종합지수는 경기동향을 예측하는 지수로 재고순환지표, 구인구직비율, 건설수주액 등 9개 항목으로 구성된다. 다만 구성항목 중 구인구직비율과 기계수주액(=설비투자)은 후행적 지표로 선행적 지표의 민감성을 완화시켜주는 역할을 한다.

       한 가지 유의해야할 점은 경기상황 예측에 있어서 전월/전분기 대비 지표는 의미가 없는 것이 계절별로 주기별로 경기변화가 어느정도는 발생하고 수출입에도 주기성이 있기 때문이다. 때문에 전년대비 지수와 비교해서 보아야하며 이를 확인해보면 종합주가지수와 거의 비슷하게 움직임을 확인할 수 있다.

      (차트를 보면 순환변동치라는 것이 있는데 100을 기준으로 100을 상회하면 추세이상의 성장을 하고 있다는 의미이다. 단, 그 수준보다는 방향성을 중심으로 해석해야한다)

   3) 물가지수

       소비자물가지수, 생활물가지수, 근원물가지수, 생산자물가지수 등으로 나눈다. 

       소비자물가지수는 가계소비지출에서 차지하는 비중이 11만 분의 1인 400여개 품목을 대상으로 하는 지수이다.

       생활물가지수는 구입 빈도와 지출 비중이 높은 150여개 품목을 대상으로 하며 소비자기대지수에 영향을 주는 지수다.

       근원물가지수는 장기적이고 기조적인 물가 변동지수이며, 가격 변동이 큰 농산물이나 외부 충격에 민간함 석유 등은 제외한다. underlying 혹은 core inflation이라고 한다.

       위 세가지 물가지표들은 주가지수에 후행하기 때문에 소비자물가(소비지출)에 영향을 미치는 물가 변동성 예측을 위해서는 생산자 물가를 살펴보아야 한다. 생산자 물가 상승이 곧 소비자 물가 상승으로 이어지기 때문이다. 생산자물가지수는 국내에서 생산하여 국내시장에 출하되는 모든 재화와 서비스 요금, 즉 생산자의 부담 정도의 변동을 측정한다. 다만, 다른 지표에 선행하는 소비자 지출 역시 주가지수와 동행할 뿐이기 때문에 주식시장이 조정/침체 국면일 때 참고자료로써 활용하는 의미 밖에 없다.

       


'경제_경영_재테크' 카테고리의 다른 글

주식투자를 위한 거시경제지표(미국)  (0) 2017.10.28
:
Posted by SK
2017. 10. 24. 00:04

파이썬 기초2 Python2017. 10. 24. 00:04

1. 함수 

   파이썬에서 함수는 아래와 같이 작성한다.

   def do_something(input_value):

       return_value = input_value + 1

       return return_value


2. 모듈

   코드 재사용을 위해서 함수와 변수들을 묶어 모듈화할 수 있다. 예를 들어 my_module.py라는 파일에 다음과 같이 정의한 경우,

   def my_function():

       pass   

   my_var = 'test'    

   if __name__ == "__main__":

      print('main code')


   다른 파일에서 import my_module 이라고 선언함으로써 my_module.my_function, my_module.my_var의 형태로 접근할 수 있다.

   위 예시에서 if문으로 시작하는 부분은, 해당 파일을 import가 아닌 직접  실행할 때만 구동되는 코드이다. 

   파이썬은 Java나 C++처럼 main부가 따로 없기 때문에 위와 같은 형태를 쓰는 것 같다.

  

   모듈을 import 하는 방법이 하나 더 있는데, from my_module import my_function 처럼 특정 기능을 명시하는 것이다.

   이렇게 하면 my_module.my_function()이 아닌 my_function() 그 자체로 호출할 수 있다.

   

3. 클래스

    파이썬에서는 클래스 또한 지원한다. 아래와 같은 형태로 사용하며, __init__은 생성자, __del__은 소멸자이다.

    class MyClass():

        var = 0

        def __init__(self, input_value):

            self.input_value = input_value

            var += 1

        def __del__(self):

            var = 0

     

     클래스를 상속할 때는 다음과 같이 쓴다. 

     단순히 클래스의 인자에 부모 클래스를 넘기기만 하면되며, 부모 클래스의 생성자를 활용할 경우에는

     super.__init__()을 호출해서 사용하면 된다.

     class MyClass(ParentClass):

        def __init__(self):

            super.__init__()

            self.parent_func1('input_value')


     클래스를 활용하려면 인스턴스를 생성해야 한다. c1 = MyClass()와 같이 쓴다.


3. 파일입출력

    파일입출력은 Java보다는 C형태에 좀 더 가깝다. 

    1) 파일입력

        f = open('C:\\Users\\user\\Desktop\\test.txt','rt')

        line_of_file = f.readlines()

        위 코드에서 r은 read의 의미이고 t는 text파일이라는 뜻이다. 경로는 \ 하나가 아닌 \\ 두개를 써야함을 명심하자.

     2) 파일출력

        f = open('C:\\Users\\user\\Desktop\\test.txt','wt')

        f.write('test message')

        f.close()

        파일 출력은 r 대신 w를 쓴다는 점이 다르다. f.write()로 내용을 입력하고 f.close()로 닫아준다.

    


'Python' 카테고리의 다른 글

파이썬 기초1  (0) 2017.10.22
:
Posted by SK
2017. 10. 22. 21:19

파이썬 기초1 Python2017. 10. 22. 21:19

업무를 하면서 문자열 등을 다룰 일이 꽤 생긴다. 쉘 스크립트로 처리하면 가장 이상적이겠지만, 워낙 불편해서 펄을 해볼까 하다 업데이트도 잘 안되는 듯 하고... 파이썬이 적합할 것 같아서 기초적인 공부를 해보기로 했다.


파이썬 패키지를 일일이 설치하기가 귀찮을 것 같아서 배포판을 선택, 그 중에서도 Anaconda로 설치했다.

(다운로드 : https://www.anaconda.com/download/)


C 밑에 바로 설치했는데, C:\Anaconda3\Lib\idlelib <- 이 경로로 가보면 idle.bat 이라는 파일이 있다. 이 것을 실행하면 python shell이 실행되면서 여기에서 간단한 테스트를 해 볼 수 있다.


다음은 파이썬 기초 및 특징

1. { }, ( ) 를 쓰지 않는다

쉘 스크립트나 PL/SQL을 쓰면서도 가장 적응이 안되는 부분인데, JAVA나 Javascript와 다르게 { }, ( )를 쓰지 않는다.

코드의 포함관계는 들여쓰기로 해결한다. 때문에 함부로 들여쓰기를 해서는 안된다. (Syntax error가 발생한다)

또한 if문 for문 에서는 괄호 없이 바로 조건문을 적는다.

2. 기본 데이터 타입

int, float, string 세 가지의 기본적인 데이터 타입이 존재한다.

3. 문자열은 ''와 ""로 표현가능

Javascript와 마찬가지로 문자열은 '' 안이나 "" 안에 넣어서 쓰면 된다.

4. 변수 타입을 정하지 않는다

int, char, float 등 타입을 명시하지 않고 바로 var = 'test_var' <- 이와 같이 변수를 선언하여 사용한다.

5. 기본 자료구조

리스트, 튜플, 딕셔너리라는 파이썬 자체의 기본 자료구조가 있다.

1) 리스트 : 일반적인 그 리스트와 비슷하다. list1 = ['a','b','c']와 같이 선언하며, 요소에 접근하기 위해서는 list1[0]과 같이

[] 안에 인덱스 번호를 주면 된다. 특이하게도 list1[-1]처럼 뒤에서부터 세는 방법도 있는데 이는 튜플에서도 쓸 수 있다.

아래와 같은 주요 메서드가 있다.

(1) append : list1.append('d')의 형태로 사용하며, 리스트 맨 끝에 요소를 추가한다.

(2) insert : list1.insert(2, 'd')의 형태로 사용하며, 지정한 인덱스에 요소를 추가한다.

  2) 튜플 : 조작이 불가능한 배열이라고 해야할 듯 싶다. tu = ('a', 'b', 'c')와 같이 선언하며, 삽입이나 삭제가 되지 않는다.

리스트보다 속도가 빠르다는 장점이 있다. 접근은 리스트와 동일한 방식으로 한다.

3) 딕셔너리 : 맵 자료구조와 같다. dic = {'key1':'value1', 'key2':'value2'}와 같이 선언하며, dic['key1']과 같이 키 값을

인자로 주면 해당하는 값을 꺼낼 수 있다. 아래와 같은 주요 메서드가 있다.

(1) keys : dic.keys()의 형태로 사용하며, 딕셔너리가 가진 키 값들을 반환한다.

(2) values : dic.values()의 형태로 사용하며, 딕셔너리가 가진 밸류 값들을 반환한다.

(3) items : dic.items()의 형태로 사용하며, 키와 밸류의 쌍을 반환한다.

6. 자료구조 다루기

자료구조를 다루는 공통적인 함수 및 방법들이 있다.

1) del : del(list1[0])의 형태로 사용하며 인자로 넣은 요소를 삭제한다.

위에서 언급했듯이 튜플은 선언 이후 데이터 조작이 불가능하기 때문에 del을 사용하면 에러가 발생한다.

(del(tup)의 형태로 변수 자체를 삭제하는 것은 가능하다)

2) len : len(tup)의 형태로 사용하며 인자로 넣은 변수의 요소의 수, 문자열의 길이 등을 반환한다.

3) list : list(dic.keys())의 형태로 사용하며 인자로 넣은 값을 리스트로 변환하여 반환한다.

(list("abcd")와 같이 문자열을 넣으면 ['a','b','c','d']와 같은 형태로 바꾸어 준다)

4) slicing : 리스트 등의 자료구조에서 원하는 범위의 값을 가져올 때 쓰는 방법이다. list1[2:5]와 같은 형태로 사용하는데,

이는 앞의 인덱스의 요소를를 포함하고 뒤의 인덱스의 요소는 포함하지 않는 범위를 선택하게 해준다.

list1[0:], list1[:3]처럼 써서 ~부터 끝까지, 혹은 처음부터 ~까지의 범위를 지정할 수도 있다.

7. 조건문

다음과 같은 형태로 조건문을 사용한다.

1) if 문 : 

if a < 0:

print('OK')

2) if ~ else 문 :

if a < 0 :

print('OK')

else :

print('NOT OK')

3) if ~ else if 문 :

if a == 0 :

print('1')

elif a == 1 :

print('2')

elif a == 2 :

print('3')

8. 반복문

다음과 같은 형태로 반복문을 사용한다.

for var in range(1, 10):

print(var)

위 코드에서 range(1, 10)은 1 이상 10 미만을 반환해준다. range 대신 리스트나 튜플이 올 수도 있고 딕셔너리를 써도 된다.

딕셔너리 자료구조를 쓸 경우에는 아래와 같이 사용한다.

for k, v in dic.items():

print("%s : %s", %(k, v))

위 코드에서 %s로 표현된 부분은 C의 printf처럼 사용하는 것이며, 쉼표(,)뒤에 % 이후 작성한 변수를 읽어들인다.

'Python' 카테고리의 다른 글

파이썬 기초2  (0) 2017.10.24
:
Posted by SK
2017. 8. 5. 17:58

PL/SQL 조건, 반복 제어문 DB2017. 8. 5. 17:58

<조건 제어문>

PL/SQL의 조건제어문에는 크게 IF와 CASE가 있다.

- IF문

IF var1 >10 THEN

do something

ELSIF var1 <= 10 AND var1 > 1 THEN

do something

ELSE

do something

END IF;

IF문은 위와 같이 사용하며, ELSE IF가 아니라 ELSIF인 것에 주의가 필요하다. 또한 AND, OR를 사용한다.

- CASE문

CASE var1 

WHEN var1 > 10 THEN

do something

WHEN var1 <= 10 AND var > 1 THEN

do something

ELSE

NULL;

END CASE;

CASE문은 위와 같이 사용하며, SQL의 CASE문과 유사한 사용법을 보인다. 

조건 분기 시 세부 로직에 NULL을 사용할 수 있는데, 아무것도 하지 않는다는 명시적 표현이다.


<반복 제어문>

반복제어문을 사용하는 방법에는 여러가지가 있는데, 가장 활용도가 높은 것이 FOR LOOP와 WHILE LOOP인 것 같다.

- FOR문

FOR var1 IN 1 .. 10 LOOP

do something

END LOOP;

FOR문의 위와 같이 사용하며 반복의 범위를 Start .. End의 형태로 표현할 수 있다.

- WHILE문

DECLARE

cnt NUMER := 0;

BEGIN

 WHILE var 1 < 10;

do something;

cnt : cnt + 1;

END LOOP;

'DB' 카테고리의 다른 글

Resource Manager  (0) 2019.02.09
파티셔닝  (0) 2019.02.09
PL/SQL 구조와 변수  (0) 2017.08.03
PL/SQL 시작하기  (0) 2017.07.18
해쉬 인덱스  (0) 2017.06.06
:
Posted by SK