전체 글 54

redis

사실 모듈이라고 보기는 좀 그렇지만, 그래도 그냥 좀 정리를 해보자. 먼저 얘가 뭐하는 놈인지부터 보면,RAM 기반으로 저장이 이루어져 매우 빠르고, 따라서 캐시 같은 역할을 하는 친구라고 생각할 수 있겠다. 특징key-value 구조관계형 데이터베이스들과는 달리, key-value 구조를 갖는다.다양한 자료구조 지원String, List, Set, SortedSet 등 다양하게 지원해줘서 여러가지로 활용될 수 있다.TTL(만료 시간) 지원따라서 캐시로 만들기 좋다. 오래된 놈은 걍 지워지니까. 이러한 특징 때매 DB 부하 감소를 위한 캐시로 사용되거나, 작업 큐를 관리하는 Celery Broker로 사용되거나 하는 것 같다. 파이썬에서 사용import redisr = redis.Redis(host="l..

ABCMeta

ABCMeta는 파이썬에서 인터페이스를 선언해주기 위해 사용된다.사용 예제from abc import ABCMeta, abstractmethodclass Animal(metaclass=ABCMeta): @abstractmethod def sound(self): pass직접 인스턴스화 할 수 없다a = Animal() # TypeError: Can't instantiate abstract class Animal ...상속받은 클래스에서는?class Dog(Animal): def sound(self): return "멍멍"d = Dog() # ✅ OKd.sound() # "멍멍"class Cat(Animal): passc = Cat()# Ty..

dataclass

dataclass는 “데이터 묶는 클래스”를 아주 간단하게 만들어주는 표준 라이브러리이다. class Point: def __init__(self, x, y): self.x = x self.y = y와 같은 코드를 아래처럼 바꿔준다.from dataclasses import dataclass@dataclassclass Point: x: int y: int 다음과 같은 기능들이 있다. 1. 기본 기능1) 자동 __init__p = Point(3, 4)print(p.x, p.y) # 3 42) 자동 __repr__print(p)# Point(x=3, y=4)3) 자동 __eq__Point(1,2) == Point(1,2) # TruePoint(1,2) == Poi..

BOJ 3015 - 오아시스 재결합

문제요약길이가 N인 수열이 주어진다.어떤 두 원소 사이에 그 두 원소보다 큰 수가 존재하지 않는다면, 두 원소는 서로를 볼 수 있다라고 정의한다.서로를 볼 수 있는 원소 쌍의 개수를 구하여라.관찰 1수열에서 두 원소 A와 B를 생각해보자.일반성을 잃지 않고, A가 B보다 왼쪽에 있다고 하겠다.'A와 B가 서로를 볼 수 있다'는 것은 곧, 'A의 오큰수가 B거나 B의 오른쪽에 있고, B의 왼큰수가 A거나 A의 왼쪽에 있다'라고 바꾸어 생각할 수 있겠다.풀이 1(시간복잡도-O(N^2))그러면 다음과 같은 풀이를 생각해볼 수 있지 않을까?먼저 수열의 모든 원소에 대해 모노톤 스택을 활용하여 오큰수와 왼큰수의 위치를 기록해 둔다.이후 각 원소 쌍(A, B)에 대해 'A의 오큰수가 B거나 B의 오른쪽에 있고, B..

7. MVC/MVP/MVVM 패턴

