HTTP 상태 코드

  • 상태 코드는 서버로부터 리퀘스트 결과를 전달
  • 200 OK와 같이 3자리 숫자와 설명으로 나타남
    • 첫 째 자리는 리스폰스의 클래스를 의미
    • 나머지 2자리는 딱히 분류가 없음

2xx 성공

2xx 리스폰스는 리퀘스트가 정상으로 처리되었음을 나타냄

  • 200 OK: 클라이언트가 보낸 리퀘스트를 서버가 정상적으로 처리하였음
    • 상태 코드와 함께 되돌아 오는 정보는 메소드에 따라 다름
    • GET의 경우, 리퀘스트 리소스에 대응하는 엔티티
    • HEAD의 경우, 리퀘스트 리소스에 대응하는 헤더 필드
  • 204 No Content: 리퀘스트는 성공했지만 리소스는 돌려주지 않음
  • 206 Partial Content: Range에 의해 범위가 지정된 리퀘스트에 의해 서버가 부분적 GET 리퀘스트를 받음

3xx 리다이렉트

3xx 리스폰스는 리퀘스트가 정상적으로 처리를 종료하기 위해 브라우저 측에서 특별한 처리를 수행해야 함을 의미

  • 301 Moved Permanently: 리퀘스트된 리소스에 새로운 URI 부여되어, 이후로는 바뀐 URI를 사용해야 한다고 알림
    • 따라서 북마크가 설정되어 있는 경우, URI 변경을 할 것을 권함
  • 302 Found: 리소스 URI가 일시적으로 다른 곳에 이동되어 있음을 알림
    • 영구적으로 이동한 것은 아니기 때문에 북마크 변경을 권하지 않음
  • 303 See Other: 리소스 URI가 다른 곳에 있다는 것을 알림 + GET 메소드의 사용을 권함
    • 302 Found와 같은 기능이지만, GET 메소드의 사용을 권하기 때문에 303을 사용하는 것이 바람직함
    • 301, 302, 303 리스폰스 코드 수신 시 브라우저는 POST를 GET으로 바꾸어 리퀘스트를 자동으로 재송신
      • 301, 302에서는 POST를 GET으로 바꾸는 것을 금지하지만, 실상에서는 변경하는 것이 대부분
  • 304 Not Modified: 클라이언트가 조건부 리퀘스트를 했을 때 리소스에 대한 접근은 허락하지만, 조건이 만족되지 않았음을 알림
  • 307 Temporary Redirect: 302 Found와 같은 기능 수행

4xx 클라이언트 에러

4xx 리스폰스는 클라이언트의 원인으로 에러가 발생했음을 나타냄

  • 400 Bad Request: 리퀘스트 구문이 잘못되었음을 나타냄
    • 브라우저는 해당 상태 코드를 200 OK와 같이 취급
  • 401 Unauthorized: 리퀘스트에 HTTP 인증 정보가 필요하다는 것을 알림
    • 브라우저에서 처음 401 리스폰스를 받은 경우에는 인증을 위한 다이얼로그가 표시됨
  • 403 Forbidden: 리퀘스트된 리소스의 액세스가 거부되었음을 알림
    • 이유를 명확히 하는 경우에는 Entity Body에 기재해서 유저 측에 표시
  • 404 Not Found: 리퀘스트한 리소스가 서버 상에 없다는 것을 나타냄

5xx 서버 에러

5xx 리스폰스는 서버 원인으로 에러가 발생하고 있음을 나타냄

  • 500 Internal Server Error: 서버에서 리퀘스트를 처리하는 도중에 에러가 발생했음을 알림
  • 503 Service Unavaliable: 일시적으로 서버가 과부하 상태이거나 점검중이기 때문에 리퀘스트 처리가 불가함을 알림
    • 상태가 해소되기까지 걸리는 시간을 Retry-After 헤더 필드에 전달하는 것이 좋음

'Software Convergence > Network' 카테고리의 다른 글

Network Layer (2)  (0) 2018.10.08
Network Layer (1)  (0) 2018.10.07
Transport Layer  (0) 2018.10.07
OSI 7 Layers Overview  (0) 2018.10.01
Application Layer  (0) 2018.09.30

클래스 Object와 Wrapper 클래스

Object class

  • 클래스 Object는 Java에서 모든 클래스의 superclass
  • Java의 모든 클래스는 이미 equals와 toString 메서드 등을 가지고 있음
  • class Object의 member method
    • equlas, toString, getClass, hashCode()
  • toString method는 사용자가 원하는 결과를 출력하도록 Override를 해주어야 함
  • Object 클래스의 equals 메서드의 매개변수는 Object 타입
    • 매개변수로 제공된 객체와 자기 자신의 동일성을 검사
      • 값을 비교하는 것이 아님
    • 따라서 원하는 값의 비교를 해주기 위해서는 역시 Override 해주어야 함

Wrapper class

  • Java에서 primitive type 데이터와 non-primitive type 데이터(객체)는 근본적으로 다르게 처리됨
  • 때로 primitive type 데이터를 객체로 만들어야 할 경우가 있음
    • 이럴 때, Integer, Double, Character 등의 Wrapper class를 이용
int a = 20;
Integer age = new Integer(a);
int b = age.intValue();  // b becomes 20

// 데이터 간 형변환
String str = "1234";
int d = Integer.parseInt(str);  // d becomes 1234
  • Autoboxing과 Unboxing
Object[] theArray = new Object[100];
theArray[0] = 10; // 컴파일러가 자동으로 10을 Integer 객체로 변환해줌(autoboxing)
int a = (Integer)theArray[0]; // theArray[0]에 저장된 걱은 Integer 객체이지만 컴파일러가 자동으로 정수로 변환(unboxing)


'Software Convergence > Java' 카테고리의 다른 글

다형성: Polymorphism  (0) 2018.11.05
static과 접근제한자  (0) 2018.10.19
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04

스프링 부트 원리 (2)

자동 설정 구현

  • 보통 configure와 starter는 패키지를 나누어서 만듦
    • xxx-spring-boot-autoconfigure 모듈: 자동 설정
    • xxx-spring-boot-starter 모듈: 필요 의존성 정의
  • 그러나, 그냥 하나로 만들고자 할 때는 xxx-spring-boot-starter에 함께 집어 넣음
  • 구현 방법
  1. 의존성 추가
<dependencies>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure</artifactId>
  </dependency>
  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-autoconfigure-processor</artifactId>
      <optional>true</optional>
  </dependency>
</dependencies>
     
<dependencyManagement>
  <dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-dependencies</artifactId>
          <version>2.0.3.RELEASE</version>
          <type>pom</type>
          <scope>import</scope>
      </dependency>
  </dependencies>
