💖
라이브러리
: 공통으로 사용될 수 있는 특정한 기능들을 모듈화 한 것
- 규칙 ❌, 프레임워크에 비해 자유로움 (폴더명, 파일명 등)
💖
프레임워크
: 공통으로 사용될 수 있는 특정한 기능들을 모듈화 한 것
- 규칙 ⭕️, 라이브러리에 비해 엄격함 (폴더명, 파일명 등)
🍋
싱글톤패턴
: 하나의 클래스에 하나의 인스턴스만 가지는 패턴
하나의 인스턴스를 다른 모듈들이 공유하며 사용
class DesignPattern1_1 {
private static class singleInstanceHolder { // 메서드(객체 생성하는)
// 객체 INSTANCE 생성
// private로 제한 -> 생성자를 통한 무분별 객체생성 막음
private static final DesignPattern1_1 INSTANCE = new DesignPattern1_1();
}
// getInstance() 메서드 -> 객체반환 (public)
public static DesignPattern1_1 getInstance() {
return singleInstanceHolder.INSTANCE;
}
}
class DesignPattern1_2 {
public static void main(String[] args) {
// getInstance()를 통해서 객체(인스턴스) 생성
DesignPattern1_1 a = DesignPattern1_1.getInstance();
DesignPattern1_1 b = DesignPattern1_1.getInstance();
System.out.println(a.hashCode());
System.out.println(b.hashCode());
if (a == b) {
System.out.println(true);
}
}
}
📍 Java에서 Singleton ; 프로그램 실행 시, 최초 한번만 메모리 할당
(메모리고정 -> 낭비최소화)
📎 TDD(Test-Driven-Development)의 걸림돌이 됨
🍋
의존성주입
: 모듈간 결합을 느슨하게 만듬. '느슨한 결합관계' → 싱글톤패턴 단점 해결
의존성(=종속성) : 양방향관계
구분 | 내용 |
---|---|
장점 | 모듈 쉽게 교체할 수 있는 구조 → 테스팅 ✅, 마이그레이션 수월함 ✅ |
장점 | 애플리케이션 의존성 방향 일관 |
장점 | 애플리케이션 쉽게 추론 가능 |
단점 | 모듈분리 → 클래스 수 증가로 인한 런타임 패널티 |
📎 의존관계 역전 원칙
📎 단일 책임 원칙
// (의존성이 높은 경우, 클래스 간 관계)
class Pencil1 {}
class Store1 {
private Pencil1 pencil1;
public Store1() { // 생성자
this.pencil1 = new Pencil1();
}
}
// (의존성 주입 -> 느슨한결합형태)
interface Product {} // 다형성 (여러가지 제품을 하나로 표현하는 interface)
class Pencil2 implements Product{}
class Store2 {
private Product product;
public Store2(Product product) { // 생성자 (객체를 넣어주는 방식)
this.product = product;
}
}
class BeanFactory {
public void store2() {
// Bean 생성
Product pencil2 = new Pencil2();
// 의존성주입
Store2 store2 = new Store2(pencil2);
}
}
🐱
팩토리패턴
① 객체 생성 부분 떼어냄 → 추상화한 패턴
② 상속 관계 두 클래스 → 상위 클래스 : 뼈대결정 + 하위클래스 : 객체 생성 구체적내용 결정
느슨한 결합
(의존성 low) ✅더 많은 유연성
✅유지보수성 증가
✅// super class -> Lattee, Americano, DefaultCoffee의 부모클래스
abstract class Coffee { // 객체생성부분 추상화
public abstract int getPrice(); // 메서드
@Override
public String toString() { // 메서드
return "Hi this coffee is " + this.getPrice();
}
}
class DefaultCoffee extends Coffee {
private int price; // 멤버변수
public DefaultCoffee() { // 생성자
this.price = -1;
}
// Coffee 클래스 getPrice() 메서드 -> 생성자로 설정한 값 덮어씌움
@Override
public int getPrice() {
return this.price;
}
}
class Latte extends Coffee {
private int price; // 멤버변수
public Latte(int price) { // 생성자
this.price = price;
}
// Coffee 클래스 getPrice() 메서드 -> 생성자로 설정한 값 덮어씌움
@Override
public int getPrice() {
return this.price;
}
}
class Americano extends Coffee {
private int price; // 멤버변수
public Americano(int price) { // 생성자
this.price = price;
}
// Coffee 클래스 getPrice() 메서드 -> 생성자로 설정한 값 덮어씌움
@Override
public int getPrice() {
return this.price;
}
}
class CoffeeFactory {
public static Coffee getCoffee(String type, int price) { // 메서드
if ("Latte".equalsIgnoreCase(type)) { // 입력값(type) = "Latte"
return new Latte(price);
}
else if ("Americano".equalsIgnoreCase(type)) { // 입력값(type) = "Americano"
return new Americano(price);
}
else {
return new DefaultCoffee();
}
}
}
class DesignPattern1_3 {
public static void main(String[] args) {
Coffee latte = CoffeeFactory.getCoffee("Latte", 4000);
Coffee ame = CoffeeFactory.getCoffee("Americano", 3000);
System.out.println("Factory latte :: " + latte);
System.out.println("Factory ame :: " + ame);
}
}
Factory latte :: Hi this coffee is 4000
Factory ame :: Hi this coffee is 3000
📎 상수 및 메서드 집합을 정의할 때 사용되는 type
🌈
전략패턴
=정책패턴
- 객체 행위 수정 → ‘직접’ 수정 ❌
- 전략 (캡슐화한 알고리즘) → 컨텍스트 안에서 바꿈 ➡️ 상호교체 가능
// 결제 interface
interface PaymentStrategy {
public void pay(int amount); // pay 메서드
}
// (결제) 전략 1
class KAKAOCardStrategy implements PaymentStrategy {
private String name;
private String cardNumber;
private String cvv;
private String dateOfExpiry;
// 생성자
public KAKAOCardStrategy(String name, String cardNumber, String cvv, String dateOfExpiry) {
this.name = name;
this.cardNumber = cardNumber;
this.cvv = cvv;
this.dateOfExpiry = dateOfExpiry;
}
// PaymentStrategy interface pay 메서드
@Override
public void pay(int amount) {
System.out.println(amount + " paid using KAKAOCard.");
}
}
// (결제) 전략 2
class LUNACardStrategy implements PaymentStrategy {
private String email;
private String password;
// 생성자
public LUNACardStrategy (String email, String password) {
this.email = email;
this.password = password;
}
// PaymentStrategy interface pay 메서드
@Override
public void pay(int amount) {
System.out.println(amount + " paid using LUNACard.");
}
}
// 상품 클래스
class Item {
private String name;
private int price;
// 생성자
public Item (String name, int price) {
this.name = name;
this.price = price;
}
// 메서드
public String getName() {
return name;
}
public int getPrice() {
return price;
}
}
// 장바구니 클래스
class ShoppingCart {
// Item 클래스 리스트 객체
List<Item> items;
// 생성자
public ShoppingCart() {
this.items = new ArrayList<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 item : items) {
sum += item.getPrice();
}
return sum;
}
public void pay(PaymentStrategy paymentStrategy) {
int amount = calculateTotal();
paymentStrategy.pay(amount);
}
}
class DesignPattern1_4 {
public static void main(String[] args) {
// 객체 생성
ShoppingCart cart = new ShoppingCart();
Item A = new Item("mallang", 1000);
Item B = new Item("quokka", 1000);
cart.addItem(A);
cart.addItem(B);
// pay by LUNACard
cart.pay(new LUNACardStrategy("quokka@gmail.com", "quokka"));
// pay by KAKAOCard
cart.pay(new KAKAOCardStrategy("mallang", "mallang123", "123", "04/12"));
}
}
2000 paid using LUNACard.
2000 paid using KAKAOCard.
🐰
옵저버패턴
① 주체가 객체의 상태변화 관찰
② 상태변화 감지 → method() 통해 ➡️ 옵저버목록 속, 옵저버에게 변화 notification
객체 변화 상태 → 전달되는 메서드 기반 ➡️ '추가 변화 사항'이 생기는 객체
① Model(주체)에서 변경사항 발생
② update() 메서드 → View(옵저버)에게 notification
③ 위의 사항 기반으로 Controller 작동
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();
}
// 자바 구현방식 : 부모 interface -> 자식클래스에서 재정의 하여 구현
// 반드시 부모클래스의 메서드를 재정의해야함 (!= 상속 extends)
class Topic implements Subject {
private List<Observer> observers;
private String message;
// 생성자
public Topic() {
this.observers = new ArrayList<>();
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 Object getUpdate(Observer obj) {
return this.message;
}
public void postMessage(String msg) {
System.out.println("Message sended to Topic: " + 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);
System.out.println(name + ":: got message >> " + msg);
}
}
class DesignPattern1_5 {
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.postMessage("mallang is crossfit champion!");
}
}
// topic은 주체이자 객체
Message sended to Topic: mallang is crossfit champion!
a:: got message >> mallang is crossfit champion!
b:: got message >> mallang is crossfit champion!
c:: got message >> mallang is crossfit champion!
🐰
상속(extends)
: 자식클래스가 부모클래스의 메서드 등을 상속받아 사용
🐰
구현(implements)
: 부모 interface를 자식클래스에서 재정의하여 구현 (@Override)
🎈
프록시패턴
① 대상객체(subject) 접근 전, 접근에 대한 흐름을 가로챔
② 대상객체(subject) 앞단의 인터페이스 역할을 하는 디자인패턴
캐시(임시저장소) 안에 정보를 담아둠
d1, d2 Request에 대해 원격저장소에 Request ❌
트래픽감소효과
🎈
프록시서버
: Server와 Client사이 → Client가 자신을 통해 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터시스템 or 응용프로그램
🎈
nginx
: 비동기 이벤트기반구조와 다수의 연결을 효과적으로 처리가능한 웹서버 (Node.js 서버 앞단 프록시 서버로 활용)
Node.js 버퍼오버플로우 취약점 해결방안
익명 Client → 직접적 서버 접근 차단 ⛔️
간접적으로 한단계 더 거침 → 보안강화 ✅
🎈
CloudFlare
: 전 세계적으로 분산된 서버 → 시스템 콘텐츠 전달을 빨리 할 수 있는 CDN 서비스
CDN (콘텐츠 전송 네트워크)
1. DDOS 공격방어
📎 DDOS
① 짧은기간 → 네트워크에 많은 Request를 보내 네트워크 마비
② 웹사이트 가용성을 방해 사이버공격
2. HTTPS 구축
3. 트래픽 보안
🎈
CORS
: 서버가 웹 브라우저에서 리소스 다운 시, 다른 오리진을 통해 로드하지 못하게 하는 HTTP Header 기반 메커니즘
📎 오리진 origin
- 프로토콜 + host(IP) + port 조합
- https://mallang.com:8000
→ https:// 프로토콜, mallang.com 호스트, 8000 포트
CORS ERROR
FrontEnd port와 BackEnd port 불일치
해서 발생프록시 서버 → FrontEnd 서버에서 요청되는 오리진 → BackEnd 서버에 맞춰 오리진 변경
✅📎 DNS (도메인이름시스템)
- mallang 도메인 → 127.0.0.1 머신 IP 주소로 변환
사전이 따로 없네요~ 훌륭합니다. ㅋㅋ 목차가 왼쪽에 있으면 더 좋을거 같아요