7주 차 시작!

 

package 키워드

자바의 패키지는 비슷한 성격의 자바 클래스들을 모아 놓은 자바의 디렉터리를 말한다.

크게는 built-in package 와 custom package로 구분할 수 있다.

 

package 키워드는 모든 클래스 파일에 최상단에 존재하여야 하고, 하나의 소스만 존재해야 한다.

 

 

Built-in package? (내장 패키지)

java, lang, javax, net, io, util, math... 등 Java API에 포함된 모든 패키지들을 말한다.

 

Custom package? (사용자 정의 패키지)

사용자(개발자)가 정의한 패키지를 말한다.

 

Sub package? (하위 패키지)

어떤 package 내부에 존재하는 package를 Sub package라고 한다.

이는 하나의 package 에서도 객체의 행위를 기반으로 다시 분류하기 위함이다.

  • 입력, 출력 작업 → io package
  • 네트워크 작업 → net package...

 

package를 사용함으로써 얻을 수 있는 장점

  • 클래스와 인터페이스를 성향, 쓰임세에 맞게 분류하여 쉽게 유지 보수할 수 있다.

  • 접근 지정자를 통한 가시 범위(보호 범위)를 제공한다.

접근 지정자가 명시되지 않은 경우 package-private, 즉 패키지 내에서만 참조 가능하다.

  • 클래스, 인터페이스가 같은 이름을 가짐으로써 발생하는 충돌을 방지한다.

 

package 명명 규칙

  • 패키지 이름은 클래스, 인터페이스 이름과 충돌하지 않도록 소문자로 작성한다.

    → 대문자를 사용하지 않는 것이 좋다. (권고사항)

  • 최상위 도메인/나라 코드. 회사명/팀명/그룹명(회사 내규). 프로젝트명/프로그램 명으로 작성한다.

    → com.example.project (패키지 정의 표준 사항)

  • 자바 예약어를 사용해서는 안된다.

자바 패키지 내부 클래스 실행 방법

// Sample.class
java com.example.project.main.Sample

 

Package Class?

해당 package에 대한 Spec 및 Implement 정보를 얻을 수 있는 메서드를 제공하는 클래스이다.

ClassLoader와 BootLoader를 사용하여 해당 정보를 로드하고 접근한다.

@Test
    void PackageTest() {
        Package aPackage = Package.getPackage("java.lang");
        Package[] aPackages = Package.getPackages();
        System.out.println(Arrays.toString(aPackages));

        System.out.println(aPackages.length);

        // package name
        System.out.println(aPackage.getName());

        // package spec Title
        System.out.println(aPackage.getSpecificationVersion());
        // package spec Vendor
        System.out.println(aPackage.getSpecificationTitle());
        // package spec Version
        System.out.println(aPackage.getSpecificationVendor());

        // package impl Title
        System.out.println(aPackage.getImplementationVersion());
        // package impl Vendor
        System.out.println(aPackage.getImplementationTitle());
        // package impl Version
        System.out.println(aPackage.getImplementationVendor());

        // package annotations
        Annotation[] annotations = aPackage.getAnnotations();
        System.out.println(Arrays.toString(annotations));

        // package declaredAnnotations
        Annotation[] declaredAnnotations = aPackage.getDeclaredAnnotations();
        System.out.println(Arrays.toString(declaredAnnotations));
    }

 

import 키워드

import?

기본적으로 접근할 수 없는 다른 패키지에 접근하기 위해 사용되는 키워드이다.

  • java lang과 현재 패키지에 대해서는 생략할 수 있다.
// 형식
import domain.project(program).subpackage;
import domain.project.*;

// 예시
import org.junit.jupiter.api.Test;

// .* 를 사용함으로써 해당 패키지의 하위 패키지, 클래스를 모두 접근할 수 있다.
import org.junit.jupiter.api.*;

 

static import?

JDK 5에 추가된 기능으로 어떤 클래스의 정적 멤버에게 직접 액세스 할 수 있도록 지원하는 기능이다.

Class 명을 명시하지 않고 static import 설정을 함으로써 정적 멤버만을 명시하여 사용할 수 있다.

  • static variable, static method

장점

  • 자주 사용하는 정적 메서드(기능)를 한결 쉽게 사용할 수 있다.

      import org.junit.jupiter.api.Assertions;
      import org.junit.jupiter.api.Test;
    
      import static org.junit.jupiter.api.Assertions.assertEquals;
    
      @Test
      void staticImportTest() {
          // non-static-import
          Assertions.assertEquals("A", "A");
    
          // static-import
          assertEquals("A", "A");
      }

단점

  • 과도하게 사용하는 경우 (정적 메서드 이름 중복 등) 어떤 클래스의 정적 메서 드을 가져온 것인지 확인하여야 한다. (의도한 동작이 발생하지 않을 수 있고, 로직을 하나하나 찾아보아야 한다.)

 

클래스패스

JVM에서 사용하는 매개변수로 Java 프로그램을 컴파일 및 실행하는 데 사용되며, Built-in package와 Custom package에 경로를 지정하여 Application ClassLoader를 통해 참조, 접근할 수 있다.

 

CLASSPATH를 설정하는 경우

  • 현재 Directory나 Sub Directory에 없는 Class를 사용하여야 하는 경우
  • 지정한 위치에 존재하지 않는 Class를 불러와야 하는 경우

 

CLASSPATH 형식

CLASSPATH는. class 파일이 포함된 디렉터리와 파일을 콜론으로 구분한 목록이다.

  • CLASSPATH의 기본 값은 . 이며, 현재 검색된 Directory를 의미한다.

    → 이는 CLASSPATH 변수나 -classpath 명령에 의해 변경할 수 있다.

  • 여러 클래스 경로를 설정하려면 (새미 콜론) ; 를 사용하여 CLASSPATH를 구분하여야 한다.

 

CLASSPATH를 설정하는 항목에 따라 다른 형식을 가진다

// 지정할 파일이 JAR 또는 zip 인 경우
C:\Program Files\Java\jdk-1.8.0.252-2\jre\lib\resources.jar
C:\Program Files\Java\jre1.8\MySQL-Connector Java.jar
C:\Users\xxx\Downloads\example.zip

// 클래스 파일 이름이 지정되지 않은 패키지에 있는 경우
C:\Users\xxx\someDirectory

 

자바에서 사용되는 CLASSPATH Library는 GNU CLASSPATH라는 opensource이다.

 

GNU CLASSPATH Properties

  • gcj.dumpobject

    빈 문자열이 아닌 문자열을 설정한 경우, Library Debug build에 사용되는 Serialize Debuging을 활성화시킨다.

  • gnu.classpath.vm.shortname

    VM의 간결한 이름을 나타낸다.

  • gnu.classpath.home.url

    시스템 속성 파일을 찾는 데 사용되는 기본 URL Pattern 값을 지정한다.

    기본적으로 java.home의 lib Directory를 가리키는 값을 가진다.

추가! )

Spring Framework에서 사용되는 표준 Resolver인 PathMatchingResourcePatternResolver는 리소스에 접근할 때 CLASSPATH Pattern으로 매개변수를 받아 접근한다.

PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
resolver.getResources("classpath:mybatis/mapper/*.xml")

 

CLASSPATH 환경변수

고급 시스템 설정 / CLASSPATH 변수 설정

Window의 경우 win + Pause key를 눌러 제어판 \ 모든 제어판 항목 \ 시스템으로 이동할 수 있다.

여기서 고급 시스템 설정으로 들어간다.

여기서 환경 변수를 클릭하면 사용자 변수와 시스템 변수를 수정, 추가할 수 있다.

CLASSPATH 속성이 있는 경우 편집 버튼을 클릭하고 ;을 입력한 뒤 파일 경로를 추가하면 된다.

없는 경우에는 새로 만들기를 클릭하고 변수의 이름을 CLASSPATH로 설정한 뒤 값을 지정한다.

 

명령 프롬프트 설정

명령 프롬프트를 실행시킨 뒤

// 클래스 패스 속성이 이미 설정된 경우
SET CLASSPATH=%CLASSPATH%;C:\Program Files\Java\jdk-1.8.0.252-2\jre\lib\resources.jar

// 없는 경우
SET CLASSPATH=C:\Program Files\Java\jdk-1.8.0.252-2\jre\lib\resources.jar

;을 우선 작성하고 추가할 파일의 경로를 작성한다.

→ %으로 묶여 있는 변수는 기존의 환경 변수를 뜻한다.

 

CLASSPATH 옵션

. java 파일을 컴파일하기 전에 해당 파일이 필요로 하는 클래스들을 찾기 위해 사용하는 옵션이다.

-classpath 뒤에 Directory Path를 작성하면 컴파일 시 해당 Directory를 탐색하게 된다.

// javac -classpath <find-Directory-path> <Executable-file-path>
javac -classpath C:\Java\example example.java

 

접근 지시자

public : 모든 클래스에서 해당 클래스를 참조 가능하다.

public class PublicExample {

    public static void main(String[] args) {
        PublicExample example = new PublicExample();
        example.run();
    }

    public void run() {
        PublicClass publicClass = new PublicClass();
        publicClass.getName();
    }
}

public class PrivateClass {
    private final String name = "Lob!";

    private void getName() {
        System.out.println("PrivateClass.getName = " + name);
    }
}
PublicClass.getName = Lob!

 

package-private : 해당 클래스가 포함된 패키지 내에서만 참조 가능하다. (지정이 없는 경우)

public class PackagePrivateExample {

    public static void main(String[] args) {
        PackagePrivateExample example = new PackagePrivateExample();
        example.run();
    }

    public void run() {
        PackagePrivateClass packagePrivateClass = new PackagePrivateClass();
        // error: getName() is not public in PackagePrivateClass; cannot be accessed 
        // from outside package packagePrivateClass.getName();
        packagePrivateClass.getName();
    }
}

public class PackagePrivateClass {
    final String name = "Lob!";

    void getName() {
        System.out.println("PackagePrivateClass.getName = " + name);
    }

}

 

protect : 서브, 하위 클래스와 동일 패키지 내부에 존재하는 클래스만 참조 가능하다.

  • 기본적인 Class 에는 적용할 수 없으며, 중첩, 내부 클래스에는 적용 가능하다.
public class ProtectExample extends ProtectClass{

    public static void main(String[] args) {
        ProtectExample example = new ProtectExample();
        example.run();
    }

    public void run() {
        ProtectClass protectClass = new ProtectClass();
        protectClass.getName();
    }
}

public class ProtectExample2 {

    public static void main(String[] args) {
        ProtectExample example = new ProtectExample();
        example.run();
    }

    public void run() {
        ProtectClass protectClass = new ProtectClass();
        protectClass.getName();
    }
}

public class ProtectClass {

    private final String name = "Lob!";

    protected void getName() {
        System.out.println("ProtectClass.getName = " + name);
    }
}

--------------------------
// (패키지 외부) = 상속시 사용 가능
public class ProtectExample3 {

    public static void main(String[] args) {
        ProtectExample example = new ProtectExample();
        example.run();
    }

    public void run() {
        ProtectClass protectClass = new ProtectClass();
        // error: getName() has protected access in ProtectClass protectClass.getName();
        protectClass.getName();
    }
}
// ProtectExample 
ProtectClass.getName = Lob!

// ProtectExample2 
ProtectClass.getName = Lob!

 

private : 자기 자신인 객체 내부에서만 참조 가능하다. (인터페이스도 JDK9부터 사용 가능)

public class PrivateExample {

    public static void main(String[] args) {
        PrivateExample example = new PrivateExample();
        example.run();
    }

    public void run() {
        PrivateClass privateClass = new PrivateClass();

                // 'getName()' has private access in 'example.accessmodifiers.PrivateClass'
        privateClass.getName();
    }
}

-----------------------------

public class PrivateClass {
    private final String name = "Lob!";

    private void getName() {
        System.out.println("PrivateClass.getName = " + name);
    }
}
error: getName() has private access in PrivateClass privateClass.getName();

 

참고 자료

'Live Study' 카테고리의 다른 글

Live Study_Week 09. 예외 처리  (0) 2021.01.11
Live Study_Week 08. 인터페이스  (0) 2021.01.05
Live Study_Week 06. 상속  (0) 2020.12.21
Live Study_Week 05. 클래스  (0) 2020.12.15
Live Study_Week 04. 제어문 + 과제  (0) 2020.12.01

Proxy Pattern?

Proxy Pattern?

실제 비즈니스 로직과 그 외의 코드를 분리시키는 역할을 수행하는 객체를 만드는 패턴이다.

-> 실제로 로직을 수행하는 객체의 인터페이스 역할을 하게된다. 

 

객체를 호출하는 지점에서 프록시 객체를 호출하여 부가적인 코드를 수행한 뒤 참조 변수를 통해 실제 서비스 객체를  호출한다.

 

 

클라이언트는 프록시를 통해 서비스 객체 기능을 사용하기에

  • 접근 권한
  • 부가기능
  • 리턴 값 변경
  • 로깅
  • 트랜잭션 등