</dependencyManagement>
  1. @Configuration 파일 작성
  2. src/main/resource/META-INF 폴더에 spring.factories 파일 만들기
  3. spring.factories 안에 자동 설정 파일 추가
    #groupID + Configuration 파일명
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.devfon.HolomanConfiguration
  1. mvn install
  • 다른 maven project에서도 사용이 가능해지도록 local maven 저장소에 jar 파일 설치하게 됨
  • 다른 프로젝트에서는 아래와 같이 다른 프로젝트에서 의존성 추가하여 사용
<dependency>
    <groupId>com.devfon</groupId>
    <artifactId>devfon-spring-boot-starter</artifactId>
    <version>1.0-SNAP</version>
</dependency>
  • 아래와 같이 의존성이 추가된 것을 확인할 수 있음

  • but, 한 가지 문제가 발생!
    • Component Scan으로 새로운 Bean을 등록한다 하더라도, 이후에 AutoConfiguration의 Bean을 다시 등록하기 때문에 AutoConfiguration의 Bean이 이전 Bean을 무조건 덮어쓰는 문제
    • 이를 해결하기 위해서는 @ComponentScan으로 읽힌 Bean들이 항상 우선 시 되어야 함
    • 해결 방법: @ConditionalOnMissingBean
      • AutoConfiguration에서 설정한 Bean에 @ConditionalOnMissingBean 애노테이션을 달아줌
  • 위 해결 방안을 통해 기정의된 convention이 아닌 내가 정의한 Bean의 사용이 가능해짐! -> "Customizing"
  • 더 나아가...
    • 다른 프로젝트에서 해당 Bean을 사용할 때, 매 번 Bean을 등록해주기가 번거롭다.
    • 다른 편리한 방법이 없을까?
    • ConfigurationProperties의 사용!
  1. jar 파일로 만들고자 하는 프로젝트에 ConfigurationProperties 파일 추가
@ConfigurationProperties("holoman")
public class HolomanProperties {

    private String name;
    private int howLong;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getHowLong() {
        return howLong;
    }

    public void setHowLong(int howLong) {
        this.howLong = howLong;
    }
}
  1. Configuration 파일에 EnableConfigurationProperties 옵션 추가
@Configuration
@EnableConfigurationProperties(HolomanProperties.class)
public class HolomanConfiguration {
    @Bean
    @ConditionalOnMissingBean
    public Holoman holoman(HolomanProperties properties){
        Holoman holoman = new Holoman();
        // properties 파일로부터 값을 읽어와 생성하는 방식!
        holoman.setHowLong(properties.getHowLong());
        holoman.setName(properties.getName());

        return holoman;
    }
}
  1. jar 파일 사용하는 프로젝트의 application.properties에서 설정값 적용
holoman.name = sang
holoman.howLong = 365


스프링 부트 원리 (1)

의존성 관리 이해

  • spring-boot-dependencies -> spring-boot-starter-parent -> 내 프로젝트의 pom 순으로 의존성 계층 구조가 성립
  • spring-boot-dependencies의 dependencyManagement에 각종 의존성들에 대한 version이 모두 명시되어 있음
  • 따라서 내 프로젝트의 pom에 spring-boot-dependencies에 정의되어 있는 의존성을 사용하게 될 경우, 직접 version을 명시해주지 않더라도 version 정보를 가져오게 됨
  • 즉, 각각의 starter에 이미 의존성들이 제공되고 있기 때문에 우리가 직접 관리해야 할 의존성의 수가 줄어들게 됨
    • 우리가 관리해야 하는 일이 줄어든다는 의미
    • version up을 하고자 할 때, third-party library의 어느 version과 호환되는지 모르는 문제도 해결 가능
    • 깔끔한 의존성 관리
  • pom에서 지원하지 않는 의존성을 추가하고자 할 때는 직접 version을 명시해주어 함!
  • 특정 library의 특정 version의 사용을 원하는 경우 명시해주어 사용 가능 -> 편리한 Customizing
  • 자기만의 의존 구조를 성립시키고 싶을 때는? (두 가지 방법)
    1. 직접 parent pom을 만들어 현재 프로젝트의 parent로 만들고, 그 parent로 spring-boot-starter-parent를 두는 것 (추천)
      • 즉, spring-boot-starter-parent -> 내 프로젝트의 parent -> 내 프로젝트의 구조를 만드는 것
    2. 현재 프로젝트의 parent를 만들고, 해당 parent에 섹션을 만들어 spring-boot-starter를 추가하여 사용 (비추천)
      • but, spring-boot-starter에는 dependency들만 가져오는 것이 아니라, 그 밖의 다른 설정들이 존재
        • ex) java 1.8, UTF-8, 각종 yml, plugin 설정 등
      • 이 설정들을 가져오지 못하는 불편함 존재

의존성 관리 응용

    1. 버전 관리 해주는 의존성 추가
    • spring-boot-starter-data-jpa
    1. 버전 관리 안해주는 의존성 추가
    • ModelMapper: version을 명시해주어야 함
<dependency>
    <groupId>org.modelmapper</groupId>
    <artifactId>modelmapper</artifactId>
    <version>2.3.1</version>
</dependency>
  • What is ModelMapper?
# Source model
class Order {
    Customer customer;
    Address billingAddress;
}

class Customer {
    Name name;
}

class Name {
    String firstName;
    String lastName;
}

class Address {
    String street;
    String city;
}

# Destination model
class OrderDTO {
    String customerFirstName;
    String customerLastName;
    String billingStreet;
    String billingCity;
}

# Domain to DTO를 자동으로 해주는 기능!
ModelMapper modelMapper = new ModelMapper();
OrderDTO orderDTO = modelMapper.map(order, OrderDTO.class)
    1. 기존 의존성 버전 변경하기
    • 내 프로젝트 pom의 에 직접 명시해주어 변경 가능!
    <properties>
        <spring.version>5.0.6.RELEASE</spring.version>
        <java.version>1.9</java.version>
    </properties>

자동 설정 이해

  • @Configuration?
    • Bean을 등록하는 java 설정 파일
  • SpringBootApplication의 핵심 annotation들!
    • @SpringBootConfiguration
    • @ComponentScan
    • @EnableAutoConfiguration
  • 스프링 부트는 Bean을 두 번 등록
    1. ComponentScan으로 한 번
    2. EnableAutoConfiguration으로 또 한 번
  • 1단계: @ComponentScan
    • @Component을 달고 있는 class들을 Scan해서 Bean으로 등록
    • @Configuration, @Repository, @Service, @Controller, @RestController 들도!
  • 2단계: @EnableAutoConfiguration
    • springframework.boot.autoconfigure.EnableAutoConfigure 내 META-INF의 spring.factories 파일 읽어옴
    • 그 아래의 @Configuration들 읽어옴
    • but, @ConditionalOn'XxxYyyZzz'
      • 즉, 조건에 따라 Bean으로 등록하기도 하고, 안하기도 함!

