본문 바로가기
서적 정리

면접자를 위한 CS전공지식 노트 - ing

by 설이주인 2022. 7. 14.

HTTP 완벽 정리 이후 공부와 정리가 필요한

http://www.yes24.com/Product/Goods/108887922

 

면접을 위한 CS 전공지식 노트 - YES24

디자인 패턴, 네트워크, 운영체제, 데이터베이스, 자료 구조, 개발자 면접과 포트폴리오까지!CS 전공지식 습득과 면접 대비, 이 책 한 권이면 충분하다!개발자 면접에서 큰 비중을 차지하는 CS(Comp

www.yes24.com

해당 책을 선택했습니다! 이번에도 천천히 그리고 꾸준히 가보겠습니다.

 


1장 디자인 패턴과 프로그래밍 패러다임

SECTION 1.1 디자인 패턴

 

싱글톤 패턴

하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴

주로 DB 모듈과 연결시 주로 사용한다.

하나의 인스턴스를 만들고 다른 모듈에 공유하며 사용하기 때문에 인스턴스를 생성시에 드는 비용을 절약할 수 있다. 다만 하나를 다른곳에 공유하기 때문에 의존성이 높아진다.

class Singleton{
    private static class singlrInstanceHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public staticsynchronized Singleton getInstance() {
        return singleInstanceHolder.INSTANCE;
    }
}

public class HelloWorld{
    public static void main() {
        Singleton a = Singleton.getInstance();
        Singleton b = Singleton.getInstance();
        sout(a.hashCode());
        sout(b.hashCode());

        if(a == b){
            sout(ture);
        }
    }
}

단점

- TDD(Test Driven Development) 사용 시 걸림돌이 된다. 우리가 흔히 아는 TDD는 테스트가 서로 독립적으로 어떤 순서로든 실행이 가능해야한다.

- 싱클톤 패턴은 생성된 하나의 인스턴스를 기반으로 구현하는 패턴, 각 테스트마다 “독립적인” 인스턴스를 만들기 어렵다.

- 모듈간의 결합을 강하게 만든다.

 

모듈간의 결합을 느슨하게 만들기 위해서 우리는 의존성 주입(Dependency Injection)을 진행 할 수 있다.

 

의존성 주입

흔히  A가 B에 의존성이 존재 할 시 B에 변경이 일어나면 A 또한 변하게 되는것이다.

 

싱글톤 패턴은 메인 모듈이 모든 관계를 맺지만 의존성 주입의 상태에서는

메일 모듈과 직접연결이 아닌 중간에 의존성 주입자가 해당 부분을 가로채서 메인 모듈이 "간접"적으로 의존성을 주입해주는 방식이다.

위의 행위는 상위 모듈이 하위 모듈에 대한 의존성이 떨어지게 되는 상황 (해당 상황을 디커플링 된다.라고 한다.)

 

장점

- 모듈의 교체가 쉽고 테스팅과 마이그레이션이 수월하다. (마이그레이션 : 데이터 마이그레이션은 데이터를 한 위치에서 다른 위치로, 한 형식에서 다른 형식으로 또는 한 애플리케이션에서 다른 애플리케이션으로 이동하는 프로세스입니다.)

- 의존성 방향이 일관 되며, 애플리케이션을 쉽게 추론 할 수 있으며 모듈간의 관계들이 명확해집니다.

 

단점

- 모듈의 분리로 클래스 수가 증가 되면서 런타임 패널티가 발생하기도 한다.

 

의존성 주입은 지켜야하는 원칙이 존재한다.

- 상위 모듈은 하위 모듈의 어떤한 것도 가져와서는 안되며, 두다 추상화에만 의존해야하며, 추상화는 세부 사항에 의존하지 말아야한다.

 

 

팩토리 패턴

객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴, 상속 관계에 있는 두 클래스에서 상위 클래스가 뼈대를 결정하고 하위 클래스는 이후 구체적인 내용을 결정하는 패턴이다.

 

상위와 하위는 분리 되어있기 때문에 느슨한 결합을 가지며 상위 클래스는 인스턴스 생성에 대해서 전혀 알 필요가 없기에 더 많은 유연성을 갖게 된다. 또한 객체 생성 로직이 따로 떼어져 있기 때문에 코드 리팩토링 시 한 부분만 수정해도 되어서 유지 보수성이 증가 된다.

 

abstract class Coffee{
    public abstract int getPrice();

    @Override
    public String toString(){
        return "this Coffee" + this.getPrice();
    }
}

class CoffeeFactory {
    public static Coffee getCoffee(String type, int price){
        if("Latte".equalsIgnoreCase(type)) return new Latte(price);
        else if ("Americano").equalsIgnoreCase(type) return new Americano(price);
        else {
            return new DefaultCoffee();
        }
    }
}

class DefaultCoffee extends Coffee {
    private int price;

    public DefaultCoffee() {
        this.price = -1;
    }

    @Override
    public int getPrice() {
        return this.price
    }
}

class Latte extends Coffee {
    private int price;

    public Latte() {
        this.price = price;
    }

    @Override
    public int getPrice() {
        return this.price
    }
}

class Americano extends Coffee {
    private int price;

    public Americano() {
        this.price = -1;
    }

    @Override
    public int getPrice() {
        return this.price
    }
}

public class HelloCoffe {
    public static void main(String[] args) {
        Coffee latte = CoffeeFactory.getCoffee("Latte", 4000);
        Coffee ame = CoffeeFactory.getCoffee("Americnao", 3000);

        sout(latte);
        sout(ame);
    }
}

 

전략 패턴 (주로 사용됨) 

전략 패턴은 정책 패턴이라고도 하며, 객체의 행위를 바꾸고 싶은 경우 ‘ 직접’ 수정하지 않고

전략(캡슐화 알고리즘)을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴이다.

(참고 : https://niceman.tistory.com/133 )

 

  • Strategy (전략) : 전략 사용을 위한 인터페이스 생성
  • ImplementationOne, ImplementationTwo : Strategy 인터페이스를 구현한 실제 알고리즘을 구현
  • Context : 인스턴스를 주입 받아 직접 사용하는 역할
//Strategy
interface PaymentStrategy {
    public void pay(int amount);
}

//ImplementationOne
class KAKAOCadStrategy implements PaymentStrategy {
    private String name;
    private String cardNumber;
    private String cvv;
    private String dateOfExpiry;

    public KAKAOCadStrategy(String nm, String ccNum, String cvv, String expiryDate) {
        this.name = nm;
        this.cardNumber = ccNm;
        this.cvv = cvv;
        this.dateOfExpiry = expiryDate;
    }

    @Override
    public void pay(int amount){
        sout(amount + " paid using kakaoCard");
    }
}

//ImplementationTwo
class LUNACardStrategy implements PaymentStrategy {
    private String emailId;
    private String password;

    public LUNACardStrategy(String email, String pwd) {
        this.email = email;
        this.password = pwd;
    }

    public void pay() {
        sout(amount + " paid using LUNACard");
    }
}

class Item {
    private String name;
    private int price;

    public Item(String name, int cost) {
        this.name = name;
        this.price = price;
    }

    public String getName() {
        return name;
    }

    public String getPrice() {
        return price;
    }
}

class shoppingCart {
    List<Item> items;

    public ShoppingCart() {
        this.items. = new ArryaList<Item>();
    }

    public void addItem(Item item) {
        this.items.add(item);
    }

    public void removeItem(Item item) {
        this.items.remove(item);
    }

    public int calculateTotal() {
        int sum = 0;
        for(Item items : items) {
            sum += item.getPrice();
        }
        return sum;
    }

    public void pay(PaymentStrategy paymentMethod) {
        int amount = calculateTotal();
        paymentMethod.pay(amount);
    }
}

//Context (Client가 접촉하는 곳)
public class HelloPayment {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item A = new Item("A", 100);
        Item B = new Item("B", 400);

        cart.addItem(A); //100
        cart.addItem(B); //400

        cart.pay(new LUNACardStrategy("sample@email.com", "pwd!!@@"));

        cart.pay(new KAKAOCadStrategy("name", "cartdNm", "456", "27/12"));
        
        /**
         * paid 500 LUNA
         * paid 500 KAKAO
         */
    }
}

 

옵저버 패턴

주체가 객체의 상태 변화가 일어날때마다 메서드를 통해 목록안에 있는 옵저버들에게 변화를 알려주는 디자인 패턴이다.

  • 주체와 객체가 나눠진 상태
  • 주체와 객체가 합쳐진 상태

해당 패턴을 활용한 서비스 트위터

 

interface Subject {
    public void register(Observer obj);
    public void unregister(Observer obj);
    public void notifyObservers();
    public Object getUpdate(Observer obj);
}

interface Observer {
    public void update();
}

class Topic implements Subject {
    private List<Observer> observers;
    private String message;

    public Topic() {
        this.observers = new ArryaList<> ();
        this.message = "";
    }

    @Override
    public void register(Observer obj) {
        if(!observers.contains(obj)) observers.add(obj);
    }

    @Override
    public void unregister(Observer obj) {
        observers.remove(obj);
    }

    @Override
    public void notifyObservers() {
        this.observers.forEach(Observer :: update);
    }

    @Override
    public void getUpdate(Observer obj) {
        return this.message;
    }

    public void postMeessage(String msg) {
        sout("message" + msg);
        this.message = msg;
        notifyObservers();
    }
}

class TopicSubscriber implements Observer {
    private String name;
    private Subject topic;
    
    public TopicSubscriber(String name, Subject topic) {
        this.name = name;
        this.topic = topic;
    }

    @Override
    public void update() {
        String msg = (String) topic.getUpdate(this);
        sout(name + "::  message" + msg);
    }
}

public class HelloTopic {
    public static void main(String[] args) {
        Topic topic = new Topic();
        Observer a = new TopicSubscriber("a", topic);
        Observer b = new TopicSubscriber("b", topic);
        Observer c = new TopicSubscriber("c", topic);
        topic.register(a);
        topic.register(b);
        topic.register(c);

        topic.postMeessage("this message");
    }
}

 

노출모듈 패턴

 

즉시 실행 함수를 통해 private, public 같은 접근 제어자를 만드는 패턴을 말한다.

publilc - 클래스에 정의된 함수에서 접근 가능하며 자식 클래그와 외부 클래스에서 접근 가능한 범위

private - 클래스에서 정의된 함수에서 접근 가능하며 자식 클래스와 외부 클래스에서 접근 불가능 범위

protected - 클래스에 정의된 함수에서 접근이 가능하지만 자식 클래스와 외부 클래스에서 접근이 불가능한 범위

즉시 실행 함수 - 함수를 정의 하자마자 바로 호출하는 함수, 초기화 코드, 라이브러리 내 전역 변수의 충돌 방지등에 사용한다.

 

MVC패턴

 

Model - View - Controller로 이루어진 디자인 패턴

model - 애플리케이션의 데이터인 데이터베이스, 상수, 변수를 뜻함

view - 사용자 인터페이스

컨트롤러 - 하나 이상의 모델과 하나 이상의 뷰를 잇는 다리, 메인 로직 구성

 

프록시 패턴 (proxy pattern)

 

대상 객체(subject)에 접근하기 전 그 접근에 대한 흐름을 가로채 대상 객체 앞단의 인터페이스 역할을 해주는 디자인 패턴

 

위의 행위를 통해서 객체의 속성, 변환등을 보완하면서 보안, 데이터 검증, 캐싱, 로깅에 사용한다.

객체로도 쓰이지만 서버로도 활용 된다.

 

+) 프록시 서버에서의 캐싱

캐시 안에 정보를 담아두고 캐시 안에 있는 정보를 요구하는 요청에 대해 다시 저 멀리 있는 원격 서버에 요청 하지 않고 캐시 안에 있는 데이터를 활용하는 것을 말한다. 이를 통해 불필요하게 외부와 연결 하지 않기에 트래픽을 줄일 수 있다.

 

프록시 서버로 nginx

비동기 이벤트 기반의 구조다수의 연결을 효과적으로 처리 가능한 웹 서버

 


 

'서적 정리' 카테고리의 다른 글

이펙티브 자바  (0) 2023.10.19
앞으로 틈틈히 읽은 서적 목록  (0) 2022.07.14
HTTP 완벽 가이드  (0) 2022.06.02