이러한 기능을 추가 할 수 있다.

 

즉 서비스 객체의 SRP를 해치지 않고 프록시를 통해 책임을 추가할 수 있다.

 

 

해당 Pattern의 특징

  1. 프록시 객체는 실제 서비스 객체와 같은 이름의 메서드를 구현한다.
  2. 프록시 객체는 합성을 통해 서비스 객체에 대한 참조 변수를 가진다.
  3. 프록시 객체는 실제 서비스의 메서드를 호출하고 그 결과를 클라이언트에게 반환한다.
  4. 프록시 객체는 실제 서비스 메서드의 호출 전, 후에 별도의 로직을 수행할 수 있다.

 

Pure Java Proxy

 

우선 실제로 동작할 서비스 객체와 프록시 객체의 타입을 정의한다.

 

TargetObject Interface

public interface TargetObject {

    String someMethod(String name);

}

 

앞서 선언한 인터페이스를 구현하는 서비스 객체와 프록시 객체의 클래스를 정의한다. 

 

TargetObjectImpl Class

public class TargetObjectImpl implements TargetObject {

    @Override
    public String someMethod(String name) {
        return "Real Subject method "+ name +"\n";
    }
}

 

 

 

TargetObjectProxy Class

public class TargetObjectProxy implements TargetObject {

    TargetObjectImpl subject;

    {
        subject = new TargetObjectImpl();
    }

    @Override
    public String someMethod(String name) {
        System.out.println("Before proxy");

        return subject.someMethod(name) + ("After proxy\n");
    }
}

 

만들어낸 프록시 객체를 호출해보자.

 

PureProxyClient Class

public class PureProxyClient {

    public static void main(String[] args) {
        PureProxyClient client = new PureProxyClient();
        client.run("Lob");
    }

    public void run(String name){
        TargetObjectProxy proxy = new TargetObjectProxy();
        System.out.println(proxy.someMethod(name));
    }

}
Before proxy
Real Subject method Lob
After proxy

 

 

Dynamic Proxy?

 

런타임에 특정 인터페이스들을 구현하는 클래스나 인스턴스를 만드는 기술을 말한다.

  • Spring Data JPA
  • Spring AOP (Method Invocation을 사용하기에 메서드 래밸만 지원한다.)
  • Mockito
  • Hibernate - lazy initialzation

 

JDK Dynamic Proxy

 

JDK Dynamic Proxy?

Java 에서 지원하는 동적(런타임) Proxy 구현 방식이다.
특정 인터페이스들을 구현하는 클래스나 인스턴스를 만드는 기술이다.

 

Reflection API을 사용하여 Target Class의 method를 invoke()를 통해 동작시킨다.

 

 

invoke?

클래스의 이름과 인자 값을 넘겨서 객체의 메서드를 실행시키는 메서드이다.

인자 값을 이용하여 메서드를 실행시키게 된다.

 

 

제약

인터페이스 기반의 Proxy → 모든 Target Class 는 Interface를 implement 하고 있어야 한다.

 

 

JDK Dynamic Proxy 단점

  • Advise 대상이든 아니든 모든 Method Call 마다 reflection API의 invoke를 실시한다.
    • 즉 Method invoke를 우선 진행하고 Advise 유무를 판단한다.

 

JDK Dynamic Proxy 를 사용하는 라이브러리

  • Spring AOP ProxyFactory ( JDK Dynamic Proxy 를 추상화하고 재정의한 Class)
    • Spring Boot 에서는 CGLIB를 기반으로 Spring AOP를 지원한다고 한다.
  • Spring Data JPA RepositoryFactorySupport (BeanClassLoaderAware, BeanFactoryAware)

 

JDK Dynamic Proxy 도 인터페이스 기반의 프록시이므로 이전 코드와 같은 구조를 지니는 인터페이스를 정의한다.

 

TargetObject Class

public interface TargetObject {

    void someMethod(String name);

}

 

TargetObjectImpl Class

public class TargetObjectImpl implements TargetObject {

    @Override
    public void someMethod(String name) {
        System.out.println("Real Subject Do something " + name);
    }
}

 

리플랙션 API에 포함된 Proxy 클래스의 newProxyInstance 를 사용하여 프록시를 구현한다.

 

DynamicProxyClient Class

public class DynamicProxyClient {

    public static void main(String[] args) {
        DynamicProxyClient dynamicProxyClient = new DynamicProxyClient();

        dynamicProxyClient.run("Lob");
    }

    public void run(String name) {
        realObject.someMethod(name);
    }

    TargetObject realObject = (TargetObject) Proxy.newProxyInstance(TargetObject.class.getClassLoader(), new Class[]{TargetObject.class},
            (InvocationHandler) (proxy, method, args) -> {
                TargetObject targetObject = new TargetObjectImpl();

                System.out.println("Before Proxy");
                Object invoke = method.invoke(targetObject, args);
                System.out.println("After Proxy");

                return invoke;
            });
}
Before Proxy
Real Subject Do something Lob
After Proxy

 

 

CGLIB Library를 통한 Dynamic Proxy 구현 방식

 

CGLIB Dynamic Proxy (Spring, Hibernate - embed Library)?

코드 생성 라이브러리(Code Generator Library), 런타임에 동적으로 자바 클래스의 프록시를 생성해주는 기능을 제공한다.

 

 

장점

  • 실제 바이트 코드를 조작하여 JDK Dynamic Proxy 보다 상대적으로 빠르다.
  • 대상 객체가 인터페이스를 가지지 않았을 경우 사용한다.
    • 인터페이스를 가져도 사용할 수 있다. aop:config의 proxy-target-class를 true로 설정.
  • 대상 객체가 정의한 모든 메서드를 프록시 하여야하는 경우 사용한다.

 

제약

  • 버전별 호환성이 좋지 않다. (사용 라이브러리 내부에 내장시켜 제공한다.)
  • final이나 private 같이 상속된 객체에 Overriding을 제공하지 않는다면 해당 행위에 대해서 Aspect를 적용할 수 없다.

 

 

CGLIB Dynamic Proxy 를 사용하는 라이브러리

  • Spring Boot AOP (Proxy)
  • Hibernate

 

TargetObject Class

public class TargetObject {

    void someMethod(String name) {
        System.out.println("Real Subject Do something " + name);
    };

}

 

CglibDynamicProxyClient Class

public class CglibDynamicProxyClient {

    public static void main(String[] args) {
        CglibDynamicProxyClient client = new CglibDynamicProxyClient();
        client.run("Lob");
    }

    public void run(String name) {

        MethodInterceptor methodInterceptor = new MethodInterceptor() {
            final TargetObject targetObject = new TargetObject();

            @Override
            public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                System.out.println("Before Proxy");
                Object invoke = method.invoke(targetObject, args);
                System.out.println("After Proxy");
                return invoke;
            }
        };

        TargetObject targetObject = (TargetObject) Enhancer.create(TargetObject.class, methodInterceptor);

        targetObject.someMethod(name);
    }
}
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by net.sf.cglib.core.ReflectUtils$1 (file:/C:/Users/serrl/.gradle/caches/modules-2/files-2.1/cglib/cglib/3.3.0/c956b9f9708af5901e9cf05701e9b2b1c25027cc/cglib-3.3.0.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of net.sf.cglib.core.ReflectUtils$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
Before Proxy
Real Subject Do something Lob
After Proxy

 

 

예제 Repo

Lob-dev/JavaEE-DesignPattern

 

Lob-dev/JavaEE-DesignPattern

Java EE 디자인 패턴 학습 Repo. Contribute to Lob-dev/JavaEE-DesignPattern development by creating an account on GitHub.

github.com

 

 

참고 자료

외부, 다른 도메인의 API를 통해 데이터를 제공받기 위해 사용할 수 있는 인터페이스를 조사해보았다.

 

RestTemplate?

Spring에서 제공하는 HTTP API 호출 시 사용할 수 있는 인터페이스이다.

멀티스레드 환경에서 안전하며 여러 기능을 지원한다.

 

내부적으로 하나의 요청에 하나의 쓰레드를 생성하여 동작시키는 Java Servlet API를 사용한다.

이는 각각 스레드가 일정량의 메모리와 CPU주기를 사용하고, 응답을 받을 때까지 스레드가 차단되는 동기화 모델이다.

 

비동기 방식의 동작을 제공하는 AsysncRestTemplate 도 있지만, WebClient 라는 인터페이스가 생겨남으로써 최적화된, 최신의 기술을 제공하기에 필요성을 잃어 deprecated 되었고, RestTemplate 은 기존에 사용되었던 프로젝트가 많이 존재하기에 유지보수만을 제공하게 되었다.

→ 스프링 5.0 이상의 프로젝트에서는 WebClient를 사용함을 권장한다.

 

Spring Boot 에서 제공하는 자동 구성 빈 (dataSource, SqlSessionFactory 등의 설정들) 에는 포함되지 않지만, 해당 인터페이스를 인스턴스로 생성하여 제공해줄 수 있는 RestTemplateBuilder을 제공한다.

 

 

기본 사용 방식

@Component
public class ApiConfiguration{

        private final RestTemplate restTemplate;

        @Autowired
        public RestExample(RestTemplateBuilder builder){
                restTemplate = builder.build(); // 아무 설정없는 RestTemplate 설정
        }

        // returnClassType exam : String.class , User.class.... 
        public String findOne() {
                return restTemplate.getForObject(apiUrlPath, returnClassType))
        }
}

 

RestTemplate 를 재정의하기

사용 목적에 따라서 재정의를 하는 방법은 3가지가 있다고 한다.

  • 필요한 순간에 재정의하는 방법

    자동 구성된 RestTemplateBuilder 빈을 주입받아 메서드가 호출되는 시점에 생성하는 방법이다. 이때 빌더를 이용해 추가적인 기능을 정의하여 새로운 인스턴스로 반환한다.

      private final RestTemplate restTemplate;
    
      public MyService(RestTemplateBuilder restTemplateBuilder) {
          this.restTemplate = restTemplateBuilder.build();
      }
    
      public Post someMethod() {
          return restTemplate.getForObject("/{name}/details", Post.class, name);
      }
  • 애플리케이션 전체에 적용되도록 하는 방법

    RestTemplateCustomizer라는 빈을 재정의하여 추가하는 방법이다. RestTemplateBuilder 에도 변경된 내용이 반영되므로 인스턴스를 생성하여 반환하면 된다.

      public class CustomRestTemplateCustomizer implements RestTemplateCustomizer {
    
              @Override
          public void customize(RestTemplate restTemplate) {
                  // Do someThing
              }
      }
    
      @Bean
      public CustomRestTemplateCustomizer customRestTemplateCustomizer() {
          return new CustomRestTemplateCustomizer();
      }
  • RestTemplateBuilder 빈을 재정의하는 방법

    구성의 우선 순위로 인하여 자동 구성으로 되는 RestTemplateBuilder 빈을 사용하지 않고 수동으로 재정의한 것을 사용함으로써 변경된 인스턴스를 반환하게 된다.

 

RestTemplate에서 제공하는 메서드

 

HTTP DELETE

  • delete()

    지정된 URL 에서 특정 Resource를 삭제한다.

      restTemplate.delete("http://example.com/Posts/{postId}", post.getId());
    

     

 

HTTP GET

  • getForObject()

    지정된 URL에 대한 GET을 수행하고 응답이 있는 경우에 해당 Resource를 반환한다.

      // URL에 제공될 PathVarialbe에 대하여서 값을 전달할 수 있다.
      String result = restTemplate.getForObject(
              "http://example.com/Location/{locationId}/Posts/{postId}", String.class
              , "42", "21");
  • getForEntity()

    지정된 URL 에 대한 GET을 수행하여 ResponseEntity를 반환받는다.

      ResponseEntity<String> response = restTemplate.getForEntity(
              "http://example.com/Posts/{postId}", String.class, "1");

 

HTTP HEAD

  • headForHeders()

    URL로 지정된 리소스의 모든 헤더를 검색하고 반환한다. (HttpHeaders Type)

      HttpHeaders httpHeaders = restTemplate.headForHeaders(url);
      // httpHeaders.getContent()...

    HttpHeaders?

    HTTP 요청이나 응답에 포함된 헤더를 나타내는 일종의 데이터 구조(객체)이다.

    문자열 헤더 이름을 문자열 값 목록에 매핑하고 유형에 따른 접근자를 제공한다.

    • getFirst(String) : 주어진 헤더 이름과 관련된 첫 번째 값을 반환한다.

    • add(String, String) : 주어진 헤더 이름과 그에 따른 값을 추가한다. (Map 형식)

    • set(String, String) : 특정 헤더가 가진 값을 해당 문자열 값으로 변경한다.

      → 그외에도 containsKey, addAll, equals, getAccept 등의 편의 메서드를 제공한다.

 