스프링 부트 시작하기

스프링 부트 소개

  • 토이 수준이 아닌 Spring 기반의 Production-grade의 독립적 어플리케이션을 빠르고 쉽게 만들 수 있도록 도와줌
  • Opinionated view: 개발자가 직접 설정하지 않고도, Spring boot가 정의하는 Convention을 자동으로 설정해주는 것
    • 따라서 모든 것을 일일이 설정하지 않아도 됨
    • Spring platform 뿐 아니라, third-party library에 대한 설정도 자동으로 해줌
      • ex) Tomcat의 8080 port 설정...
  • 스프링 부트의 목표
    • 모든 스프링 개발에 있어 빠르고, 폭 넓은 사용성을 제공
    • Opinionated view를 제공하지만, 개발자가 원할 시 쉽고 빠르게 설정 변경 가능
    • 비즈니스 로직을 구현하는데 필요한 기능 뿐 아니라 Non-functional한 기능도 제공
    • xml 설정을 더 이상 하지 않고, code generation을 하지 않음
      • 쉽고 명확하며, 더 편리하게 customizing이 가능해짐!

스프링 부트 시작하기

  • group id는 보통 package명으로 설정
  • spring boot의 parent로 spring-boot-starter-parent 추가해줌
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
    </parent>
  • Maven 간 프로젝트 계층 구조 만드는 것

    • spring-boot-starter-parent를 부모 프로젝트로 설정
    • Spring boot가 제공하는 의존성 관리와 매우 관련이 깊은 설정!
  • spring-boot-starter-web 의존성 추가

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
  • build plugin 추가
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
  • IntelliJ에서 psvm 으로 Main 함수 추가 가능
  • mvn package로 maven project build 가능
    • jar 파일을 결과물로 생성!
  • 이후, java -jar 'jar 명'으로 jar 파일 생성 가능

스프링 부트 프로젝트 구조

  • 메이븐 기본 프로젝트 구조와 동일
    • 소스 코드
    • 소스 리소스
      • classpath가 root dir 의미
    • 테스트 코드
    • 테스트 리소스
  • @SpringbootApplication이라는 annotation이 달려 있는 MainApplication class는 가장 최상위 패키지에 두는 것이 추천됨
    • @SpringbootApplication을 기점으로 Component scan을 하기 때문
    • java 폴더 바로 밑에 Main class 두게 될 경우, 프로그램에 존재하는 모든 패키지를 뒤져서 component를 찾는 비효율 발생
    • 따라서, 다른 패키지에 있는 moduleㅡㄹ은 component로 등록이 안되기 때문에 디렉토리 구조를 설정는데 주의!

다형성: Polymorphism

  • Super class 타입의 변수가 Sub class 타입의 객체를 참조할 수 있다!
  • 예시) Notebook class가 Computer class를 상속 받고 있다고 가정
Computer computer = new Notebook("Bravo", "Intel", 4, 240, 2/4, 15)
  • Computer 타입의 변수 computer가 Notebook 타입의 객체를 참조하고 있음!

  • 다음의 예를 생각해보자
  • 가정) Computer와 Notebook class는 모두 toString method를 지니고 있음
System.out.println(compter.toString());
  • 위 예에서의 toString은 두 class 중 어느 class의 method를 호출하게 될까?
  • 답은 Notebook class의 toString !
    • 즉, 동적 바인딩(dynamic binding)이 일어남

      • Runtime 중에 참조 객체를 결정
    • cf. Computer class의 toString을 호출하는 경우, 정적 바인딩
      • 컴파일러가 참조 객체를 결정


'Software Convergence > Java' 카테고리의 다른 글

Object 클래스와 Wrapper 클래스  (0) 2018.11.13
static과 접근제한자  (0) 2018.10.19
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04

Spring boot camp #3

기본적인 웹 Template

  • application과 사용자의 접점인 boundary
    • 조회 화면, 글쓰기 화면 등이 boundary의 예
  • 사용자가 요청한 업무를 처리하는 control
  • 게시물과 같은 entity
  • 외부 시스템(ex. 외부 결제 시스템)과의 접점도 필요함
    • 이 역시 boundary로 구현하여 control과 연동시킴
  • Transaction은 Spring JDBC, Spring Data JPA 그리고 외부 웹에서 자료를 받아오기 위한 Rest template 등에 의해 수행
    • DBMS 관리와 SQL에 대한 지식을 DBA 만큼은 아니더라도 갖추어야 함