1. 이 패턴들이 해결하고자 하는 문제는 무엇인가?UI가 있는 프로그램을 나이브하게 구현하다 보면 View(화면)쪽에 로직이 몰리는 현상이 발생하기 쉽다.onClick() { if (input invalid) showError() data = api.call() updateUI(data) saveCache(data) logEvent()}이렇게 되면 UI와 로직 간의 결합도가 너무 높아져서 한쪽의 변경이 다른쪽에 영향을 주게 되고, 결국 기능의 추가나 변경이 점점 어려워지는 문제가 발생한다.또한 단순히 코드가 길어져서 가독성이 떨어지기도 한다.이러한 문제를 설계 차원에서 해결하고자 등장한 것이 바로 MVC/MVP/MVVM 패턴이라고 생각하면 될 것 같다.2. MVC 패턴MVC(Model-View-..

6. 이터레이터 패턴

1. 이터레이터 패턴이 해결하고자 하는 문제는 무엇인가?프로그램이 커지면 다양한 자료구조를 사용하게 된다.배열/리스트연결 리스트트리그래프해시 맵커스텀 컨테이너(예: 덱, 카드 덱, 인벤토리)그런데 순회를 직접 구현하게 되면 각 자료구조에 따라 다른 방식을 사용해야 하고, 결국 호출부가 그 자료구조의 내부 구조까지 알아야 한다는 문제가 생긴다.또 자료구조가 바뀌면 호출부의 순회 코드도 수정해야 하고, 동일한 순회 로직이 여기저기 중복된다는 문제가 생긴다.2. 이터레이터 패턴이터레이터 패턴은 위의 문제점을 다음과 같은 아이디어로 해결한다.컬렉션의 내부 구조를 노출하지 않고, 원소들을 순차적으로 접근하는 방법을 이터레이터 객체로 캡슐화한다. 보통 다음과 같은 구조로 구성된다.1. Iterator 인터페이스ha..

5. 프록시 패턴/프록시 서버

1. 프록시 패턴이 해결하고자 하는 문제는 무엇인가?어떤 대상(객체/리소스)에 직접 접근하려고 하면 여러가지 문제가 생길 수 있다보안/권한 문제비용 문제(연결하는데에 시간이 오래걸린다든지..)...즉, 어떤 대상에 직접 접근할 경우, 접근 비용이 크거나(지연/자원), 접근 자체가 제한되어야 하거나(보안/권한), 접근 과정에 공통적인 부가 처리가 필요한 경우가 있다.이러한 문제를 해결하고자 등장한 것이 바로 프록시 패턴이다.2. 프록시 패턴프록시 패턴의 아이디어는 다음의 한 문장으로 정리할 수 있다.실제 객체(RealSubject)와 동일한 인터페이스를 가진 “대리 객체(Proxy)”를 두고,접근 제어/지연 로딩/캐싱/로깅 같은 부가 처리를 프록시에 맡긴 뒤, 필요할 때 실제 객체로 위임한다. 핵심은 호출..

4. 옵저버 패턴

1. 옵저버 패턴이 해결하려고 하는 문제는 무엇인가?게임 프로그램을 만든다고 생각해보자. 플레이어의 HP가 바뀌면 다음의 변화가 일어나야 할 것이다. UI 체력바 갱신데미지 로그 기록업적/퀘스트 체크사운드/이펙트 재생서버 동기화AI 반응근데 이러한 모든 반응들을 다음과 같이 하나의 함수에서 처리한다면 어떨까.class Player { setHp(newHp) { hp = newHp ui.updateHpBar(hp) logger.writeHpChange(hp) achievement.checkHp(hp) server.sendHp(hp) sound.play("hit") }}겉보기에는 하나의 함수에서 다 처리하니까 편해보이지만, 규모가 커지면 바로 문제가 나타난다.1. Pla..

3. 전략 패턴

1. 전략 패턴이 해결하고자 하는 문제는 무엇인가?일단 다음의 코드를 한번 봐보자.class OrderService { pay(type, amount) { if (type == CARD) { ...카드 결제... } else if (type == BANK) { ...계좌 이체... } else if (type == POINT) { ...포인트... } }} 이러한 식으로 코드를 짤 경우 하나의 클래스에 너무 많은 책임이 부여되어 기능의 확장이나 변경을 위해서는 해당 클래스의 로직을 건드려야 하고, 버그가 발생할 위험이 커진다. 또한 코드의 가독성이 떨어지고 테스트가 어려워질 수 있다.즉, 정책(어떤 행동을 할지)와 실행(행동을 수행하는 코드)가 섞이는 것이 문제이다.2. 전략 패턴전략..

2. 팩토리 패턴

1. 팩토리 패턴이 해결하려고 하는 문제는 무엇인가?프로그램의 규모가 커지면 객체를 생성하는 코드(new)가 코드 이곳저곳에 퍼지게 된다.이로 인해 기능을 추가하거나 수정할 때, 객체를 사용하는 코드뿐만 아니라 생성과 관련된 여러 부분을 함께 수정해야 하는 상황이 발생한다.또한 동일한 객체를 생성하더라도, 생성 기준이나 초기화 방식이 각 위치마다 달라질 수 있어 일관성이 깨지고 버그의 원인이 되기도 한다.즉, 객체를 어떻게 생성할지에 대한 책임이 분산되면서 변경에 취약한 구조가 되는 것이 문제이다.2. 팩토리 패턴팩토리 패턴의 아이디어를 한 줄로 정리하면객체 생성을 한 곳으로 모아서, 생성 로직을 캡슐화한다이다.즉 생성 로직을 바꿔도, 나머지 코드에서의 변경 사항을 거의 없애고 호출부는 그저 '무엇이 필..