HTTP OPTIONS

  • optionsForAllow()

    지정된 URL에 대한 Allow 헤더의 값을 반환한다.

      Set<HttpMethod> allowedMethod = template.optionsForAllow(
              new URI("http://example.com/Posts" + "/get"));

    Allow Header?

    해당 리소스가 지원하는 메서드의 집합을 나열해주는 헤더이다.

    서버에서 405 Method Not Allowed를 응답할 경우 해당 헤더를 무조건 보내야 한다.

    만약 해당 헤더가 비어있다면 어떠한 요청 메서드이든 간에 허용되지 않음을 의미한다.

 

HTTP POST

  • postForLocation()

    주어진 HttpEntity를 URL에 요청하여 리소스를 만들고 Location 헤더 값을 반환받는다.

    해당 결과 값은 일반적으로 리소스가 저장된 위치(URI)를 제공한다.

      HttpEntity<String> requestEntity = new HttpEntity<>("Lob!");
      URI location = restTemplate.postForLocation(url, request);

    HttpEntity?

    헤더 및 본문으로 구성된 HTTP 요청, 응답 엔티티를 나타내는 인터페이스이다.

    • RequestEntity, ResponseEntity 의 상위 클래스이다. (구현체 들)
  • postForObject()

    주어진 객체를 URL에 요청하여 리소스를 만들고 응답을 해당 리소스로 받는다.

      Post savedPost = restTemplate.postForObject("http://example.com/Posts", 
              post, Post.class);
  • postForEntity()

    주어진 객체를 URL에 요청하여 리소스를 만들고 응답을 ResponseEntity로 받는다.

      ResponseEntity<Post> responsePost = restTemplate.postForEntity(
              "http://example.com/Posts", post, Post.class)

 

HTTP PUT

  • put()

    주어진 요청 객체를 URL으로 PUT 요청을 보내어서 새로운 리소스를 생성한다.

      restTemplate.put("http://example.com/Posts/{postId}", 
              new Post("ChangeTitle", "ChangeContent"), post.getId());

 

Any Method

  • exchange()

    지정된 URI 템플릿에 대하여 HTTP 메서드를 실행한다.

    RequestEntity를 사용하여 요청하며 반환 값은 ResponseEntity로 제공받는다.

      HttpHeaders requestHeaders = new HttpHeaders();
      requestHeaders.add("Accept", MediaType.APPLICATION_JSON_VALUE);
    
      HttpEntity<String> requestEntity = new HttpEntity<>(requestHeaders);
    
      ResponseEntity<Post> = restTemplate.exchange(
              "http://example.com/Posts/{postId}", HttpMethod.GET, 
              requestEntity, Post.class, "10");
  • execute()

    지정된 URI 템플릿에 대하여 HTTP 메서드를 실행한다.

    Request Callback으로 요청을 받고, Response Extractor로 응답을 읽는다.

      Post request = new Post("title","content");
      RequestCallback requestCallback = httpEntityCallback(request);
      execute(url, HttpMethod.PUT, requestCallback, null)

모든 메서드는 RestClientException를 던지게 된다.

 

Traverson

Spring HATEOAS 라이브러리에서 제공하는 하이퍼미디어 API이다.

 

HTTP Method를 지원하지 않고, 하이퍼 링크를 이용하여 다른 URL로 이동하게 된다.

기본적으로 Traverson 인스턴스에 API의 기본 URI와 Accept 헤더를 설정할 수 있다.

Traverson traverson = new Traverson(URI.create("http://example.com/")
        , MediaTypes.HAL_JSON);

 

Traverson에서 제공하는 메서드

  • follow

    Traverson에 Customizing 된 정보로 리소스 간의 단일 관계에 대하여 설정한다.

    결과 값의 타입은 Traverson.TraversalBuilder이다.

      Traverson.TraversalBuilder builder = traverson.follow("self");
    
      // 추가적으로 사용할 수 있는 메서드
      // Map<String, ?> 형식의 Key-Value를 전달할 수 있다.
      Traverson.TraversalBuilder builder = traverson.follow("self")
              .withTemplateParameters(parameters); 
    
      // 응답에 따른 결과를 지정하는 타입 형식으로 마샬링하는 메서드
      String response = traverson.follow("self").withTemplateParameters(parameters)
              .toObject(String.class);
      //  .toObject("$.title"); 속성 값 사용 가능
  • setRestOperations

    사용할 RestOperations를 구성한다. null이 제공된 경우 RestTemplate를 사용한다.

      traverson.setRestOperations(null);

    RestOperations?

    RESTful 작업의 기본적인 작업 단위를 지정한 인터페이스이다.

    주 구현체로는 RestTemplate이 있으며 직접 사용되는 경우는 거의 없지만, 쉽게 모킹 하거나 스터빙을 할 수 있음으로써 테스트의 확장성을 향상하는데 유용하게 사용될 수 있다.

  • setLinkDiscoverers

    사용할 링크 검색기를 설정한다. 기본적으로 단일 HalLink Discoveryer가 등록된다.

      traverson.setLinkDiscoverers(null);

 

WebClient

Spring Flux 라이브러리에서 제공하는 API 호출 인터페이스.

내부적으로 이벤트 루프 방식을 구현한 Reactive Streams API를 사용한다.

 

WebClient를 재정의하기

재정의를 하는 방법은 크게 3가지가 있다고 한다.

  • 필요한 순간에 재정의하기

    WebClient.Builder를 주입받아서 메서드를 호출하는 시점에서 생성한다. 해당 변경사항은 해당 애플리케이션에서 생성되는 모든 클라이언트에 반영되게 된다.

      private final WebClient webClient;
    
      public MyService(WebClient.Builder webClientBuilder) {
          webClient = webClientBuilder.baseUrl("http://example.com").build();
    
              // 혹은
    
              webClient = WebClient.builder()
                  .baseUrl("http://example.com/")
                  .defaultCookie(cookieKey, cookieValue)
                  .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) 
                  .defaultUriVariables(Collections.singletonMap("url", "http://example.com/"))
          .build();        
      }
    
      public Post someMethod() {
          return webClient.get().url("/posts/{postId}", "1")
                              .retrieve().bodyToMono(Post.class);
      }

    동일 시점에서 하나의 빌더로 여러 클라이언트를 생성하려는 경우 builder.clone(); 을 통한 빌더 복제를 고려하여야 한다.

      public MyService(WebClient.Builder webClientBuilder) {
          WebClient.Builder clientBuilder2 = webClientBuilder.clone();
      }
  • WebClientCustomizer 빈을 통한 커스텀

  • WebClient 인스턴스 생성 방식 이용하기

    이 방식의 경우 Auto Configuration이나 WebClientCustomizer가 적용되지 않는다.

      WebClient client = WebClient.create();
    
      WebClient client = WebClient.create("http://example.com/");
  • 추가 :) TCP 커넥션 시 연결 시간에 대한 설정 정보를 커스텀하는 방법 ( TcpClient )

      TcpClient tcpClient = TcpClient
        .create()
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) // 연결 시간 제한을 설정
        .doOnConnected(connection -> {
            connection.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS));
            connection.addHandlerLast(new WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS));
        });
    
      WebClient client = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient)))
        .build();

 

WebClient에서 제공하는 메서드

 

Any Method

  • method(HttpMethod method)

      WebClient webClient = WebClient.create("http://example.com/");
    
      Post post = webClient.method(HttpMethod.GET)
              .url("/posts")
              .retrieve()
              .bodyToMono(Post.class);
  • mutate()

    해당 WebClient 인스턴스의 속성을 변경(정의)하는 빌더를 반환한다.

  • retrieve()

    앞서 체이닝 된 정보대로 HTTP 요청을 수행하고 응답 본문을 가져오게 된다.

  • exchange()

    응답 상태 및 헤더를 가진 클라이언트의 응답 엔티티를 반환받는다.

    해당 엔티티에서 응답 본문을 가져올 수 있다.

 

HTTP GET

  • get()

    요청을 통해 단일 리소스나 여러 건의 리소스를 가져올 수 있다.

    • bodyToFlux(Obejct.class) : 여러건의 리소스 반환

    • bodyToMono(Object.class) : 단건 리소스 반환

      WebClient webClient = WebClient.create("http://example.com/");
      
      public Mono<Post> findById(Long id) {
            return webClient.get().url("/posts/"+ id)
                    .retrieve().bodyToMono(Post.class);
      }
      
      public Flux<Post> findAll() {
            return webClient.get()
                    .uri("/posts/")
                    .retrieve()
                    .bodyToFlux(Post.class);
      }

 

HTTP POST

  • post()

    일반적으로 요청을 통해 리소스를 만드는 데 사용된다.

      webClient.post()
              .url("/posts")
              .body(Mono.just(entity), Post.class)
              .retrieve()
              .bodyToMono(Post.class);
    
      Post savedPost = Mono.just(entity, Post.class);

 

HTTP DELETE

  • delete()

    일반적으로 요청을 통해 리소스를 삭제하는 데 사용된다.

      WebClient webClient = WebClient.create("http://example.com/");
    
      return webClient.delete()
              .url("/post/" + "1")
              .retrieve()
              .bodyToMono(Void.class);

 

HTTP HEAD

  • head()

    요청을 통해 해당 URI의 지원 헤더를 응답받는 데 사용한다.

 

HTTP PUT

  • put()

    요청을 통해 하나의 리소스 정보를 업데이트하는 데 사용된다.

      WebClient webClient = WebClient.create("http://example.com/");
    
      return webClient
              .put()
              .url("/posts/" + "1")
              .retrieve()
              .bodyToMono(Void.class);

 

HTTP OPTIONS

  • options(). options()

    요청을 통해 지원하는 메서드 정보들을 응답받는다.

 

HTTP PATCH

  • patch()

    요청을 통해 리소스의 일부분을 업데이트하는 데 사용된다.

      WebClient webClient = WebClient.create("http://example.com/");
    
      Post modifyEntity = webClient
              .options()
              .uri("/posts")
              .retrieve()
              .bodyToMono(Post.class);

 

RestTemplate vs WebClient

 

RestTemplate

앞서 말한 것처럼 RestTemplate는 내부적으로 하나의 요청에 하나의 스레드를 생성하여 동작시키는 요청당 스레드 모델을 구현한 Java Servlet API를 사용한다.

 

각각 스레드가 일정량의 메모리와 CPU주기를 사용하고, 응답을 받을 때까지 스레드가 차단되게 되는데, 이는 요청마다 스레드를 생성하기에 많은 스레드를 생성하여 스레드 풀을 소모하거나 사용 가능한 모든 메모리를 차지할 수 있으며 빈번한 CPU 콘텍스트 (스레드) 전환으로 인해 성능 저하가 발생할 수 있다.  (요청 수에 연관되어 성능 저하가 발생한다.)

 

WebClient

각 이벤트에 대해 Task를 만들고 대기열에 넣은 뒤 적절한 응답이 있는 경우에만 실행하게 된다. 즉 이벤트 루프 방식을 구현한 Reactive Streams API를 사용한다.

→ 응답이 있는 경우에만 실행 스레드가 동작하게 된다.

 

해당 방식은 RestTemplate에 비해 적은 스레드와 리소스를 사용하면서 동시에 더 많은 로직을 처리할 수 있다. (요청 수에 관계없이 일정한 성능을 제공하는 것에 의의를 둔다.)

 

선택?

상황에 따라 다를 수 있지만 들어오는 요청의 수가 많다고 가정하면 WebClient, 비동기 방식을 사용하는 것이 일반적으로 좋은 선택이다. (필요한 만큼만의 스레드, 리소스를 사용하기 때문이다.)

→ 대부분 이런 상황일 수 있기에 WebClient를 권장하는 것 같다.

 

참고 자료

물리 계층의 역할과 랜 카드의 구조

 

전기 신호

0과 1로 이루어진 이진 데이터를 전기 신호로 변환하기 위하여서 사용되는 계층은 물리 계층이다.

 

아날로그 신호

물결 모양을 그리는 신호를 말하며 전화 회선이나 라디오 방송에 사용되는 신호이다.

 

랜 카드

송신하여야할 데이터를 전기 신호로 변환하며, 전기 데이터를 이진 데이터로 변환하는 장치이다.

 

케이블의 종류와 구조

 

전송 매체

네트워크 구조에서 전기로 변환된 데이터가 흐르는 물리적인 선로를 말한다.

 

트위스트 페어 케이블 ( LAN Cable )

선로 내부에 가닥들을 꼬아놓은 것을 말한다.

 

UTP 케이블

구리 선 여덟 개를 두 개씩 꼬아 만든 네 쌍의 전선으로 실드로 보호되어 있지 않은 케이블이다.

 

실드

금속 호일이나 금속의 매듭과 같은 것으로 외부에서 발생하는 노이즈를 막는 역할을 한다.

 

노이즈

케이블에 전기 신호가 흐를 때 발생하는 현상으로 데이터 흐름에 영향을 준다.

 

STP 케이블

구리 선 두개를 꼬아 만들어낸 전선을 실드로 보호하는 케이블이다.

 

다이렉트 케이블

구리 선 여덟 개를 같은 순서로 커넥터에 연결한 케이블이다.

 

크로스 케이블