Java와 Database programming

  • 입력, 수정, 삭제
      1. DB connection: connection Interface, DriverManager class 사용
      1. SQL 준비(ex. insert into table명 values(...))
      • DB가 sql을 이해하기 위해 문장을 parsing 하는데, 이는 큰 overhead를 발생시킴
      • parsing 결과를 DB 자체에 저장해두었다가, 완전히 동일한 sql문이 오면 이전에 저장해둔 값 사용
        • insert의 경우, values가 계속 변화할 수 있기 때문에 '?'로 채워뒀다가 ? 값만 바꾸어 사용 -> 성능 개선
      1. 바인딩: ?에 값을 채워주는 것
      • PreparedStatement interface 사용
      1. PreparedStatement의 executeUpdate method 호출
      1. DB connection close
  • 데이터 조회
      1. DB connection
      1. SQL 준비
      1. 바인딩
      1. executeQuery() method 실행
      1. ResultSet Interface의 next() method 이용하여 row 한 건 씩 읽어옴
      • 즉, SQL의 select 문에는 ResultSet interface가 사용됨
      1. 읽어온 row를 column별로 잘라서 사용
      • ResultSet의 getXXX method 사용
      • ex) getName(), getTitle()...
      1. DB connection close
  • connection Interface는 DBMS 프로그램별(MySQL, Oracle..)로 다름
    • 따라서, 이 Interface를 구현하는 class는 해당 DBMS 프로그램에 존재
    • 이 class를 Driver class라 함
  • DBMS를 다루다 보면 기능별로 중복된 코드가 발생할 수 있음
    • 그리고 이는 지루한 프로그래밍을 유발
    • 또한 Java 코드로 관리하기가 어려워짐
      • 문자열이 단순히 + 연산으로 이어지기 때문!
    • xml 파일에 id값 부여하여, SQL 코드 따로 관리하자!
  • 객체에 있는 정보를 ?에 넣어주고, data를 조회하면 객체로 받아올 수는 없을까?
    • SQL 중심으로 database 코드를 짜는 SQL mapper
      • MyBatis, Spring JDBC 등이 그 예
    • SQL만 작성하면 되기 때문에 더 쉽게 프로그래밍이 가능해짐
  • 그러나 SQL은 객체지향적이지 않음
    • ex) 게시물과 댓글의 1:n 관계
      • 게시물의 getComments()와 같은 method로 댓글을 읽어오고 싶음
      • 두 Entity 간의 관계를 객체지향적으로 표현하기가 어려움
        • 패러다임의 충돌: SQL적 사고와 객체지향적 사고에는 근본적인 차이가 존재
  • DBMS 프로그래밍을 객체지향적으로 할 수 있지 않을까?
    • 그러려면 우선 SQL 자체를 제거해야 한다!
    • 개발자는 객체만 생각하고, SQL은 어디선가 자동으로 만들어주도록 하자
    • 이렇게 나온 기술이 ORM(Object Relation Mapping) -> Hibernate
      • Hibernate는 어렵지만, 객체지향적 사고를 좋아하는 사람들에게 환영 받는 기술
      • Java 측에서 JPA(Java의 ORM 표준)이 등장!
      • JPA를 사용하면 SQL을 모르더라도 DBMS 사용 가능
  • Spring은 또 다른 고민에 빠짐
    • Data 저장소는 DBMS만 존재하는 것이 아님
      • ex) NoSQL(like. MongoDB), Hadoop...
    • 한 단계 더 추상화하여, Spring Data라는 module 제공
      • Spring Data JPA를 사용하여, module이 JPA 관리하도록 함
      • 때문에 Spring Data MongoDB와 같은 module도 존재
  • 결과적으로 JDBC -> Hibernate & JPA -> Spring Data의 발전 구조
    • 수업에서는 이를 다 다룰 수는 없기 때문에 Spring Data 위주로 다룸

about JPA

  • Spring Data JPA를 추가하면?
    • DataSource) (Interface: Connection Pool)
      • Spring Boot 2 에서는 HikariCP 사용
    • PlatformTransactionManager (transaction 관리자)
      • Spring은 AOP로 트랜잭션 관리 지원
    • JDBC Driver
      • h2: 인메모리 DBMS
      • web 환경 같이 사용할 경우에는 localhost:8080/h2-console로 클라이언트 접속이 가능
  • 아래와 같은 starter와 jdbc 드라이버 의존성을 추가하면, 자동으로 DataSource와 PlatformTransactionManager에 대한 설정이 추가 됨
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>runtime</scope>
</dependency>
  • DataSource ---> Connection Pool ---> DBMS
    • Connection Pool은 DBMS와 미리 여러 개의 connection을 하고 있음
    • 즉, DataSource를 사용한다는 것은 Connection을 DataSource에게 요청하는 것
  • DataSource에게서 받은 Connection의 close() method는 Connection을 끊는다는 것이 아니라, CP에 되돌려주는 것!
    • Connection은 받아서 빨리 돌려주어야 함
    • 그러기 위해서는 SQL이 빠르게 동작해야 함
    • Slow query를 해결하여 성능 향상을 해주어야 하는 이유
  • spring.datasource.initialization-mode= always 설정은 sample data 생성하기 때문에 test 용이하게 할 수 있음
  • spring.jpa.hibernate.ddl-auto= create-drop 설정은 table이 존재하지 않을 시, 자동으로 hibernate가 table 만들도록 하는 설정. 존재한다면 삭제 후 재생성

  • JPA에서의 '저장'은 영속적이다?
    • ex) 회원이 탈퇴할 때 까지 회원 정보는 유지되어야 함
    • entity 객체를 영속적 정보를 저장해주어야 함
  • 영속 상태가 되기 위해서는 반드시 식별자 값을 가지고 있어야 함
  • insert 뿐 아니라 조회할 때도 해당 데이터는 영속적이어짐
  • EntityManager가 영속성 관리
    • 때문에 EntityManager는 Bean으로 등록되어 Spring이 관리해주도록 해야 함
  • EntityManager는 transaction 단위로 작업을 수행
    • transaction: 하나의 논리적 작업 단위
    • commit이나 rollback이 하나의 transaction을 마치게 함
  • 이처럼 Transaction 단위로 동작하는 것을 Business method라 함
    • 그리고 이를 가지고 있는 객체가 Service 객체
    • 따라서 객체 설계 시에는 해당 객체의 Business method가 무엇이 있을지에 대한 고민이 필요
  • Service 객체는 CRUD를 위해 Repository(DAO) 참조
  • Service 객체의 method에 @Transactional 혹은 @Transactional(readOnly = true) annotation 있으면 proxy 생성되어, Transaction 알아서 관리
    • PlatformTransactionManager가 이 작업을 수행해줌
      • 이는 Connection에 의존하는 관계
      • Connection이 transaction begin, commit, rollback 등을 가지고 있기 때문
    • readOnly 인자는 조회(select)만 하는 method일 경우 사용
      • 조회할 때 매 번 commit을 수행하면 성능이 확 떨어지기 때문!
    • proxy는 try문 내에서 super.'method' 수행 후, commit
    • RuntimeException는 catch 해서 rollback 처리
  • 같은 transaction 안에서는 1차 캐시가 적용됨
    • 이전에 불러온 data를 또 요청하면 다시 가져오는 것이 아니라 이미 가지고 있는 것을 돌려줌
    • 즉, 같은 id에 대한 query는 한 번만 수행되는 것
  • 영속성이 부여되면 snapshot으로 복사본이 하나 만들어짐
    • Entity의 수정 기능은 setter로 행하게 됨
    • 기존에 만들어진 snapshot과 setter로 수정된 entity의 값을 비교해서 다르면 자동으로 update 문장 만들어 update 반영
  • Entity들 간의 관계에서는 방향이 중요함
    • ex) 부서(1) <----> 사원(N) 일 때 부서는 List<사원>, 사원은 부서라는 field를 가지고 있어야 함
    • 이럴 때 List<사원>에는 @OneToMany라는 annotation을, 부서에는 @ManyToOne annotation이 붙음
      • @OneToMany에는 (mappedBy='department')와 같은 것을 추가해주어 어떤 field로 연동되는 것인지 알려줌
      • Foreign Key를 위해 사원에는 @JoinColumn(부서_id)와 같은 annotation을 추가
    • ex) Member(N) <----> MemberRole(N)
    • 실제 다대다 관계는 일대다-다대일로 풀려짐
    • 다대다 관계에는 @JoinTable annotation이 붙어야 함
  • 부서.get사원들() 하면 SQL 실행 안됨 -> 단순히 Persist 속성만 넘어옴
    • 실제로 List를 사용할 때 select 문이 실행됨 -> Lazy Loading
  • Entity를 만들면 hibernate가 해당 entity에 대한 proxy를 생성
    • 실제로 사용되는 것은 우리가 만든 entity가 아닌 해당 proxy
  • 1 + N query 문제
    • 목록 가져오는 query 1번
    • Lazy Loading으로 정보 가져오는 N번 -> 너무 많은 query가 수행되어야 한다!
    • Repository에 method를 추가해서 해결
      • 부서와 사원을 fetch join: 관련된 부서와 사원을 한 꺼번에 가져오는 것!
  • 되도록 id는 개발자가 설정하는 것이 아니라 자동 생성(auto-increment)되도록 해주는 것이 성능 상 좋음

    • 수동으로 설정하면 id가 기존에 존재하는 값인지 검사하는 연산을 수행해야 하므로
  • category.getBoards() 와 같은 method를 사용하면 data가 수 십만 건이 될 수도 있음
    • 따라서 많이 사용되는 method는 아님
    • paging 처리해서 가져오는 것이 better!
      • 이 역시 repository를 통해 가져와야 함
    • 자료의 건수에 따라 전략을 잘 선택하자
  • FetchType.EAGER는 table 간 관계가 뗄 수 없는, 즉 반드시 함께 사용되야 할 때만 사용!
    • 기본은 LAZY로 쓰고 join하고 싶을 경우, repository에서 join 해서 사용
  • Repository에 Query method 생성 가능
    • method 이름을 보고 query 문이 자동으로 생성되게 됨
    • ex) BoardRepository에 findAllByName method 추가하면 이름과 관련한 SQL 검색 가능
  • JPA에 native query도 사용이 가능하나, 그럴 경우 해당 DBMS에 종속되는 것이기 때문에 추천하는 방법은 아님
    • JPA를 사용할 떄는 JPQL을 잘 다루는 것이 더 좋음
  • DBMS를 다루다 보면 Dynamic query도 존재할 수 있음
    • dynamic query: 조건에 따라 where절이 붙거나, 안 붙거나 하는 query
    • 이러한 Dynamic query는 Query method로 해결이 불가능
    • BoardRepositoryCustom과 같은 interface 생성해서 method 정의
    • BoardRepositoryImpl class를 생성해서 interface의 method 실 구현
      • proxy가 이 놈 사용(즉, BoardRepository와 BoardRepositoryImpl 사용)
    • 구현 방법
        1. EntityManager를 직접 주입하여, JPQL 조작 -> JPA 공부하면 상대적으로 수월
        • @Autowired
        • EntityManager
        • 문자열에서 오타 낼 가능성이 많음..
        1. JPQL을 다루기 위한 문법인 JPQL criteria 참조 -> 어려움
        1. QueryDSL 사용
        • Entity 정보들을 읽어들여 소스 코드 생성하는 라이브러리
        • ex) QBoard, QCategory...
        • 환경설정 어렵지만, 이후에 편리
          • maven 설정
    • 즉, BoardRepository는 JpaRepository와 BoardRepositoryCustom을 상속 받게 되는 것

