TIL

TIL 3일차

nayoon 2022. 11. 29. 22:03

26살쯤 되면..뻔뻔하게 TIL 3일차라고 적을 수 있다..하하하.. 

오랜만에 공부를 하는데.. 그동안 궁금했던 것들..잘 모르는데 대충은 아는 얄팍한 지식들을..깊게 만들어보겠어요..

 

CORS

Cross-Origin Resource Sharing의 줄임말로 대략적으로 의미를 때려맞추면 '다른 출처의 자원을 공유하는 것'으로 보면 된다.

(CORS가 있기 때문에 여기저기에서 온 자원(resource)를 믿고 쓸 수 있는 것으로 보면 된다고 한다..)

 

Origin

아래와 같이 생긴 URL은 사실 5개의 구성 요소로 이루어져 있다.

포트 번호도 있는데, http의 경우 80, https의 경우 443으로 기본 포트번호로 약속되어져있다.

 

이러한 구성요소가 모두 동일해야 같은 출처(Same Origin)로 본다고 한다. 그렇지 않으면 다른 출처(Cross-Origin)으로 본다고 한다.

 

콘솔에다가 location.origin이라고 검색하면 손쉽게 해당 출처를 알 수 있다.

(최근 가장 가지고 싶었던 '러쉬 욕심쟁이' 를 검색해보았다.. 출처는 https://www.google.com)

 

모든 구성요소가 동일해야 같은 출처라고 했는데, 그렇지 않은 경우도 있다고 한다..?! 참고한 블로그 글을 보면..케바케라고 한다..

 

Same Origin

CORS와 같이 다른 출처로의 리소스 요청을 제한하는 것과 관련된 또 다른 정책이 있는데 SOP이다.

 

Same Origin Policy의 줄임말로 

 

 

 

플라이웨이트 패턴

이미 만들어둔 인스턴스를 이용해서 new로 객체를 마구 만들어내어 메모리를 낭비하는 것을 방지하는 패턴이라고 한다.

 

Flyweight pattern 구성요소

- Flyweight

공유에 사용할 클래스들의 인터페이스를 선언한다.

 

- ConcreteFlyweight

Flyweight의 구체적인 내용을 정의하며 실제로 공유될 객체이다.

 

- FlyweightFactory

팩토리에서 Flyweight 인스턴스를 생성 또는 공유해주는 역할을 한다.

 

- Client

패턴의 사용자이다.

 

실제 코드

Flyweight

해당 패턴을 적용할 클래스들의 인터페이스를 정의한다.

interface Shape {
	public void draw();
}

 

ConcreteFlyweight

Flyweight의 내용을 정의하고, 필요한 속성 역시 정의할 수 있다.

class Circle implements Shape {
    private String color;
    private int x;
    private int y;
    private int radius;
    
    public Circle(String color) {
    	this.color = color;
    }
    
    public void setX(int x) {
    	this.x = x;
    }
    
    public void setY(int y) {
    	this.y = y;
    }
    
    public void setRadius(int radius) {
    	this.radius = radius;
    }
    
    @Override
    public void draw() {
    	System.out.println("그린당~");
    }
    
 }

 

FlyweightFactory

getCircle() 메소드를 통해 객체의 생성 또는 공유를 담당하며 클라이언트에게 응답한다.

class ShapeFactory {
    private static final HashMap<String, Circle> circleMap = new HashMap<>();
    
    public static Shape getCircle(String color) {
    	Circle circle = (Circle)circleMap.get(color);
        
        if (circle == null) {
        	circle = new Circle(color);
            circleMap.put(color, circle);
            System.out.println("새로운 객체 생성");
        }
        
        return circle;
    }
}

 

Client

FlyweightFactory에서 원하는 객체를 생성 또는 공유하는 메소들 호출하며 객체를 사용한다.

public class Main {

    public static void main(String[] args) {
        String colors[] = {"Red", "Green", "Yellow", "Blue"};
        
        for(int i = 0; i < 10; i++) {
            Circle circle = ShapeFactory.getCircle(colors[(int) (Math.random() * 4)]);
            circle.setX((int) (Math.random() * 100));
            circle.setY((int) (Math.random() * 4));
            circle.setRadius((int) (Math.random() * 10));
            circle.draw();
        }
    }
}

 

- 실행 시에 생성되는 객체 인스턴스의 수를 줄여서 메모리를 절약할 수 있다.

- 만들어놓은 여러 개의 객체를 한 곳에 모아둘 수 있다.

 

😆 언제 사용하면 좋을까?

- 객체를 아주 많이 만들어야하는데 모두 같은 방식으로 제어할 수 있는 경우 유용하게 사용할 수 있다.

 

😇 언제 사용하면 슬플까?

- 특정 인스턴스만 다른 인스턴스처럼 동작하도록 하는 것은 불가능..

- 객체의 값을 변경하면 공유받은 객체를 사용하는 곳에 영향을 줄 수 있다.

(뜻하지 않은 결과를 볼 수도 있다..)

 

어댑터 패턴

한 클래스의 인터페이스를 사용하고자 하는 다른 인터페이스로 변환할 때 주로 사용한다.

이를 이용하면 인터페이스의 호환성이 맞지 않아 같이 쓸 수 없는 클래스를 연관 관계로 연결해서 사용할 수 있다.

 

어댑터 패턴은 두 가지로 구현할 수 있다는데 1. 상속을 이용한 어댑터 패턴, 2. 위임을 사용하는 어댑터 패턴 두 가지가 있다.

 

Adapter pattern 구성요소

- Target

지금 필요한 메소드를 결정(인터페이스)

 

- Client

Target 역할의 메소드를 사용해서 로직을 처리

 

- Adaptee

개조되는 쪽, 이미 준비되어있는 메소드가 있음

Adaptee의 메소드와 Target의 메소드가 일치한다면 Adapter는 사실 필요치 않음..

 

- Adapter

Adaptee 메소드를 이용해서 Target이 원하는 메소드를 만들어줌

class에 의한 Adapter 패턴의 경우 '상속'을 이용하도록 하고,

인스턴스에 의한 Adapter 패턴의 경우 '위임'을 이용하도록 한다.

 

실제 코드: Class에 의한 Adapter 패턴

Adaptee

class Banner {

    private String name;
    public Banner(String name) {
        this.name = name;
    }
    
    public void printBanner() {
        System.out.println(name);
    }
}

 

Target interface

interface Print {
    public void printWeak();
    public void printStrong();
}

 

Adapter

Banner 클래스를 상속받았기 때문에 super 명령어를 통해 부모 클래스의 printBanner 메소드를 사용할 수 있다.

class PrintBanner extends Banner implements Print {
    public PrintBanner(String name) {
        super(name);
    }
    
    @Override
    public void printWeak() {
    	System.out.println("weak");
        printBanner();
    }
    
    @Override
    public void printStrong() {
   	System.out.println("strong");
        printBanner();
    }
}

 

Client

public class Main {
    public static void main(String[] args) {
        Print p = new PrintBanner("hi~");
        p.printWeak();
        p.printStrong();
    }
}

// weak
// hi~
// strong
// hi~

 

-> 수정없이 Banner 클래스를 변경해야할 때 class를 이용한 Adapter 패턴을 사용하면 된다.

 

실제 코드: 인스턴스를 이용한 Adapter 패턴

Adapter를 제외한 나머지 코드는 동일합니다.

위의 코드와 다른 점은 상속을 이용하지 않고 인스턴스를 이용해서 어댑터 패턴을 적용했다는 점입니다.

class PrintBanner implements Print {
    Banner banner;
    public PrintBanner(String name) {
        banner = new Banner(name);
    }
    
    @Override
    public void printWeak() {
    	System.out.println("weak");
        printBanner();
    }
    
    @Override
    public void printStrong() {
   	System.out.println("strong");
        printBanner();
    }
}

 

어댑터 패턴을 사용하는 이유

- 이미 존재하는 클래스가 충분한 버그 테스트를 통해 입증되었으며, 지금까지 사용된 전적이 있어서 쉬이 바꿀 수 없다면 해당 클래스를 바꾸고 새롭게 정의하는 것보다는 해당 클래스를 부품으로 이용하는 것이 훨씬 안전하기 때문입니다.

- 어댑터 패턴은 기존 클래스를 통해 새로운 클래스를 만들기 때문에, 필요한 메소드를 빠르게 구현할 수 있다는 장점이 있다. 디버그도 새로 정의한 어댑터 클래스를 기준으로 진행하면 되기 때문에 로직이 복잡한 클래스라고 하더라도 빠르게 디버깅을 진행할 수 있다.

 

mysql, oracle 격리수준

 

ORM

 

 

참고 사이트

 

1. https://evan-moon.github.io/2020/05/21/about-cors/ 

2.https://lee1535.tistory.com/106

 

 

'TIL' 카테고리의 다른 글

TIL 4일차  (1) 2022.11.30
TIL 2일차  (1) 2022.11.16
TIL 1일차  (0) 2022.11.15