구리 선 여덟 개 중 한쪽 커넥터의 1번과 2번에 연결되는 구리 선을 3번과 6번에 연결한 케이블이다.

 

리피터, 허브의 구조

 

리피터

일그러진 전기 신호된 신호를 복원 (정형)하고, 들어오는 신호를 증폭하는 네트워크 중계 장비이다.

 

허브

실제로 통신하는 통로 (포트)를 여러 개 가지고 있는 네트워크 장비를 말한다.

리피터와 마찬가지로 전기 신호를 정형하고 증폭하는 기능을 한다.

 

여러 개의 포트를 가짐으로 컴퓨터 여러 대와 통신할 수 있다.

  • 하지만 특정 포트로 데이터를 받게 되면 모든 포트에게 같은 데이터를 전송한다.

 

데이터 링크 계층의 역할과 이더넷

 

데이터 링크 계층

네트워크 장비 간에 신호를 주고받는 규칙(일반적으로 이더넷)을 정하는 계층이다.

네트워크 기기 간에 데이터를 전송하고 물리 주소를 결정한다.

 

이더넷

사무실이나 가정에서 일반적으로 사용되는 랜과 관련하여 가장 많이 활용되는 기술 규격이다.

허브나 스위치 등과 연결된 컴퓨터들이 데이터를 통신할 때 사용한다.

 

충돌

데이터를 한 번에 하나만 전송할 수 있는 채널에서 두 개 이상의 전송 장치가 동시에 패킷을 보냈을 경우 발생하는 현상이다.

 

충돌 도메인

충돌이 발생하였을 경우 그 영향이 미치는 범위를 말한다.

허브에서 충돌이 발생한다면, 그 허브를 통해 연결된 모든 단말기가 충돌 도메인이 된다.

 

CSMA/CD (Carrier Sense Multiple Access with Collision Detection)

이더넷에서 사용하는 기술의 약어를 말하며, 충돌을 방지하기 위해 데이터를 보내는 시점을 늦추는 것을 말한다.

  • CS : 데이터를 보내려고 하는 컴퓨터가 케이블에 신호가 흐르고 있는지 확인하여야 하는 규칙
  • MA : 케이블에 데이터가 흐르고 있지 않다면 데이터를 보낼 수 있는 규칙
  • CD : 충돌이 발생하고 있는지를 확인한다는 규칙

 

MAC 주소의 구조

 

MAC 주소

랜 카드가 제조될 당시에 새겨지는 주소로 물리 주소라고도 부른다.

각각의 기기가 유일한 번호로 할당되어 있기에 특정한 하나의 기기만을 식별할 수 있다.

 

MAC 주소는 48 Bit 로 이루어져 있다.

  • 전면부 24 Bit : 랜 카드를 만든 제조사의 번호
  • 후면부 24 Bit : 제조사가 랜 카드에 붙인 일련번호

TCP/IP 모델의 네트워크 계층 (OSI의 데이터 링크 계층)에서는 이더넷 헤더와 트레일러를 붙이게 되는데 이때 이더넷 헤더는 MAC 주소(6byte), 출발지 MAC 주소(6byte), 유형(2byte)으로 이루어진다.

 

유형? (16진수 데이터)

이더넷으로 전송되는 상위 계층의 프로토콜 종류를 나타낸다.

  • 0800 : IPv4
  • 0806 : ARP
  • 8035 : RARP
  • 814C : SNMP over Ethernet
  • 86DD : IPv6

FCS ( Frame Check Sequence, 트레일러)

데이터 전송 도중에 오류가 발생하는지 확인하는 용도로 사용된다.

이더넷 헤더와 트레일러가 추가된 상태의 데이터를 프레임이라고 부른다.

 

스위치의 구조

 

스위치 (L2 Switch, Switching Hub)

네트워크 계층(데이터 링크)에서 동작하는 네트워크 장비를 말한다.

랜을 구성할 때 사용하는 단말기 간 스위칭 기능이 있는 장비로써, 단말기에서 특정한 다른 단말기로 패킷을 보내는 기능을 제공함으로써 통신 효율을 향상시킨다.

 

MAC 주소 테이블 (MAC address table)

스위치의 포트 번호와 해당 포트에 연결되어 있는 컴퓨터의 MAC 주소가 등록되는 데이터베이스.

 

단말기가 프레임을 전송하면 MAC 주소 테이블을 확인한 후 없는 경우 등록하는 절차를 가진다.

→ 이를 MAC 주소 학습 기능이라고 부른다.

 

플러딩(flooding)

보내야 할 단말기의 주소 정보가 등록되지 않은 경우에는 연결된 포트로 데이터를 전송하는 것을 말한다.

 

MAC 주소 필터링

보내야할 단말기의 주소 정보가 등록된 경우 해당 단말기에게만 프레임을 전송하게 되는 것을 말한다.

 

ARP

네트워크 계층에서 IP 주소를 MAC 주소로 변환하기 위하여 사용되는 프로토콜이다.

 

ARP 요청

이더넷 프레임을 전송하려면 목적지의 MAC 주소가 필요하게 되는데, 해당 주소를 알지 못할 경우, 네트워크에 IP 정보를 가지고 브로드 캐스트를 진행하게 됨을 말한다.

 

ARP 응답

ARP 요청 이후 해당 IP 정보를 가지지 않은 단말기들은 모두 요청을 무시하며, 해당 IP 정보를 가진 단말기만이 MAC

주소를 응답으로 보내게 된다. 데이터를 보내는 단말기는 ARP 응답으로 받은 MAC 주소를 이더넷 헤더에 추가함으로써 프레임을 만들고 전송할 수 있게 된다.

 

ARP 테이블

추가적으로 받은 MAC 주소를 IP 주소와 매핑하여, 메모리에 보관하게 되는데 이를 ARP 테이블이라 한다. 이후에는 해당 테이블 정보를 이용하여 프레임을 만들고 전송한다.

 

만약 다른 단말기의 IP 주소가 변경될 경우 MAC 주소도 함께 변경됨으로 데이터를 영구적으로 보관하지 않고, 보관 기간을 ARP 캐시를 이용하여 관리한다. (기간 만료 시에는 ARP 요청을 보낸다)

 

데이터가 케이블에서 충돌하지 않는 구조

 

전이중 통신

데이터의 송수신이 동시에 발생하는 통신 방식을 말한다.

서로 다른 회선이나 주파수를 이용하여 데이터 신호가 충돌되는 상황을 방지한다.

L2 Switch로 통신 중계, 단말기 간의 크로스 케이블을 이용 등 이런 경우 전이중 통신이 가능하다.

 

반이중 통신

데이터의 송수신이 번갈아가면서 통신하는 방식을 말한다.

허브를 통해 연결한 경우 반이중 통신이라고 말하며, 충돌이 발생할 위험이 있다.

 

이더넷의 종류와 특징 - 스킵.

'Book! > 모두의 네트워크' 카테고리의 다른 글

2장 네트워크의 기본 규칙  (0) 2020.12.22
1장 네트워크 첫걸음  (0) 2020.12.21

프로토콜 Protocol

네트워크에서 통신하기 위한 일종의 규약, 규칙을 말한다.

데이터를 전송하는 과정에 있어서 규정된 독립적인 규칙을 거쳐야만 한다.

 

OSI 모델과 TCP/IP 모델

OSI 모델

네트워크 구조에 대한 표준 규격 중 하나로 컴퓨터 내부에서 벌어지는 일들을 각각의 계층으로 분리한 모델을 말한다.

  • 응용, 표현, 세션, 전송, 네트워크, 데이터 링크, 물리 계층

Application Layer : 응용 계층 (7)

  • 이메일, 파일 전송, 웹 사이트 조회 등 Application과 관련된 서비스를 제공한다.

Presentation Layer : 표현 계층 (6)

  • 문자 코드, 압축, 암호화 등의 데이터를 변환한다.

Session Layer : 세션 계층 (5)

  • 세션 체결, 통신 방식을 결정한다.

Transport Layer : 전송 계층 (4)

  • 신뢰할 수 있는 통신을 구현한다.

Network Layer : 네트워크 계층 (3)

  • 다른 네트워크와 통신하기 위한 경로 설정 및 논리 주소를 경정한다.

Data Link Layer : 데이터 링크 계층 (2)

  • 네트워크 기기 간의 데이터 전송 및 물리 주소를 결정한다.

Physical Layer : 물리 계층 (1)

  • 시스템 간의 물리적인 연결과 전기 신호를 변환 및 제어한다.

 

통신 흐름

 

데이터 송신 측 7~1 Layer → 1 Layer ~ 7

 

ISO

네트워크에 대한 표준 규격을 제정하는 기관 중 하나, 국제표준화기구라고 한다.

 

TCP / IP 모델

7 계층 중 데이터 전송하는 과정을 4 계층으로 단순화하여 표현한 모델이다.

  • 응용 계층 (4)
  • 전송 계층 (3)
  • 인터넷 계층 (2)
  • 네트워크 접속 계층 (1)

 

캡슐화와 역캡슐화

 

헤더

데이터 전송을 위해서는 데이터 앞부분에 필요한 정보를 부착하여야 하는데. 이것을 헤더라 한다.

헤더에는 데이터를 전달받을 상대방에 대한 정보가 포함되어 있다.

 

캡슐화

앞서 말한 헤더라는 것을 데이터 앞쪽에 붙여나가는 것을 캡슐화라고 한다.

 

역 캡슐화

데이터를 받는 측에서는 캡슐화와 반대로 붙어있는 헤더를 하나씩 제거해나간다.

캡슐화, 역 캡슐화 흐름

  • 응용 계층에서 데이터를 전송 계층으로 내려보낸다.
  • 전송 계층에서 헤더를 부착한다.
  • 네트워크 계층에서 헤더를 부착한다.
  • 데이터 링크 계층에서도 헤더를 부착하고 트레일러를 뒤에 붙인 후 전기 신호로 전송한다.
  • 수신 측에서는 역순대로 제거해나간다.

 

트레일러

  • 데이터를 전달할 때 데이터의 마지막에 추가하는 정보를 말한다.

 

VPN (Virtual Private Network)

가상의 통신 터널을 만들어서 기업 본사나 지사와 같은 거점 간을 연결하여 통신하거나 외부에서 인터넷을 통해 사내 망에 접속할 수 있게끔 지원하는 망을 말한다.

  • Internet VPN
    • 거점 간 접속 방식 : IPsec이라는 암호 기술 프로토콜을 사용하여 접속한다.
    • 원격 접속 방식 : 외부 컴퓨터와 사내망을 연결하기 위해 암호화된 통신로를 사용한다
  • IP-VPN
    • MPLS라는 기술을 사용하여 인터넷 망이 아닌 통신 사업자 전용 폐쇄망을 사용한다.
    • 폐쇄망을 사용함으로 제삼자의 해킹이나 데이터 변조의 위험이 없다. (암호화 기능 필요 X)

'Book! > 모두의 네트워크' 카테고리의 다른 글

3장, 4장 정리  (0) 2020.12.23
1장 네트워크 첫걸음  (0) 2020.12.21

자바 상속의 특징

 

OOP 이전의 방식

이전 패러다임에서 코드를 재사용하는 방법은 복사한 후 로직 인자에 맞게 수정하는 방식이었다.

이후 기존 로직을 변경해야 할 때, 두 개의 코드다 변경해야 되는 것도 문제고, 하나의 코드를 수정하였다고 하여서 다른 코드를 그렇게 수정하면 된다는 보장이 존재하지 않는다.

 

즉 유지보수에 취약한 코드가 작성, 양산되는 것이다.

 

새롭게 등장한 OOP 패러다임에서는 이러한 부분을 해결하기 위해 도입한 방식이 상속이다.

 

 

상속이란?

기반이 되는 상위 클래스의 특성을 하위 클래스에게 적용하고, 거기에 더해 필요한 특성을 추가, 확장하는 방식을 말한다. 상속의 목적은 기존 기능의 확장과 코드의 재사용이다.

 

 

상위 클래스?

어떠한 속성과 코드를 (하위 클래스들에게) 제공하는 클래스를 말한다.

 

 

하위 클래스?

상위 클래스를 상속받는 클래스를 말한다.

 

 

상속의 장점

하위 클래스에 상위 클래스를 extend만 하여도 코드가 자동적으로 재사용된다는 것이며, 확장성을 위해 변경하여야 할 부분의 로직만 overiding을 사용하여 재정의도 가능하다.

 

 

상속 시 고려해야 할 것, 상속의 단점

상속을 사용하여 코드를 재사용하는 경우에는 기존 상위 클래스가 어떻게 작성되었는지, 어떤 동작을 해야 되는 것인지를 정확히 고려하고 진행해야 한다.

 

그렇지 않고 상속을 과용하게 되면 위에서 고려하지 않은 다른 동작을 하위 클래스가 구현하게 되고, 상속의 특성상 상위 클래스와 하위 클래스가 강한 결합상태로 묶이기 때문에, 추후의 코드의 수정이 어려워짐으로써 상위 클래스의 변경 여파가 모든 하위 클래스에 전파될 수 있는 상황이 발생한다.

 