etc

  • 커뮤니티가 많이 발달한 Java: 느리지만 지속적으로 발전하는 이유
    • 비슷한 기술이 등장하면 JSR에서 표준을 정해줌
    • 기술이 나오고 표준이 이후에 나오기 때문에, 동일한 기능을 하는 방식이 여럿 일 수 있음
  • 기술적 성숙도에 따라 아키텍쳐가 달라짐
    • JPA 같은 경우 난이도가 있기 때문에 주변에 같이 고민할 수 있는 사람이 있어야 함
    • 때문에 회사의 기술 stack을 보면 해당 회사의 기술적 수준을 알 수 있는 경우 많음


static 그리고 접근제한자

static

  • static 멤버는 class 안에 실제로 존재
    • 즉, object의 선언 없이 사용 가능한 멤버
public class Test{
    static int s = 0;
    int t = 0;

    public static void print1(){
        System.out.println("s = " + s);
//      System.out.println("t = " + t);
//      non-static member 접근 불가
    }

    public static void print2(){
        System.out.println("s = " + s);
        System.out.println("t = " + t);
    }
}
  • Java에서의 프로그램은 class들의 집합이기 때문에 main 함수 역시 class 내에 존재해야 함
    • 하지만 class의 객체 생성 없이 main method는 실행되어야 하기 때문에 항상 static으로 선언되어야 함
  • static 멤버 변수의 접근 방법?
    • 'object명'. 과 같이 해도 정상작동하는 경우 많으나, 엄격한 compile 규칙을 따른다면 틀린 것
    • 따라서 class에 속하는 멤버이므로, '클래스명'. 과 같이 접근하는 것이 정석
public class Test {
    static int s = 10;
    int t = 0;
    
    public static void print1() {
        System.out.println("s = " + s);
    }
    
    public void print2() {
        System.out.println("s = " + s);
        System.out.println("t = " + t);
    }
    
    public static void main(String[] args) {
        Test test1 = new Test();
        test1.t = 100;
        test1.print2

        // static 멤버 접근 방법
        Test.s = 100;
        Test.print1();
    }
}
  • static 멤버의 용도
    • main method
    • 상수 혹은 클래스 당 하나만 유지하고 있으면 되는 값
      • ex) Math.PI, Systemo.out
    • 순수하게 기능만으로 정의되는 method
      • ex) Math.abs(k), Math.sqrt(n), Math.min(a, b)



접근 제어: public, private, default, protected

  • public: 클래스 외부에서 접근이 가능
  • private: 클래스 내부에서만 접근 가능
  • default: 동일 패키지에 있는 다른 클래스에서 접근 가능
  • protected: 동일 패키지의 다른 클래스와 다른 패키지의 하위 클래스에서도 접근 가능

데이터 캡슐화

  • 모든 데이터 멤버를 private으로 만들고 필요한 경우 public한 get/set method를 제공
  • 객체가 제공해주는 method를 통하지 않고서는 객체 내부의 데이터에 접근할 수가 없음
    • 함부로 데이터를 접근하거나, 수정할 수 없음
  • 이것이 data encapsulation 혹은 information hiding


'Software Convergence > Java' 카테고리의 다른 글