이를 취약한 기반 클래스 문제라고 한다.

 

 

상속을 사용하는 경우

  • 상위 클래스와 필요한 하위 클래스에 대하여서 잘 알고 있는 경우
  • 프로젝트 구조 자체가 상속을 위해 설계된 경우
  • is - a 관계가 명확한 경우 (동물 → 포유류 → 고래 등, 상위 분류와 하위분류가 명확한 경우)

 

자바의 상속 구조

 

단일 상속 구조

public class 상위 클래스 {

}

public class 하위 클래스 extends 상위 클래스 {

}

 

 

다중 레밸 상속 구조

public class 최상위 클래스 {

}

public class 상위 클래스 extends 최상위 클래스 {

}

public class 하위 클래스 extends 상위 클래스 {

}

 

 

계층적 상속 구조

public class 상위 클래스 {

}

public class 하위 클래스 A extends 상위 클래스 {

}

public class 하위 클래스 B extends 상위 클래스 {

}

 

자바는 다중 상속을 허용하지 않는다.

다중 상속을 허용하지 않는 이유는 하위 클래스의 코드를 복잡하게 만들어 프로그램을 취약하게 만들고, 버그를 유발할 수 있으며, 유지 보수하기 어렵게 만들기 때문이라고 한다.

 

해당 제약을 우회하는 방법으로는 인터페이스를 이용한 다중 상속이 있다.

public class 상위 클래스 {

}

public interface 인터페이스 {

}

public class 하위 클래스 extends 상위 클래스 implements 인터페이스 {

}

 

 

다중 상속 문제 : The Deadly Diamond of Death

이러한 구조를 가지고 있을 경우에 인터페이스 간의 동일한 이름의 메서드가 존재한다면, 어떤 메서드를 사용할지 모르게 되므로 컴파일 에러가 발생하게 된다.

 

이러한 에러를 해결하기 위하여선 해당 메서드를 하위 클래스에서 overriding 할 수밖에 없다.

 

 

살짝 다른 경우!

이러한 경우에는 클래스가 인터페이스에 비해서 우선순위를 가진다.

(동일한 메서드 시그니처가 존재하는 경우 클래스의 메서드를 먼저 호출한다. ) 

 

 

상속시 메모리 구조

 

이러한 코드를 작성하였다면?

public static void main(String[] args) {
        Dog dog = new Dog();
        dog.name = "푸들";
        dog.habit = "멍멍";
        dog.showHabit();
        dog.showName();


        Animal animal = new Dog();
        animal.name = "리트리버";
        animal.showName();
}

 

메모리 상으로 이러한 구조를 가지게 된다.

 

Super 키워드

상위 클래스로부터 상속받은 필드나 메서드를 하위 클래스에서 참조하는 데 사용하는 참조 변수이다.

public class A {
    protected String property = "properties";

    public void printProperties() {
        System.out.println("A.printProperties");
        System.out.println(property);
    }
}

public class B extends A {
    protected String property = "properties of Sub Class";

    @Override
    public void printProperties() {
        super.printProperties();
        System.out.println("B.printProperties");
        System.out.println(super.property);
        System.out.println(property);
    }
}

 

super() 메서드

부모 클래스의 생성자를 호출할 때 사용되는 메서드이다.

상속 구조 관계에서 하위 클래스를 생성한 경우 내부적으로 super를 호출하여 상위 클래스부터 생성한다.

public class A {
        public String name;
        public Long age;
        public A() {
            System.out.println("A.A constructor");
        }

        public A(String name) {
            this.name = name;
        }

        public A(String name, Long age) {
            this.name = name;
            this.age = age;
        }
    }

    public class B extends A {

        public B() {
            // super() 내부적으로 동작한다.
            System.out.println("B.B constructor");
        }

                public B(String name, Long age) {
            super(name, age);
            System.out.println("B.B args constructor");
        }
    }

        // 실행 함수
    public void run() {
        B b = new B();
                B b1 = new B("name", 20L);
    }

출력 결과

A.A constructor
B.B constructor
A.A args constructor
B.B args constructor

 

메서드 오버 라이딩

상속 구조 관계에서 상위 클래스의 메서드를 하위 클래스에서 다시 정의하는 것을 말한다.

상위 클래스에서 선언된 메서드 시그니처와 동일하게 작성하여야 한다. (메서드 명, 인자 + 반환 값)

→ 리턴 값을 다르게 설정할 경우 attempting to use incompatible return type 컴파일 에러가 발생

public class SuperClass {

    public SuperClass() {
        System.out.println("SuperClass constructor");
    }

    public void showPrint() {
        System.out.println("SuperClass.showPrint");
    }
}

public class SubClass extends SuperClass{

    public SubClass() {
        System.out.println("SubClass constructor");
    }

    @Override
    public void showPrint() {
        System.out.println("SubClass.showPrint");
    }
}

@Test
public void extendTest(){
    SuperClass superClass = new SubClass();
    superClass.showPrint(); // 하위 클래스의 메서드가 호출된다.
}

출력 결과

SuperClass constructor
SubClass constructor
SubClass.showPrint

 

다이내믹 메서드 디스패치

오버 라이딩된 메서드들이 있는 경우 어떤 것을 호출할지를 런타임에서 결정하는 것을 말한다.

해당 메소드 참조에 의해 호출될 때 객체 유형에 따라서 실행할 메서드를 결정하게 된다.

 

자바는 묵시적으로 메서드를 호출한 객체를 인자로 넘기기 때문에 메서드 내부에서 호출 객체를 참조할 수 있다.

-> 이는 런타임에서 호출하는 객체도 결정된 것을 말한다.

public class SuperClass {

    public SuperClass() {
        System.out.println("SuperClass constructor");
    }

    public void showPrint() {
        System.out.println("SuperClass.showPrint");
    }
}

public class SubClass extends SuperClass{

    public SubClass() {
        System.out.println("SubClass constructor");
    }

    @Override
    public void showPrint() {
        System.out.println("SubClass.showPrint");
    }
}

public class SubClazz extends SuperClass{

    public SubClazz() {
        System.out.println("SubClazz constructor");
    }

    @Override
    public void showPrint() {
        System.out.println("SubClazz.showPrint");
    }
}

@Test
public void extendTest(){
    SuperClass clazz = new SubClazz();
    clazz.showPrint();
}

출력 결과

SuperClass constructor
SubClazz constructor
notefive.oop.SubClazz@eafc191
SubClazz.showPrint

 

추상 클래스

하나의 추상 메서드를 지니는 클래스로 구현할 때에는 유사한 여러 클래스의 동일한 부분을 잘라내어 추상화하고, 공통화한 클래스를 말한다.

 

추상 클래스는 주로 클래스의 기반 뼈대나 공통 처리(재사용)에 사용한다.

 

추상 클래스의 장점

  • 유사한 동작을 가진 클래스들의 코드를 공통적으로 모아 추상화 하기에 하나의 추상 클래스에서 해당 코드를 관리할 수 있습니다.
  • 기능 확장 시 유사한 코드를 더 작성하지 않고 상위 클래스를 상속 받음으로써 간단하게 확장할 수 있습니다.

 

추상 클래스의 단점

  • 추상 클래스를 도입하고 상속을 진행하다 보면 전체 클래스의 수가 많아지게 된다.
  • 상속 계층이 깊어질수록 해당 부분을 개발하지 않고 하위 클래스를 사용하는 개발자는 로직의 이해를 위해 해당 계층의 상위부터 동작을 이해하여야 한다. (유지 보수가 어려워진다.)

 

Final 키워드

final : 해당 지정자가 작성된 것에 대해 상속이나 변경을 금지한다는 의미이다.

  • 객체 변수 : 그 필드의 값이 변경되는 것을 금지한다.

    → 값을 해당 필드에서 초기화하지 않는다면, 생성자를 통한 초기화가 강제된다.

      private final String name = "name";
    
      혹은
    
      private final String name;
    
      public Example(String name) {
              this.name = name;
      }
  • 객체 메서드 : 해당 클래스 타입을 상속받는 서브, 하위 클래스에서 오버라이드를 금지한다.

      public class A {
    
          public final void someMethod() {
              // Do something...
              System.out.println("super class!");
          }
      }
    
      public class B extends A {
    
                      // 컴파일 에러가 발생한다.
                      // cannot override someMethod() ... overridden method is final
                      @Override 
                      public final void someMethod() {
              }
      }
    
          public void run() {
              B b = new B();
              b.someMethod();
          }
  • 클래스 자신 : 해당 클래스의 상속을 금지한다. (String, Integer.... 등)

      public final class A {
    
          public final void someMethod() {
              // Do something...
              System.out.println("super class!");
          }
      }
    
      // 컴파일 에러가 발생한다.
      // cannot inherit from final
      public class B extends A { 
      }
    
          public void run() {
              B b = new B();
              b.someMethod();
          }
      }

 

Object 클래스

최상위 클래스이며, 모든 클래스는 묵시적으로 Object 클래스를 상속받게 된다.

  • equals(), toString(), clone() 등 유틸 메서드
  • wait(), notify(), notifyAll() 등 스레드 관련 메서드
  • finalize() : GC 전 리소스를 반환하기 위한 메서드
  • hashcode() : 해당 객체의 참조 값을 나타내는 메서드

들을 제공한다.

 

equals, toString, clone, getClass

public static void main(String[] args) throws CloneNotSupportedException {

    ObjectExample example = new ObjectExample();

    System.out.println(example.toString());

    System.out.println(example.equals(example));

    System.out.println(example.hashCode());

    System.out.println(example.getClass());

}

출력 결과

notefive.anonymous.ObjectExample@43a25848
true
1134712904
class notefive.anonymous.ObjectExample

 

스레드 관련 메서드

 

wait

  • 해당 Object를 선점하고 있다가 접근 권한을 다른 쓰레드에게 넘기고 notify, notifyAll 이 호출될 때까지 해당 쓰레드를 대기하게끔 설정하는 메서드이다.
    • 스레드는 Wait Set에 들어가게 된다.

notify

  • 해당 Object의 선점을 위해 Wait Set 에 대기중인 하나의 쓰레드를 실행 대기 상태로 만든다.
    • Entry Set의 쓰레드들과 같이 경합에 참여한다.

 

notifyAll

  • 해당 Obejct의 선점을 위해 Wait Set 에 대기중인 모든 쓰레드를 실행 대기 상태로 만든다.
    • notify와 동일한 경합상태가 발생한다.

 

참고자료

'Live Study' 카테고리의 다른 글

Live Study_Week 08. 인터페이스  (0) 2021.01.05
Live Study_Week 07. 패키지  (0) 2020.12.28
Live Study_Week 05. 클래스  (0) 2020.12.15
Live Study_Week 04. 제어문 + 과제  (0) 2020.12.01
Live Study_Week 03. 연산자  (0) 2020.11.24

네트워크의 구조

디바이스(Node)들이 연결되어 통신을 통하여 상호 작용하는 링크들의 구성을 네트워크라고 한다.

해당 네트워크의 목적에 따라서 여러 명칭으로 불리게 된다.

 

Packet

Network를 통하여 전송되는 데이터의 단위를 말한다.

하나의 큰 데이터를 보내는 것은 네트워크의 대역폭을 많이 점유함으로 흐름을 막을 위험이 있다.

 

네트워크의 대역폭?

일정시간 동안 네트워크로 전송할 수 있는 비트 수에 의해 결정된다.

 

인터넷

TCP/IP 프로토콜을 사용하는 세계 최대 규모의 네트워크를 말한다.

  • 서로 연결하여 정보를 교환할 수 있도록 하나의 거대한 컴퓨터 통신망이다.

 

추가 내용 (내가 추가한 요소)

 

네트워크의 망 구성 방식

네트워크의 구조를 Network topology라고 하며, 공통 구조들을 종합하여 어떤 형이라 명칭 한다.

  • Bus Topology
  • Star Topology
  • Ring Topology
  • Tree Topology

 

네트워크 구성 방식을 선택하는 요소

  • 설치 비용 : 인프라를 구성할 때 중요한 요소 중 하나, 케이블 길이, 노드 간 거리, 서버 위치 등
  • 유연성 : 네트워크 설정의 재구성, Device (Node)의 추가 및 재배치, 제거에 대한 것
  • 신뢰성 : 노드와 케이블의 장애로 인한 전체 네트워크 영향, 가동 중지 시간의 최소화에 대한 것
  • 확장성 : 새로운 장치, 노드의 쉬운 확장, 확장으로 인한 부하를 수용하는 것
  • 설치 용이성 : 하드웨어, 소프트웨어 및 기술 인력 측면에서 쉽게 설치할 수 있는 것
  • 유지 보수 용이성 : 네트워크 문제 해결 및 유지 보수하기 쉬운 것

 

Bus Topology?

하나의 선형 전송 케이블에 여러 디바이스가 연결된 형태를 가진다.

  • 케이블을 통해 양방향으로 데이터 패킷을 전송한다.

장점

  • 간편한 설치 및 유지
  • 쉽게 확장 가능
  • 전송 라인으로 매우 안정적

단점

  • 단일 제어 지점이 없기 때문에 문제 해결이 어렵다.
  • 한 노드의 결함으로 전체 네트워크가 중단될 수 있다.

 

Star Topology?

각각의 Device 들을 서버(중앙 Node)에 개별적으로 연결하는 구조를 가진다.

  • 각 노드 간의 데이터 교환은 서버를 통해 이루어진다.

    → 노드로부터 수신된 데이터를 서버에서 처리하고 전달할 노드에게 전송한다.

    → 정보 및 음성 네트워크에서 가장 널리 사용되는 Topology이다.

장점

  • 한 노드의 장애가 전체 네트워크에게 영향을 주지 않는다.
  • 서버에서 장애가 발생한 노드를 감지할 수 있음으로써 상황을 해결하기가 쉽다.

단점

  • 각 노드를 서버에 연결하기 위해 긴 케이블이 필요할 수 있다.
  • 서버의 장애가 전체 네트워크에 영향을 끼친다.

 

Ring Topology?

한 노드가 데이터를 전송할 때 인접한 노드를 통해 전달하는 구조를 가진다.

  • 데이터가 각각의 노드를 통과하여 대상 노드까지 전달된다.

장점

  • 두 노드를 연결하기 위하여선 작은 케이블 세그먼트가 필요하다.
  • 데이터가 한 방향으로만 이동함으로 광섬유를 사용함에 있어서 이상적인 구조이다.
  • 매우 빠른 전송이 가능하다.

단점

  • 단일 노드에 장애가 발생하면 전체 네트워크에 영향을 끼친다.
  • 장애가 발생한 노드를 파악하기 위해서는 모든 노드를 검사하여야 한다.
  • 다른 노드들을 유지하면서 새로운 노드를 추가하거나 제거하기가 어렵다.

 

Tree Topology?

Star Topology와 Bus Topology를 통합한 형태, Layer Topology라고도 명칭 한다.

 

장점

  • 기존 네트워크를 쉽게 확장할 수 있다.
  • 개별 노드에 대한 Point-To-Point 배선으로 설치 및 유지 보수가 더 쉽습니다.
  • 임시 네트워크에 적합하다.

단점

  • 해당 Topology를 구현함에 있어서 필요한 전문적인 지식이 필요하다.
  • 백본 케이블의 고장으로 전체 네트워크가 중단된다.
  • 안전하지 않은 네트워크 구조이다.
  • 대규모 네트워크에 대한 유지 관리가 어렵다.

 

정보의 양을 나타내는 단위

 

Digital Data?

  • 0과 1의 집합 (Bit)로 이루어진 Data를 말한다.

Byte

  • Bit 8개가 모여서 만들어진 단위를 말한다. 

ASCII

알파벳, 기호, 숫자 등을 다룰 수 있는 기본적인 문자 코드이다.

 

네트워크 상의 데이터 전송

비트 정보를 전기 신호로 변환하기 때문에 실제로는 해당 신호를 통해 통신하게 된다.

 

LAN과 WAN

 

LAN (Local Area Network)

가정이나 빌딩 안에 사무실 같은 지리적으로 제한된 영역에서 이루어지는 Network.

 

WAN (Wide Area Network )

LAN 보다 넓은 범위에 구축된 Network.

 

ISP (Internet Service Provider)

인터넷 서비스를 제공하는 업체들을 칭하는 명칭이다.

 

가정에서의 LAN 구성

 

유선, 무선

  • 유선은 랜 케이블을 통해 연결된 것을 말한다.
  • 무선은 랜 케이블이 아닌 블루투스, WIFI 를 통한 연결을 말한다.

 

회사에서의 LAN 구성

 

DMZ

외부에 공개하기 위한 Network를 말한다.

  • Web, Mail, DNS 서버 등을 공개하게 된다.

 

서버를 운영하기 위한 선택

  • 데이터 센터 (: 사내에서 서버 실을 만들고 관리 )
  • 클라우드 (: AWS, GCP, Azure )

'Book! > 모두의 네트워크' 카테고리의 다른 글

3장, 4장 정리  (0) 2020.12.23
2장 네트워크의 기본 규칙  (0) 2020.12.22

 

클래스란 무엇일까?

클래스는 어떠한 객체들에 대한 분류이다.

  • 분류, 집합, 같은 속성과 기능을 가진 객체들을 총칭하는 개념이다.
  • 클래스는 해당 객체가 무엇인지 판단할 수 있는 일종의 식별 타입이 된다.

 

클래스의 구성요소

  • 변수 : 클래스의 Scope = { } 안에서 존재하는 변수를 말한다.

    • 객체 변수 : 접근 제어자와 변수 타입, 변수 명을 가지는 일반적인 상태 변수를 말한다.

      • 해당 변수는 클래스 정보에서 초기화되지 않고, 해당 타입을 가지는, 상속받은 객체가 생성되었을 때 Scope에 맞게 가시 된다. (공유된다)
    • 클래스 변수 : 위의 요소를 가지면서, static 이 작성된 상태 변수를 말한다.

      • 클래스가 로드되는 시점Class 정보가 저장되는 영역에서 해당 정보가 등록, 초기화 되기 때문에 이러한 명칭을 가진다. (Perm Gen, Meta space)
      • 모든 영역에서 가시되는 성질을 가진다.
  • 메서드 : 이것도 클래스의 Scope = { } 안에서 존재한다.

    • 객체 메서드 : 접근 제어자와 반환 타입, 메서드 명, 매개변수를 가지는 메서드를 말한다.

      • 인스턴스 변수와 마찬가지로 객체가 생성되었을 때 Scope에 맞게 가시 된다.
    • 클래스 메서드 : 위의 요소를 가지면서, static이 작성된 상태 변수를 말한다.

      • 클래스 변수와 마찬가지로 클래스 로드 시에 등록, 초기화된다.
      • 클래스를 생성하는 메서드인 팩토리 메서드를 정의할 때 static을 사용한다.
      • 어떠한 기능을 사용하기 위해 해당 타입의 객체를 생성하는 것이 무리가 있을 때, (유틸 성 기능의 필요함으로) static을 적용한다.
        • 예 : String.valueOf(), String.join(), String.format() 등
  • 생성자 : 당연히.. 클래스의 { } 안에 있다.

    • 객체를 생성할 때 사용되는 특별한 메서드를 말한다.
      • 별도의 생성자를 작성하지 않을 경우 인자가 없는 생성자가 자동으로 생성된다.
      • 생성 시점부터 필요한 상태 변수가 있을 경우 매개 변수를 가지는 생성자를 이용한다.

 

클래스의 생성 방법

Public final class FullName {

        // 어떠한 분류(클래스 타입)에 속하는 객체들이 가지는 상태 변수 : 객체의 상태 
        private final String firstName;
        private final String lastName;

        // 객체가 가지는 상태 값을 조작, 제공하는 메서드 : 객체의 행위이자 책임이다.

        // 메서드 선언부 public String getFirstName() : 객체가 수행해야할 책임
        // -> 인터페이스 구현, 추상 클래스의 상속을 통한 추상적인 책임은 무조건 구현하여햐 한다.

        // 메서드 구현부 { } : 객체가 해당 책임을 수행하는 방법. (객체의 자율적인 행위)
        public String getFirstName() {
                return this.firstName;
        }

        public String getLastName() {
                return this.lastName;
        }

        // 객체를 생성할 때 사용되는 생성자 : 인자 값을 통한 초기화를 진행하거나, 별도 로직을 수행한다.
        public FullName(String first, String last) {
                this.firstName = first;
                this.lastName = last;
        }
        
        public FullName() {
        	this("dev","lob");
        }
}

 

클래스에서 사용될 수 있는 수식자

  • 접근 제어자 : 적용된 키워드에 따라 해당 객체, 메서드가 가시 될 범위를 결정한다.

    • public : 모든 클래스에서 해당 클래스를 참조 가능하다.
    • package-private : 해당 클래스가 포함된 패키지 내에서만 참조 가능하다. (지정이 없는 경우)
    • protect : 서브, 하위 클래스와 동일 패키지 내부에 존재하는 클래스만 참조 가능하다.
    • private : 자기 자신인 객체 내부에서만 참조 가능하다. (인터페이스도 JDK9부터 사용 가능)
  • abstract : 해당 클래스, 메서드에서 구현부를 가지지 않고 상속 시 구현을 강제하는 지정 방식이다.

    • 추상 클래스, 인터페이스에서 사용된다.
  • static : 해당 클래스가 인스턴스화 되어있지 않아도 사용 가능하다는 지정 방식이다.

    • 위에서도 언급하였지만 생성 방식과 시점이 다르다.
  • final : 해당 지정자가 작성된 것에 대해 상속이나 변경을 금지한다는 의미이다.

    → 일종의 관례로써 전역적으로 사용되는 static 요소들은 final을 붙인다고 한다.

    → 하지만 private가 지정된 메서드나 final class에 대해선 명시하지 않아도 된다.

    • 객체 변수 : 그 필드의 값이 변경되는 것을 금지한다.

      → 값을 해당 필드에서 초기화하지 않는다면, 생성자를 통한 초기화가 강제된다.

    • 객체 메서드 : 해당 클래스 타입을 상속받는 서브, 하위 클래스에서 오버라이드를 금지한다.

    • 클래스 자신 : 해당 클래스의 상속을 금지한다. (String, Integer.... 등)

  • transient : 객체 직렬화 시에 직렬화 대상에서 제외한다. (이 경우 null로 처리된다.)

  • volatile : 해당 지정자가 붙은 변수에 대해서는 스레드가 값을 캐시하지 않고, 메인 메모리에서 처리한다.

    • 시간에 따라서 각 쓰레드가 참조하는 값이 달라지는 것을 방지한다.

    • 하나의 쓰레드가 값을 증가시키고, 여러 쓰레드가 값을 읽는 경우 항상 최신의 값을 제공하기 위해서는 해당 지정자를 사용하는 것이 좋다.

      → 여러 쓰레드가 값을 증가시키고, 읽는다면 Atomic Variable을 사용하자.

  • sysnchronized : 해당 지정자가 붙은 메서드와 스코프에 스레드 간 동기화를 진행한다는 의미이다.

    • (이후에 멀티 쓰레딩이라는 주제가 있으니 그때 알아보자.)
  • native : 해당 지정자가 붙은 메서드는 Java 가 아닌 네이티브 코드를 사용하는 것을 의미한다.

    • C/C++ 등으로 작성된 DDL이나 JNI에서 제공하는 코드를 말한다.
  • strictfp : 해당 지정자가 붙은 Double, Float에 대하여서 IEEE 754 규격을 적용한다는 의미이다.

    • 인터페이스나 메서드에 지정할 수 있다.

 

객체를 생성하는 방법?

객체를 생성하는 방법은 new 키워드를 사용하는 것이다.

// public static void main 함수나 그외 메서드 영역, 클래스에서 사용한다.

// 클래스 타입, 인스턴스(레퍼런스) 변수명 = new 키워드 생성자(인자...); 의 형태를 가진다.
// new 를 이용한 객체의 생성을 인스턴스화라고 한다.
FullName fullName = new FullName("babo", "Lob");

객체를 생성하면, 해당 객체는 바로 Heap 영역에서 생성된다. 이때 final을 제외한 모든 변수는 초기화되지 않은 상황이 되는데, 이 경우 초깃값을 가지게 된다.

  • char = "\u0000"
  • byte, short, int = 0
  • long = 0L
  • float = 0.0F
  • double = 0.0D
  • boolean = false
  • 배열, 레퍼런스 변수 = null

 

 

올바른 객체지향 시점 (내가 매번 복기하는 3가지 문장)

  • 클래스는 객체지향의 핵심이 아니다. 클래스는 객체를 구현하는 메커니즘이자 설계도일 뿐이다.
  • 클래스는 결국 비슷한 특징을 가지는 객체들의 분류를 의미한다.
  • 클래스는 어떠한 값을 담는 것이 중요한 게 아니다. 객체가 되었을 때, 제공할 행위가 중요하다.

 

메서드를 정의하는 방법?

 

메서드 시그니처?

메서드 정의 시에 메서드의 이름과 매개 변수들을 의미한다.

 

다음 주제에서 정리해야 될 것으로 예상되는 오버 로딩을 제공하기 위함이다.

// {public, private} {static, strictfp, sysnchronized} {Types, void} 메서드명 (인자들) {} 

public String getFirstName() {
        return this.firstName;
}

 

메서드의 기본적인 동작

반환될 값의 타입이 존재한다면 (void 가 아니라면) return을 통한 값 전달이 강제된다.

  • return을 통한 값 전달은 쉽게 생각하면, 메서드가 호출된 곳에 값을 주는 것이다.

 

생성자를 정의하는 방법?

생성자에 대해서도 메서드 시그니처가 적용된다. 이는 점층적 생성자 패턴을 통해 알 수 있다.

 