Object 클래스와 Wrapper 클래스  (0) 2018.11.13
다형성: Polymorphism  (0) 2018.11.05
상속의 단점과 Strategy Pattern  (0) 2018.09.03
Generic 자료형 실습  (0) 2018.07.12
instanceof / encapsulation  (0) 2018.07.04

Spring boot camp #2

JSP & Servlet

  • Spring MVC
    • 내부적으로는 Servlet, JSP를 사용
    • 따라서 Spring을 사용하기 위해서는 Servlet, JSP에 대한 이해를 해야 함
  • 응집도의 개념이란 관련된 기능을 하나의 class가 모아 지니고 있는 것
  • Spring Framework를 이용하는 spring boot
    • 따라서 Spring에 대한 이해를 하는 것이 좋음
    • Spring boot를 사용하면 설정해주지 않아도 되는 부분드리 많지만, 현업에서 이미 Spring으로 작성된 프로젝트를 관리해야 할 일들도 많이 있기 때문
  • Java 웹프로그래밍의 시작, Servlet & JSP

    • Servlet 3.0 이전에는 web.xml 설정을 해주어야 함
      • 하나의 path 설정하는 것이 하나의 servlet
      • 결국, 응집도가 떨어지는 결과 -> 문제
    • 3.0 이후부터는 annotation을 이용해서 path 설정
    • JSP는 HTML code와 Java code를 섞어서 작성하는 것
      • 서버에서 JSP가 java code로 바뀜
        • <h1>hello</h1>이라는 HTML line이 out.write("<h1>hello</h1>")로 변환되는 것
        • 즉, out이라는 Java 변수가 위에 선언되어야 하는 것 -> JSP 내장 객체
      • 근래에는 Java code 잘 사용 안하려고 함
        • 유지보수 어려워지기 때문
      • JSTL과 EL로 결과값만 출력하자! 는 것이 대세
  • Servlet의 구성

    class 'servlet_name' extends HttpServlet{
      doGet()
      doPost()
      Service
      ...
    }
    



After JEE Pattern

  • Java로 기업급에서 프로그래밍을 할 때는 이러한 패턴을 사용하자!
  • Front controller도 그 JEE Pattern 하나

    • browser가 하는 모든 요청을 이 놈이 받도록 함
    • Servlet으로 작성할 수도, JSP로 작성할 수도, ServletFilter로 작성할 수도 있음
  • Spring MVC는 Servlet으로 Front Controller 만듬

    • Spring MVC의 DispatcherServlet이 Front Controller의 역할 수행
    • 즉, Spring MVC의 life cycle이 궁금하다면 DispatcherServlet을 공부해야 함!
      • WAS가 DispatcherServlet을 메모리에 올려주는 역할 수행
        • 1) web.xml에 등록(143.p)
          • 배포를 1초라도 빨리하려면 web.xml에 DispatcherServlet 등록해주는 것이 좋음
          • 명시적인게 빠르기 때문
        • 2) 서블릿 3.0 이상에서는 ServletContainerInitializer 인터페이스 사용 -> WAS용 Java config
        • 3) but, Spring 쪽에서는 모든 객체를 Spring 쪽에서 관리해주고 싶어함
          • WebApplicationInitializer 인터페이스 구현해서 사용 -> Spring용 Java config
          • Servlet 인터페이스를 보고 Spring interface를 확인하기 때문에 배포 속도가 가장 느림
    • DispatcherServlet은 내부적으로 WebApplicationContext(Bean Container)를 지님
  • Front Controller는 관련된 url 요청들을 분배하는 역할을 수행하게 됨

    • 관련된 url을 처리하는 객체를 Spring MVC에서는 'xxx'Controller라고 부름
      • cf.명령을 처리한다는 개념에서 Command Pattern이라고 부르기도 함
    • 프로그래머가 만들고 Spring이 관리해주는 객체
    • @Controller 혹은 @RestController 라는 annotaion이 붙어있어야 함
    • Web에 종속적인 기술
      • UI에 따라 사용되지 않을 수도 있는 것
    • Spring containter가 Component scan을 통해 annotation 붙어있는 객체들 찾음
      • 다 Bean으로 등록해줌
      • Bean이란 Spring이 관리해주는 객체
    • 공통적으로 처리되는 부분들은 객체 하나를 사용해서 중복되게 사용되도록 사용할 수 있음
      • 'xxx'Service라 불리우는 객체 !
      • 즉, 하나의 Controller가 여러 개의 Service를 사용하도록 하는 것 ! (중복된 기능을 제공하기 위해서)
      • @Service annotation 사용
      • Service 안에서 또 중복된 기능을 사용
        • 대개, CRUD 기능이 중복된 코드일 가능성이 높음
        • 이러한 기능을 Repository 혹은 DAO라고 부름
        • @Repository annotation 사용
  • 이처럼 FrontController-'xxx'Controller-'xxx'Service의 계층으로 나뉘어져 구성되기 때문에 'Layered Architecter' 라고 부름

  • Service와 Repository는 별도의 ApplicationContext 필요 (Business Logic 관리하기 위해)

    • Service와 Repository에 해당하는 객체만 관리해줌
    • WebApplicationContext은 Service와 Repository 객체를 사용하기 위해 ApplicationContext를 부모로 가짐(141.p)
    • 자식 container는 부모 container로 부터 객체 먼저 찾음
      • 부모가 가지고 있는 Service를 자식의 Controller에 넣어주게 됨
    • 중요한 것은 Context 간에 부모-자식 관계가 있을 수 있다는 것
  • 경우에 따라서 DispatcherServlet을 여러 개 선언할 수도 있음

    • /board를 1번 Dispatcher가,
    • /users를 2번 Dispatcher가 관리하도록 함
    • 따라서 WebApplicationContext도 2개 생성됨
      • Container를 따로 사용하기 때문에 1번 Dispatcher에서의 객체를 2번 Dispatcher에서 사용 불가
        • 마치 한 서버에 있지만, 두 서버에 있는 듯한 느낌
        • 나중에 Micro service 단위로 분할하기 편하게 하기 위해 사용하는 경우가 있긴 하나 잘 사용되지는 않는 기법



Controller

  • Controller의 예