전달하는 인자에 의해서 호출되는 생성자가 달라진다.

  • 점층적으로 생성되는 생성자가 5개 이상으로 늘어난다면 코드가 복잡해진다.. 이때에는 빌더 패턴을 고려해보자. (이펙티브 자바)
public SomeClass() {
}

SomeClass some = new SomeClass();

public SomeClass(String a) {
        this.aa = a;
}

SomeClass some = new SomeClass(a, b);

public SomeClass(String a, String b, String c) {
        this.aa = a;
        this.bb = b;
        this.cc = c;
}

SomeClass some = new SomeClass(a, b, c);

...... 

 

this 키워드 이해하기

this 참조 변수는 객체가 자기 자신을 참조하는 데 사용하는 키워드이다.

즉 this는 해당 객체의 참조 값 (hashcode 값)을 가지고 있는 것이다.

@Test
public void helloThis(){
    Animal animal = new Animal();
    animal.showThis();
    System.out.println(animal);
}

public class Animal {

    public Animal() {
    }

    public void showThis() {
        System.out.println(this);
    }
}
notefive.oop.Animal@4eb7f003
notefive.oop.Animal@4eb7f003

 

결과를 보면 System.out.println(this), System.out.println(animal)가 동일한 결과를 출력함을 알 수 있다.

객체를 println으로 출력할 때는 인스턴스를 출력할 경우 toString()을 호출한다는 것은 알 것이라고 생각한다.

재정의가 되지 않았을 경우, Object의 toString()을 호출한다.

문자를 Bold 처리한 부분을 보면 출력되는 정보에 뒷부분에 hashCode()를 사용함을 볼 수 있다.

// Object의 toString
public String toString() {
    return getClass().getName() + "@" + **Integer.toHexString(hashCode());**
}

 

this는 언제 사용하는가?

  • 객체 변수와 같은 이름을 가진 다른 것이 존재할 때 객체 변수를 가리키고 있음을 명확히 한다.
String name;
public void someMethod(String name) {
    this.name = name;
}
  • 생성자에서 다른 클래스의 생성자를 호출하는 데 사용할 수 있다.
// 해당 코드는 밑의 생성자를 호출한다.
public SomeClass() {
        this("someString");
}

public SomeClass(String a) {
        this.aa = a;
}
  • 현재 Java 객체를 매개 변수로 전달하는 데 사용한다.
public void SomeClassA{
    public void run() {
        SomeClassB someClassB = new SomeClassB();
        someClassB.getClass(this);
    }
  }

public void SomeClassB{
public void getClass (SomeClassA some){
        // Do SomeThing
    }
}
  • 현재 객체를 반환하는 데 사용할 수 있다. 해당 코드는 빌더 패턴에서 볼 수 있다.
public Builder name(int val) {
    name = val;   // 사용되는 변수명이 다르므로 this를 생략 가능하다.
    return this;  // 객체 자기 자신을 반환함으로써 참조 연산자 . 을 이용한 체이닝이 가능하다.
}

 

5주 차 과제 BinaryTree 구현하기

트리 (Tree)

  • 나무의 형태를 뒤집은 것 같은 형태의 자료구조이며, 각 노드는 M개만큼의 자식 노드를 가지게 된다. 루트 노드부터 시작하여 각 노드는 단반향 간선을 통해서 연결되어 있으며, 하위 레밸에서도 트리가 반복되는 모습을 보이게 되어있다.
  • 트리의 길이는 출발한 노드부터 목적지 노드까지의 거쳐야 하는 가짓수를 의미한다.
  • 트리의 깊이는 루트 노드부터 특정 노드까지의 길이를 의미한다.

 

이진트리 (Binary Tree)

  • 모든 노드의 자식 노드가 최대 2개까지인 트리를 말한다.

 

Binary Tree의 종류

  • 이진 탐색 트리 (Binary Search Tree)

    • Root 노드의 값을 기준하여 좌, 우측에 값을 나누어 저장하는 반 정렬 상태의 이진트리이다.
    • 기본적으로 좌측의 서브 트리, 노드들은 Root 노드보다 작으며, 우측은 크다.
    • 중복된 값을 허용하지 않는다.
  • 정 이진트리 (Full Binary Tree)

    • 마지막 래벨의 노드(리프 노드)를 제외한 모든 노드가 두 자식을 가지고 있는 트리를 말한다.
  • 완전 이진트리

    • 마지막 레밸을 제외하고는 모든 레밸이 완전히 채워져 있는 상태의 트리를 말한다.
    • 마지막 레밸의 노드를 채울 때에는 가장 왼쪽부터 채우게 된다.

 

int 값을 가지고 있는 이진트리를 나타내는 Node라는 클래스를 정의하세요.

  • int value, Node left, right를 가지고 있어야 합니다.
public class Node {

    private int element;
    private Node left;
    private Node right;

    public Node(int element) {
        this.element = element;
        left = right = null;
    }

    public Node(int element, Node left, Node right) {
        this.element = element;
        this.left = left;
        this.right = right;
    }

    public int getElement() {
        return element;
    }

    public Node getLeft() {
        return left;
    }

    public Node getRight() {
        return right;
    }
}

Lob-dev/DashBoardDemo

 

 

BinrayTree라는 클래스를 정의하고 주어진 노드를 기준으로 출력하는 bfs(Node node)와 dfs(Node node) 메서드를 구현하세요.

  • DFS는 왼쪽, 루트, 오른쪽 순으로 순회하세요.
public class BinaryTree {

    public void dfs(Node node) {
        if (node == null) {
            return;
        }
        dfs(node.getLeft());
        System.out.print(node.getElement() + " ");
        dfs(node.getRight());
    }

    public void bfs(Node node) {
        if (node == null) {
            return;
        }
        Queue<Node> queue = new ArrayDeque<>();
        queue.offer(node);
        while (!queue.isEmpty()) {
            traverse(queue);
        }
    }

    private void traverse(Queue<Node> queue) {
        Node poll = queue.poll();
        if (poll != null){
            System.out.print(poll.getElement() + " ");
            getChild(queue, poll.getLeft());
            getChild(queue, poll.getRight());
        }
    }

    private void getChild(Queue<Node> queue, Node child) {
        if (child != null) {
            queue.add(child);
        }
    }
}

Lob-dev/DashBoardDemo

 

테스트 코드

Lob-dev/DashBoardDemo

 

참고자료

각각의 리소스를 분류하기 위해 모든 데이터는 그것만의 표준화된 이름을 가지고 있다. (식별 값)

  • 책의 ISBN 번호
  • 버스의 노선 번호
  • 은행 계좌의 번호
  • 사람의 주민등록번호 등

 

리소스

RFC 2396 - Uniform Resource Identifiers (URI): Generic Syntax

모든 리소스가 일종의 표준 이름을 준수하기에 식별 값을 기준으로 쉽게 공유하고 접근할 수 있다.

 

URL은 인터넷의 리소스를 가리키는 표준이름이다.

 

인터넷의 리소스 탐색하기

URL은 리소스의 위치를 가리키며, 이것을 이용해 리소스를 찾고 사용하며 공유할 수 있다.

사용자는 브라우저에 URL을 입력하고 브라우저는 화면 뒤에서 사용자가 원하는 리소스를 얻기 위해 적절한 프로토콜을 사용하여 메세지를 전송한다.

 

URL 은 통합 자원 식별자 혹은 URI 라고 불리는 일반화된 부류의 부분집합이다.

출처 :https://danielmiessler.com/study/difference-between-uri-url/

 

URI 는 URL 과 URN으로 구성된 종합적인 개념이며, 리소스를 접근하는 방식에 따라 분류를 나눈다.

 

스킴은 사용될 프로토콜을 나타내고, 서버 위치는 해당 서버의 주소, 호스트명, 리소스 위치는 리소스 명과 내부

디렉터리 위치를 나타낸다.

 

Scheme : 스킴

주어진 리소스에 어떻게 접근하는지 알려주는 중요한 정보이다.

이것은 클라이언트가 어떤 프로토콜을 사용하여 리소스를 요청해야하는지 알려주는 역할을한다.

 

호스트와 포트

애플리케이션이 인터넷에 있는 리소스를 찾으려면, 리소스를 호스팅하고 있는 장비와 그 장비 내에서 접근할 수 있는 서버가 어디에 있는지 알아야한다

 

호스트와 포트는 그 두가지 정보를 제공해준다.

포트값이 지정되지 않았을 경우, 기본 값인 80을 사용하게 된다.

 

사용자 이름과 비밀번호

많은 서버가 데이터 접근을 허용하기 전에 인증 처리를 우선적으로 진행하게끔 설계되어 있다.

사용자의 이름과 비밀번호는 서버에 등록되어 관리되면서 기존 정보와 비교되어 동일한 경우에만 데이터를 제공해준다.

 

경로

리소스가 서버의 어디에 있는지 알려준다.

경로를 잘 살펴보면 계층적 파일 시스템과 유사한 구조를 가지고 있음을 알 수 있다.

 

파라미터

많은 스킴이 리소스에 대한 호스트 및 경로 정보만으로는 찾지 못한다.

서버가 어떤 포트를 열어놓고 있는지, 어떤 정보를 요구하는 지 등의 다른 정보들을 제공하여야 한다.

 

URL의 파라미터는 애플리케이션이 서버에 정확한 요청을 하기 위해 필요한 입력 파라미터를 받는데 사용하게 되는데, Key:Value 형식으로 URL에 기술되어 제공된다.

 

질의 문자열

데이터베이스와 같은 서비스들은 요청받을 리소스의 형식의 범위를 좁히기 위해 질문이나 질의를 받을 수 있다.

? 으로 시작되며 각 Key 와 Value 는 = 으로 대입되고 &으로 구분되어 있다.

ex) ?item=12731&color=blue

 

프래그먼트

HTML 같은 리소스 형식들은 본래의 수준보다 더 작게 나뉠 수 있다.

 

질문이 포함된 하나의 큰 텍스트 문서가 있을 경우, 그 리소스에 대한 URL은 해당 문서를 가르키지만 프래그먼트를 통해서 해당 문서 내부의 특정한 값을 가르킬 수 있다.

 

프래그먼트는 URL 문자 오른쪽에 # 구분자 이후에 오게된다.

ex) tools.html#drills

 

단축 URL

웹 클라이언트는 몇몇 단축 URL을 인식하고 사용한다. 상대 URL은 리소스 안에 있는 리소스를 간결하게 기술하는데

사용할 수 있다. 많은 브라우저가 사용자가 기억하는 URL 일부를 입력하면 나머지 부분을 자동으로 입력해주는 URL

자동 확장을 지원한다.

 

상대 URL

URL은 상대 URL과 절대 URL로 나뉘게 된다.

앞서 나왔던 URL들은 리소스에 접근할 수 있는 모든 정보를 포함한 절대 URL 이다.

 

상대 URL로 리소스에 접근하는데 필요한 모든 정보를 얻기 위해서는 기저(base)라고 하는 다른 URL을 사용해야 한다.

 

어떠한 HTML 문서에서 사용되는

<a href="./login.html"/>

이러한 형식의 URL을 상대 URL 이라고 하며, 현재 접근한 URL 이 Base URL이 된다.

 

즉 현재 URL 정보에서 링크 정보를 통해 추가적인 접근을 할 수 있는 것이다.

 

URL의 확장

어떤 브라우저들은 URL을 입력한 다음이나, 입력하고 있는 동안에 자동으로 URL을 확장해준다.

이는 사용자가 좀 더 빠르게 URL을 작성할 수 있게끔 지원하는 기능이다.

  • 호스트 명 확장

    naver만을 입력하면 www. 와 .com을 붙여서 www.naver.com 의 형태를 만들어주게 된다.

    몇몇 브라우저는 해당단어를 포함한 사이트를 찾지 못한다면, 몇 가지의 URL을 추가로 제시한다.

  • 히스토리 확장

    과거에 사용자가 방문했던 URL 기록을 저장하여 유사한 단어가 나왔을 경우 완전한 URL들을 불러와 선택하게 해준다.

 

안전하지 않은 문자

URL은 호환성을 위하여, 허용되지 않은 문자(이진 데이터, 알파벳 외의 문자 등)를 포함한 URL이 전송되는 경우 이스케이프라는 기능을 사용하여 인코딩하게끔 지원한다.

 

URL 문자 집합

컴퓨터 시스템의 기본 문자 집합은 보통 영어 중심으로 설정되어 있다. (ASC II 등)

영어를 제외한 비 라틴어, 유럽의 언어 등을 지원하기 위해서 URL에 이스케이프 문자열을 사용할 수 있도록 설계하였으며, 호환성을 지킬 수 있게 되었다.

 

스킴의 종류

  • http
  • https
  • mailto - 이메일 주소를 가리킨다.
  • ftp - FTP 서버에 있는 파일을 다운, 업로드, 컨텐츠 목록을 불러오는 등의 행위에서 사용된다.
  • rtsp, trspu - 실시간 스트리밍 프로토콜의 약자이며, 오디오, 비디오와 같은 미디어 리소스이다.
  • file - 주어진 호스트 기기에서 바로 접근할 수 있는 파일들을 나타낸다. (로컬 디스크, 네트워크..)
  • news - 특정한 문서나 뉴스 그룹에 접근하는데 사용된다.
  • telnet - 대화형 서비스에 접근하는데 사용된다.

등이 있다.

'Book! > HTTP 완벽 가이드' 카테고리의 다른 글

1장 HTTP 개관  (1) 2020.12.11

전 세계의 브라우저, 서버, 웹 애플리케이션은 모두 HTTP를 통해 서로 대화한다

 

HTTP : 인터넷의 멀티미디어 배달부

HTTP 는 신뢰성 있는 데이터 전송 프로토콜을 사용하기 때문에, 데이터가 지구 반대편에서 오더라도 전송 중 손상되거나 꼬이지 않음을 보장한다. 이 덕분에 사용자는 인터넷에서 얻는 정보가 손상된 게 아닌지 염려하지 않아도 된다.

 

웹 클라이언트와 서버

웹 컨텐츠는 서버에 존재한다. 서버는 보통 HTTP 프로토콜로 의사소통하기 때문에 HTTP 서버라고 부르기도 한다. 웹 서버는 인터넷의 데이터를 저장하고 클라이언트가 요청한 데이터를 제공한다.

웹 클라이언트

  • 크롬
  • 익스플로러
  • 사파리 등

 

리소스

웹 서버는 "리소스"라는 것을 관리하고 제공한다.

리소스란?

  • 웹 서버의 정적 파일 (HTML, Text, Word, PPT, JPEG, PNG, AVI....)

  • 웹 서버의 동적 콘텐츠 (라이브 스트리밍, 주식 거래 API 결과, 검색 엔진, 물품 거래 결과..)

    WAS에서 요청에 따라 생성되는 데이터

즉 리소스는 웹에 콘텐츠를 제공하는 모든 것을 의미한다.

 

미디어 타입

인터넷은 수많은 데이터 타입을 다룬다. 이것을 MIME라는 데이터 포맷 라벨을 붙이고 관리하는데, 이 포맷은 사실 각기 다른 전자메일 시스템 간의 메시지 전송시 호환성을 위해 설계되었다.

 

Primary Object Type / Specific Sub Type 구조로 이루어져 있다.

웹 서버는 모든 HTTP 데이터에 MIME 타입을 붙이고 관리하게 된다.

  • image/jpeg

  • image/gif

  • text/html

  • text/plain

  • audio/mpeg

  • application/....

    ... 등

 

URI

서버 리소스 이름은 URI (Uniform Resource Identifier)이라는 식별자로 관리된다.

클라이언트는 URI를 이용하여 어떠한 리소스를 선택하고 이용할 수 있다.

예)

http://www.joes-hardware.com/specials/saw-blade.gif

URI의 종류에는 두 가지가 존재한다.

  • URL
  • URN

 

URL (Uniform Resource Locator)

리소스 식별자의 가장 흔한 형태이다.

URL은 특정 서버의 한 리소스에 대한 구체적인 위치를 서술한다.

URL 리소스의 정확한 위치와 접근방법을 보여주는 예

대부분의 URL은 세 부분으로 이루어진 표준 포맷을 따른다.

  • scheme : 리소스에 접근하기 위해 사용되는 프로토콜을 서술한다. (http://)
  • 서버의 인터넷 주소 (www.oreilly.com)
  • 접근할 서버의 리소스 (index.html,. gif...)

오늘날 대부분의 URI는 URL이며, 통상적인 관례로는 URI를 URL과 같은 의미로 사용한다고 한다.

 

URN (Uniform Resource Name)

콘텐츠를 이루는 한 리소스에 대해, 그 리소스의 위치에 영향받지 않는 유일무이한 이름 역할을 한다. 이 URN은 리소스의 위치가 변경되더라도 문제없이 접근, 동작할 수 있게 한다.

  • 리소스의 이름이 변하지 않고 유지되는 동안 접근할 수 있다.

 

트랜잭션

HTTP 트랜잭션은 요청 명령과 응답 결과로 구성되어 있다.

  • 요청 명령 : 클라이언트에서 서버로 보내는 상황
  • 응답 결과 : 서버에서 클라이언트로 보내는 상황

HTTP 트랜잭션과 관련된 상호작용은 HTTP 메시지라고 불리는 데이터를 통해 이루어진다.

참고 : https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages#:~:text=HTTP messages are how data, and span over multiple lines.

 

메서드

HTTP는 HTTP 메서드라고 불리는 여러 가지 종류의 요청 명령을 지원한다.

모든 HTTP 메시지는 한 개의 HTTP 메서드를 가지게 된다.

 

HTTP request methods

 

HTTP 메서드는 서버에게 어떠한 동작을 해야 하는지 알려주는 역할을 한다.

  • GET → GetMapping
  • POST → PostMapping
  • Delete
  • Update
  • HEAD 등

 

상태 코드

모든 HTTP 응답 메시지는 상태 코드와 함께 반환된다.

HTTP response status codes

상태 코드는 클라이언트에게 요청이 성공했는지 아니면 추가 조치가 필요한지 알려주는 숫자 값이다.

  • 200 OK
  • 302 Redirect
  • 404 Not Found 등

상태 코드는 숫자 값 : 사유 구절의 형태로 클라이언트에게 제공된다.

  • 200 OK
  • 200 Document attached
  • 200 Success 등

 

웹 페이지는 여러 객체로 이루어질 수 있다.

Application은 보통 하나의 작업을 수행하기 위해 여러 HTTP 트랜잭션을 수행한다.

시작적으로 여러 콘텐츠를 가진 웹 페이지가 있다 가정하였을 떼 다수의 트랜잭션이 진행된다.

  • HTML 뼈대를 하나의 트랜잭션으로 가져온 뒤
  • 첨부된 이미지, 그래픽, 자바 애플릿 등의 파일을 위해 추가적으로 트랜잭션을 수행한다.

 

메시지

HTTP 요청과 응답 메시지 구조를 살짝 들여다보자.

HTTP Message는 단순한 줄 단위의 문자열이다. 이진 형식이 아닌 일반 텍스트이기 때문에 사람이 읽고 쓰는 것이 쉽다.

 

참고 : http://www.icodeguru.com/dotnet/core.c.sharp.and.dot.net/0131472275/ch17lev1sec1.html

 

클라이언트가 서버로 보내는 HTTP 메시지를 요청 메시지, 반대로 서버가 클라이언트에게 보내는 것을 응답 메시지라고 부른다.

 

 

메시지 구조

  • 시작 줄 - Request line

    요청이라면 무엇을 해야 하는지 응답이라면 무슨 일이 일어났는지 알려준다.

  • 헤더

    시작줄 이후로는 0개 이후의 헤더 필드가 이어지게 된다.

    각 헤더 필드는 : 를 기준으로 구분되어 있는 하나의 이름과 값으로 구성된다.

  • 본문

    어떤 종류의 데이터든 들어갈 수 있는 공간이다.

    요청, 응답 본문이 해당 부분에 작성되며, 각종 타입의 이진 데이터, 텍스트를 포함할 수 있다.

 

TCP 커넥션

HTTP 메시지는 TCP 커넥션을 통하여 이동하게 된다.

 

TCP/IP

HTTP는 Application 계층의 프로토콜이다. HTTP는 네트워크 통신의 핵심적인 세부사항에 대해 신경 쓰지 않는다. 대신 TCP/IP라는 프로토콜에게 전송 등에 대한 처리를 위임한다.

 

TCP는 다음과 같은 기능을 제공한다.

  • 오류 없는 데이터의 전송
  • 순서에 맞는 전달 (데이터는 언제나 보낸 순서대로 도착한다)
  • 조각나지 않는 데이터 스트림 (언제든 어떤 크기로든 보낼 수 있다.)

TCP/IP는 TCP와 IP가 층을 이루는, 패킷 교환 네트워크 프로토콜의 집합이다.

TCP/IP는 각 네트워크와 하드웨어의 특성을 숨기고, 어떤 종류의 디바이스든 간에 서로 신뢰성 있는 의사소통을 하게 해 준다.

 

일단 TCP 커넥션이 맺어지면, 클라이언트와 서버 간의 교환되는 메시지가 없어지거나 손상되거나 순서가 뒤바뀌어 수신되는 일은 결코 없다.

 

접속, IP 주소 그리고 포트번호

HTTP 클라이언트가 서버에 메시지를 전송할 수 있게 되기 전에, 인터넷 프로토콜 주소와 포트번호를 사용해 클라이언트와 서버 사이에 TCP/IP 커넥션을 맺어야 한다.

 

TCP에서는 서버 컴퓨터에 대한 IP 주소와 그 서버에서 실행 중인 프로그램이 사용 중인 포트번호가 필요하다. 그리고 그것을 알기 위해 URL을 사용한다.

 

HTTP URL에 포트번호가 빠진 경우에는 80을 기본값으로 사용하여 접근한다.

  1. 웹 브라우저는 URL에서 호스트 명을 추출한다.
  2. 서버의 호스트 명을 IP로 변환한다
  3. URL에서 포트번호를 추출한다. (존재하는 경우)
  4. 웹 브라우저가 해당 정보를 가지고 서버와 TCP 커넥션을 맺는다. (3 way handshake)
  5. 웹 브라우저는 서버에 HTTP 요청을 보낸다.
  6. 서버는 웹 브라우저에게 HTTP 응답을 돌려준다.
  7. 커넥션이 닫히면 웹 브라우저는 문서를 보여준다. (4 way handshake)

 

프로토콜 버전

  • HTTP/0.9

    GET 메서드만을 지원하고 MIME 타입이나, 헤더, 버전 번호를 지원하지 않는다.

  • HTTP/1.0

    버전 번호, 헤더, 추가 메서드, MIME 객체 처리를 추가하였다.

  • HTTP/1.0+

    공식적인 기능은 아니지만 KEEP-ALIVE 커넥션, 가상 호스팅, 프락시 연결 등을 지원하였다.

    유명한 웹 클라이언트, 서버에 의해 확장된 HTTP/1.0 등을 칭한다.

  • HTTP/1.1

    HTTP 설계의 구조적 결함 조정, 두드러진 성능 최적화, 잘못된 기능 제거에 집중하였다.

    그 외에도 앞서 추가했던 KEEP-ALIVE 등 기능들을 공식적으로 지원하였다.

  • HTTP/2.0

    HTTP/2

    HTTP 1.1 버전의 성능을 개선하기 위해 구글의 SPDY 프로토콜을 기반으로 설계한 버전이다.

 

웹의 구성요소

 

HTTP 프록시 서버

클라이언트와 서버 사이에 위치한 HTTP 중개자

웹의 보안, Application 통합, 성능 최적화를 위한 중요한 구성 요소이다.

 

주로 모든 HTTP 요청을 받아 서버에 전달한다.

모든 웹 트래픽 흐름 속에서 신뢰할 만한 중개 역할을 수행한다.

요청과 응답을 필터링한다. (바이러스 검출, 성인 콘텐츠 차단 등)

 

 

웹 캐시, 캐시 프락시

많이 찾는 웹페이지를 클라이언트 가까이에 보관하는 HTTP 창고이다.

문서들 중 자주 접근하는 것의 사본을 저장하여 다음 요청 시에 캐시 된 문서를 제공한다.

 

HTTP는 캐시를 효율적으로 동작하게 하고 캐시된 콘텐츠를 최신의 버전으로 유지하면서 동시에 프라이버시도 보호하기 위한 많은 기능을 정의한다.

 

 

게이트웨이

다른 Application과 연결된 특별한 웹 서버이다.

주로 HTTP 트래픽을 다른 프로토콜로 변환하기 위해 사용한다.

 

게이트웨이는 언제나 스스로가 리소스를 갖고 있는 서버인 것처럼 요청을 다룬다.

클라이언트는 자신이 게이트웨이 통신하고 있음을 알아채지 못한다.

 

 

터널

HTTP 통신 전달만을 책임지는 특별한 프락시이다.

두 커넥션 사이에서 데이터를 전달하는 HTTP Application이다.

 

HTTP 터널은 주로 비 HTTP 데이터를 하나 이상의 HTTP 커넥션을 통해 그대로 전송해준다.

대표적인 활용 예로는 암호화된 SSL 트래픽을 HTTP 커넥션으로 전송함으로써 웹 트래픽만 허용하는 방화벽을 통과시키는 것이 있다.

 

 

에이전트

자동화된 HTTP 요청을 만드는 준지능적 웹 클라이언트이다.

웹 브라우저를 포함하며, 스파이더(크롤링)나 웹 로봇 등도 하나의 에이전트이다.

 

 

도서

http://www.yes24.com/Product/Goods/15381085?pid=136927&ReturnURL=http://www.yes24.com&

'Book! > HTTP 완벽 가이드' 카테고리의 다른 글

2장 URL과 리소스  (0) 2020.12.12

+ Recent posts