@Controller
@RequsetMapping("/board")
class test{
    @RequsetMapping("/list")
    static void testmethod(){
        ...
    }
}
  • Spring 4.3 버전 이후부터 RequestMapping 외 GetMapping, PostMapping, PutMapping 등도 등장
  • class의 mapping 정보와 method의 mapping 정보가 결합된 것이 실제 url 주소
  • Controller를 url을 처리해준다하여 Handler라고도 부름
  • HandlerMapping이라는 객체가 존재하여, url 관리
    • 어떤 Controller의 method와 관련이 있다는 정보들을 저장
    • 즉, 내부적으로 DispatcherServlet의 관리해주는 것
    • 유효한 요청을 받았을 시, HandlerAdapter로 보내 실행
      • Controller method는 보통 View 이름 return
        • ModelAndView 혹은 String 객체로 return
  • HTTP header에는 accept 정보 존재
    • browser가 원하는 data format(ex. html, json, xml...)
  • ViewResolver는 어떤 view를 보여줄지에 대한 전략을 세워줌
    • 경로 작성해주고, data format 찍어주어 view 생성하여 return
      • ex) WEB-IMF/views... + /list + .jsp
    • ViewResolver도 여러 개 존재해서, 요청한 data format에 따라 다르게 처리 가능
    • Java config에서 default 값들 설정해주면 됨
  • DispatcherServlet과 Controller 사이에 Interceptor 여러 개 존재할 수 있음
    • 모든 요청에 대해 공통으로 처리해줄 수 있음
    • Dispatcher 앞에 존재할 수 있는 ServletFilter와 유사한 역할 수행



실습

  • Lombok 적용: Preference -> Compiler -> annotation processor -> enable annotation processing
  • @Configuration 붙어있는 class들은 Java config
  • @ConditionalOn이 붙어있는 annotation은 중요한 annotation
    • ex) ConditionalOnMissingBean
      • 사용자가 AutoConfig 사용하지 않고 Bean 직접 생성했을 때 자동 설정을 사용하지 않겠다는 설정
  • spring.factories에서 기본 설정 확인 가능
    • dispathcer servlet 생성해줌
    • MultipartResolver는 file upload용
  • Spring 구버전의 @RequestMapping(method = RequestMethod.GET)가 GetMapping이 됨
  • Spring에서 JSP로 결과 출력하려면 JSTL 의존성 추가해주어야 함
    • tomcat에 기본적으로 포함된 것이 아니기 때문
    • pom.xml과 application.properties에 다음 설정 추가
// pom.xml
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
        </dependency>

// application.properties
spring.mvc.view.prefix= /WEB-INF/jsp/
spring.mvc.view.suffix= .jsp
  • http://www.inven.co.kr/board/{game name}/{board id}
    • 위 예에서 'game name'과 'board id'는 Path variable
  • http://www.inven.co.kr/board/{game name}/{board id}/?sort=PID&p=1

    • 위 예에서 ? 이하의 값은 Request Parameter
    • 이름=값&이름=값 의 형태로 전달
  • 내가 입력한 값들을 저장해야 하는 서버

  • 이전 입력 값들에 대한 parameter를 계속 가지고 다녀야 함
  • form 도 requestParam으로 읽어올 수 있음

  • redirect?

    • 요청을 하는 WebClient와 요청을 받는 WAS의 존재를 가정
      • form을 POST 방식으로 입력
      • HTTP message에는 POST /boards 방식 명시되고, header 정보 이후 body 부분에 user가 입력한 값이 실림
        • 1) @RequestParam으로 입력 값 읽어드릴 수 있고,
        • 2) form의 입력 값이 너무 많을 시, @ModelAttribute 사용
          • @ModelAttribute Board board와 같이 정의
          • set으로 값 채워넣음
          • +) 값을 validate하는 기능 필요
            • 값이 잘못되어있으면 다시 입력하라는 메시지와 함께 이전 정보들 재전송
            • hibernate에 검증 기능 구현
  • Forward vs. Redirect
    • viewname을 return하는 방식은 다 forward
      • forward와 밀접한 관련이 있는 것이 RequestScope
        • 요청 정보는 해당 정보와 관련있는 JSP까지 전달됨
        • SetAttribute로 Request에 값을 담고, GetAttribute로 값을 꺼냄
      • JSP는 RequestScope에서 정보를 꺼내서 결과 출력
    • redirect는 view를 생성하지 않고, browser에게 redirect하라는 명령 (status code: 302)
      • browser는 redirect하라는 주소로 다시 요청보냄
      • 최종적으로 redirect 주소 정보를 받아와 읽게 됨
    • redirect를 할 때도 정보 전달 가능 -> RequestParam을 통해
      • 그러나, header 길이의 한계로 큰 data는 redirect로 전송이 불가능함
      • Spring MVC의 FlashMap 객체 이용해 정보 저장 가능
      • 이후, distpatcherServlet이 FlashMap의 정보를 꺼내서 browser에 제공
      • 해당 FlashMap 정보는 1회용 !
  • @RequestBody와 @ModelAttribute 혼동하지 말자!

    • @RequestBody는 body에 JSON과 같은 데이터 넘어올 때 사용
      • 내가 보낸 정보를 저장해라!
    • body가 form data 형식으로 넘어오면 @ModelAttribute 사용
  • 반환할 객체에 값을 자동으로 채워넣어주는 ArgumentResolver

    • 먼저, 내가 지원하는 type인지를 검사
      • true이면, 해당 객체를 생성
    • Controller method에 객체를 반환해줌
  • Interceptor를 구현하여 값을 검사하거나, 삭제하거나, 검증하는 등의 기능을 구현할 수도 있음
    • 보안 관련된 기능을 구현할 때 용이
  • 작성한 ArgumentResolver와 Interceptor는 Java config에 등록을 해주어야 사용 가능
    • Spring MVC가 읽어들이는 설정에 ArgumentResolver와 Interceptor를 등록해주어야 함
    • ex) WebMvcConfigurer를 구현한 Config class에 두 객체를 모두 등록하여 사용



etc

  • 잘 만들어진 객체는 보는 것만으로도 공부가 됨
    • 내가 객체를 작성해야 할 때 참고하기도 좋음
  • 기술면접에서 화이트보드 면접이 잦아짐
    • 그림 그리면서 설명하는 것이 수월할 것
  • 모든 Web의 기본은 게시판!
  • 프로젝트 주제를 신중하게 정하자
    • 본인이 계속 운영하고 싶은 페이지를 만들어라!
    • open source로 만들어 계속 version up
    • 이후, 이직 과정에서 포트폴리오로 사용할 수 있음
    • Why? 내가 사용하지 않는 코드는 version up이 되지 않음
    • 또한 개발이 50%라면, 운영 역시 50% 만큼의 능력을 요함
  • Paper Prototyping을 하자!
    • 웹 페이지 어떻게 구성될 것인지 detail하게 그려가며 구상
  • 디자인에 신경을 쓰지 않더라도, 최소 bootstrap 정도는 이용하는 것이 좋음
  • 앞으로는 Java 8을 공부해야 함
    • Stream, lambda 등의 신규 문법 숙지!
  • 절대로 운영중인 서버에는 sysout 사용하지 마라
    • 성능이 엄청 떨어짐
    • 대신, logger 객체를 이용해야 함
  • 어느 한 interface가 있고, 다른 class에서 해당 interface를 구현해야 함
    • 이 인터페이스의 모든 기능을 구현하지 않고, 필요한 기능만 구현하고 싶다면?
    • ex) 사용자가 MyInterface만들었고, 해당 인터페이스가 메소드를 5개 가지고 있음
      class MyBean implements MyInterface{
      5개의 메소드 구현해야 함
      }
      
  • 이전에는 이러한 불편함 해결하기 위해 Myinterface를 구현한 MyAdapter라는 default 클래스 제공
    • 해당 interface의 method들을 구현하고 있지만, 내용은 없음
class MyAdapter implements Myinterface{
    ...
    ... 
}

class MyBean extends MyAdapter{
    필요한 것만 Override해서 사용!
}
  • jdk 8부터는 default method 기능 추가됨
    • 이제 interface도 method 구현이 가능해짐!
    • Why? Framework 측에서 제공하는 interface에 method 추가하고 싶은데,
    • 이미 framework를 사용하고 있는 수 많은 프로젝트들 때문에 함부로 추가하지 못함
    • 함부로 method의 갯수를 늘리면 모든 프로젝트가 에러나게 생김
    • default로 구현된 method를 추가하여 배포하면 문제없이 사용할 수 있게 될 것이라는 개념에서 비롯됨


Network Layer (2)

Routing Algorithm

  • Global or decentralized information?
    • global
      • 모든 router는 link cost info를 지녀야 함
      • "link state" algorithms
    • decentralized
      • router는 물리적으로 연결된 이웃과 해당 이웃과의 cost를 알아야 함
      • 연산의 결과에 대해 이웃과 정보 교환을 해야 함
      • "distance vector" algorithms
  • Static or Dynamic?
    • static
      • routes가 시간에 따라 느리게 변화
    • dynamic
      • route가 보다 빨리 변경
      • 주기적인 update
      • link cost가 변함에 따라 변경

Link-State: Dijkstra's algorithm

  • 모든 node들이 net 상의 link costs를 알고 있음
    • link state broadcast를 통해서!
    • 따라서 모든 node들은 같은 정보를 지니고 있음
  • 한 node에서 다른 모든 node로 가는 가장 적은 cost의 path 연산
  • 알고리즘 복잡도: n nodes
    • 다른 모든 node들 까지의 거리를 구해야 하므로, O(n^2)
    • 우선순위 큐를 활용하여 O(nlogn) 까지 성능 향상 가능

Distance Vector algorithm

  • 각각의 node들은 각각의 이웃과의 cost를 알아야 함
  • 시간에 따라 각 node들은 distance vector 추정치를 이웃들에게 전송
  • link cost changes:
    • node가 local link cost를 감지했을 때
    • routing info를 update하고, distance vector 재연산
    • DV가 변동되면 이웃에게 알림

Hierarchical routing algorithm

  • 여태까지의 routing은 이상적인 case
  • 실제로는 그처럼 이상적이지 않음
  • 모든 목적지의 정보를 routing table에 저장할 수 없음

  • router들을 region에 응집시킴 -> Autonomous Systems
  • 같은 AS에 있는 router들은 같은 routing protocol을 따름
    • intra-AS routing protocol
  • 다른 AS에 있는 router들은 다른 routing protocol 따름
  • Gateway router가 각각의 AS의 입구에 존재
    • 해당 AS를 다른 AS와 연결하는 역할




Intra-AS Routing

RIP: Routing Information Protocol

  • use distance vector algorithm
  • 각각의 link는 1 cost를 의미하며, hops 단위로 계산
  • 30초 마다 advertisement를 통해 이웃 간 정보 교환

  • 180초 이후에 advertisement 전송 안되면, 해당 이웃/link를 dead 판정
    • 해당 이웃 지나는 route 모두 무효 판정
    • 따라서 새로운 ad를 이웃들에게 보냄

OSPF: Open Shortest Path First

  • use link state algorithm(다익스트라 알고리즘)
  • 각각의 node에는 모든 cost 비용 존재
  • OSPF advertisement는 이웃 당 하나의 entry 나름
    • advertisement는 전제 AS로 퍼짐
  • 모든 OSPF 메시지는 악의적 침입을 막기 우해 authenticated
  • RIP는 하나의 path만 허용하지만 OSPF에는 같은 cost의 길이 여러 개일 경우, 다수의 paths 허용
  • 큰 domain에서는 hierarchical OSPF 사용


Internet inter-AS routing: BGP(Border Gateway Protocol)

  • inter-domain routing protocol
  • 두 개의 BGP router들이 BGP msg 교환
    • advertising paths to different dest
    • exchanged over semi-permanent TCP connection
  • How does entry get in forwarding table?
    • Router가 다른 AS의 prefix임을 인지
      • BGP advertisement를 통해 다른 모든 router들에게 알림
    • 해당 prefix를 위한 router의 output port를 결정
      • BGP route selection을 통해 최적의 inter-AS route 설정
      • OSPF를 사용하여 inter-AS route로 향하는 최적의 intra-AS route를 설정
      • Router가 해당 경로의 prot를 idetify
    • prefix-port entry를 forwarding table에 입력

Why different Intra-, Inter-AS routing ?

  • intra-AS: 성능에 초점을 둘 수 있음
  • inter-AS: 성능보다 policy에 초점을 맞추어야 함

Broadcast routing

  • source로부터 다른 모든 node들에게 패킷 전달
  • source packet을 복제하는 것은 비효율적

In-network duplication

  • flooding
    • node가 broadcast packet을 받으면 다른 모든 이웃들에게 복사본 전송
    • cycle 생길 위험 있음
  • controlled flooding
    • node가 이전에 같은 packet을 broadcast하지 않았다면 해당 packet만 broadcast
    • 이미 broadcast 되었던 packet id를 트랙킹
  • spanning tree
    • node들이 여분의 패킷을 전송받을 필요 없음

Spanning Tree

  • node들이 spanning tree를 따라 copy를 전송
  • 외에도 Shortest path tree, Reverse path forwarding, Steiner tree 등의 구조가 있을 수 있음


'Software Convergence > Network' 카테고리의 다른 글

HTTP 상태 코드  (1) 2018.11.15
Network Layer (1)  (0) 2018.10.07
Transport Layer  (0) 2018.10.07
OSI 7 Layers Overview  (0) 2018.10.01
Application Layer  (0) 2018.09.30

+ Recent posts