728x90
반응형

데드락이란 무엇인가?

데드락(Deadlock)은 두 개 이상의 프로세스나 스레드가 서로가 가진 자원을 기다리며 무한히 대기하는 상태(=교착상태)

(외나무 다리의 양 끝에서 서로 비켜주기를 바라는 것과 같은 상태)

 

데드락의 발생 조건

데드락이 발생하기 위해서는 다음 네 가지 조건이 동시에 충족되어야 합니다:

  1. 상호 배제(Mutual Exclusion): 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 합니다.
  2. 점유 대기(Hold and Wait): 자원을 가지고 있는 프로세스가 다른 자원을 기다리고 있어야 합니다.
  3. 비선점(No Preemption): 다른 프로세스가 사용 중인 자원을 강제로 빼앗을 수 없어야 합니다.
  4. 순환 대기(Circular Wait): 프로세스들이 순환 형태로 서로의 자원을 기다리고 있어야 합니다.

 

DB에서 발생하는 데드락 예시

-- Transaction A
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

-- Transaction B
START TRANSACTION;
UPDATE accounts SET balance = balance - 200 WHERE id = 2;
UPDATE accounts SET balance = balance + 200 WHERE id = 1;
COMMIT;

 

이 두 트랜잭션이 다음과 같은 순서로 실행된다고 가정해 봅시다:

  1. Transaction A가 id=1인 계좌의 잠금을 획득합니다.
  2. Transaction B가 id=2인 계좌의 잠금을 획득합니다.
  3. Transaction A가 id=2인 계좌의 잠금을 시도하지만, B가 이미 잠금을 가지고 있어 대기합니다.
  4. Transaction B가 id=1인 계좌의 잠금을 시도하지만, A가 이미 잠금을 가지고 있어 대기합니다.

이 상황에서 두 트랜잭션은 서로가 가진 잠금을 기다리며 영원히 진행하지 못하는 데드락 상태에 빠지게 됩니다.

MySQL은 이러한 데드락을 감지하면 둘 중 하나의 트랜잭션을 강제로 중단시켜 문제를 해결합니다. 하지만 이는 애플리케이션 로직에 예기치 않은 오류를 발생시킬 수 있습니다.

 

데드락을 방지하기 위한 방법

  1. 트랜잭션의 범위를 최소화하여 잠금 시간을 줄입니다.
  2. 모든 트랜잭션이 같은 순서로 테이블에 접근하도록 합니다.
  3. 가능하다면 SELECT ... FOR UPDATE 대신 낙관적 잠금(Optimistic Locking)을 사용합니다.
  4. 트랜잭션 격리 수준을 적절히 조정합니다.

 

결론

데드락은 동시성 프로그래밍에서 흔히 발생할 수 있는 문제입니다. 개발자는 데드락의 발생 조건을 이해하고, 적절한 설계와 프로그래밍 기법을 통해 이를 예방해야 합니다. 특히 데이터베이스 작업에서는 트랜잭션의 설계와 실행 순서에 주의를 기울여야 합니다. 데드락을 완전히 피하는 것은 어렵지만, 그 위험을 최소화하고 발생 시 적절히 대응할 수 있도록 준비하는 것이 중요합니다.

728x90
반응형
728x90
반응형

디자인 패턴이란?

개념 설명: 디자인 패턴은 소프트웨어 개발에서 반복적으로 발생하는 문제들에 대한 일반적이고 재사용 가능한 해결책입니다. 이는 특정 상황(컨텍스트)에서 발생하는 문제에 대한 검증된 해결 방법을 제공합니다.

 

쉬운 설명: 디자인 패턴은 마치 요리 레시피와 같습니다. 특정 요리를 만들 때 따르는 단계별 지침처럼, 디자인 패턴은 특정 프로그래밍 문제를 해결하는 데 사용할 수 있는 검증된 방법을 제공합니다.

 

예시: 일상생활에서의 디자인 패턴을 생각해봅시다. 예를 들어, "리마인더 패턴"이라는 것을 상상해볼 수 있습니다. 출입증을 자주 두고 나가는 문제가 있다면, 문 앞에 "출입증 확인" 스티커를 붙이는 것이 해결책이 될 수 있습니다. 이는 반복적인 문제(출입증을 잊어버림)에 대한 간단하고 효과적인 해결책입니다.

 

디자인 패턴의 중요성

  • 재사용성: 다양한 상황에서 적용 가능한 해결책을 제공합니다.
  • 소통의 용이성: 개발자들 간의 의사소통을 더욱 효율적으로 만듭니다.
  • 올바른 설계 촉진: 초보 개발자들이 좋은 설계 방식을 빠르게 학습하는 데 도움을 줍니다.

 

디자인 패턴의 예: 전략 패턴

 

개념 설명: 전략 패턴은 알고리즘군을 정의하고 각각을 캡슐화하여 교환해서 사용할 수 있도록 만드는 패턴입니다.

쉬운 설명: 전략 패턴은 마치 스마트폰의 케이스를 바꾸는 것과 같습니다. 스마트폰(기본 객체)은 그대로 두고, 필요에 따라 다른 케이스(전략)를 끼워 사용할 수 있습니다.

예시: 자동차 경주 게임을 만든다고 가정해봅시다. 여기서 자동차의 움직임 방식이 다양할 수 있습니다:

  • 항상 움직이는 자동차
  • 항상 멈춰있는 자동차
  • 특정 조건에서만 움직이는 자동차

이럴 때 전략 패턴을 사용하면, 자동차 객체는 그대로 두고 움직임 전략만 교체하여 다양한 동작을 구현할 수 있습니다.

 

디자인 패턴 학습에 대한 조언

  • 기본기 중요: 객체 지향 프로그래밍의 기본 원리를 먼저 잘 이해하는 것이 중요합니다.
  • 단순성 추구: 패턴을 위한 패턴 적용보다는, 현재 상황에서 가장 단순한 해결책을 찾는 것이 중요합니다.
  • 종합적 이해: 패턴의 사용 방법뿐만 아니라, 그 패턴의 기반 원리, 적용 시기, 장단점 등을 종합적으로 이해해야 합니다.

결론

디자인 패턴은 개발자의 강력한 도구이지만, 모든 문제의 만능 해결책은 아닙니다. 상황에 맞게 적절히 사용할 때 그 진가를 발휘합니다. 기본기를 탄탄히 다지고, 실제 문제 해결 과정에서 패턴을 적용해보며 경험을 쌓는 것이 중요합니다.

이렇게 구성하면 독자들이 디자인 패턴의 개념, 중요성, 예시, 그리고 학습 방법에 대해 쉽게 이해할 수 있을 것입니다.

728x90
반응형
728x90
반응형

단일 책임 원칙 (Single Responsibility Principle, SRP)

개념: 하나의 클래스는 하나의 책임만 가져야 한다.

쉬운 설명: 각 부품은 한 가지 일만 잘하면 된다.

일상 예시: 주방에서 칼은 자르는 일만, 냄비는 음식을 담아 조리하는 일만 합니다. 칼에 음식을 담아 끓이려 하거나, 냄비로 음식을 자르려 하지 않죠. 각자의 역할에 충실한 것이 단일 책임 원칙과 비슷합니다.

개방-폐쇄 원칙 (Open-Closed Principle, OCP)

개념: 소프트웨어 개체(클래스, 모듈, 함수 등)는 확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.

쉬운 설명: 기존 코드를 건드리지 않고도 새로운 기능을 추가할 수 있어야 한다.

일상 예시: 스마트폰을 생각해보세요. 새로운 앱을 설치할 때 휴대폰의 운영체제를 변경하지 않습니다. 휴대폰(기존 시스템)은 그대로 두고, 새로운 기능(앱)을 쉽게 추가할 수 있죠. 이것이 바로 개방-폐쇄 원칙의 예입니다.

 

리스코프 치환 원칙 (Liskov Substitution Principle, LSP)

개념: 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.

쉬운 설명: 부모 클래스가 들어갈 자리에 자식 클래스를 넣어도 잘 작동해야 한다.

일상 예시: 커피숍에서 일하는 바리스타를 생각해보세요. 숙련된 바리스타 대신 신입 바리스타가 와도 커피를 만들 수 있어야 합니다. 물론 맛의 차이는 있겠지만, 기본적인 커피 제조 과정은 동일하게 수행할 수 있어야 하죠. 이처럼 대체 가능성을 보장하는 것이 리스코프 치환 원칙입니다.

 

인터페이스 분리 원칙 (Interface Segregation Principle, ISP)

개념: 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안 된다.

쉬운 설명: 불필요한 인터페이스는 구현하지 말고, 꼭 필요한 인터페이스만 구현하라.

일상 예시: 스마트폰의 리모컨 앱을 생각해보세요. TV 리모컨 앱은 TV 제어 기능만 있고, 에어컨 리모컨 앱은 에어컨 제어 기능만 있습니다. 하나의 앱에 모든 가전제품을 제어하는 기능을 넣지 않죠. 이처럼 필요한 기능만 분리해서 제공하는 것이 인터페이스 분리 원칙과 유사합니다.

 

의존관계 역전 원칙 (Dependency Inversion Principle, DIP)

개념: 고수준 모듈은 저수준 모듈의 구현에 의존해서는 안 되며, 저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다.

쉬운 설명: 구체적인 것이 추상적인 것에 의존해야 하며, 변하기 쉬운 것보단 변하기 어려운 것에 의존해야 한다.

일상 예시: 전기 콘센트를 생각해보세요. 콘센트는 어떤 전자기기가 꽂힐지 모르는 추상적인 인터페이스입니다. 전자기기(구체적인 것)는 이 추상적인 콘센트 규격(추상화)에 맞춰 만들어집니다. 콘센트 디자인이 변경되면 모든 전자기기를 바꿔야 하는 상황은 피해야 하죠. 이처럼 구체적인 것이 추상적인 것에 의존하게 만드는 것이 의존관계 역전 원칙입니다.

 

이렇게 SOLID 원칙을 적용하면, 코드의 유지보수가 쉬워지고, 확장성이 높아지며, 재사용성이 증가합니다. 마치 잘 정돈된 주방에서 요리하는 것처럼, SOLID 원칙을 따르는 코드는 개발자가 더 효율적으로 일할 수 있는 환경을 제공합니다.

728x90
반응형
728x90
반응형

서론

객체지향 프로그래밍에서 '추상화 수준'은 코드의 가독성과 유지보수성을 크게 향상시킬 수 있는 중요한 개념입니다. 이 글에서는 추상화 수준이 무엇인지, 왜 중요한지, 그리고 어떻게 적용할 수 있는지 살펴보겠습니다.

 

객체지향 프로그래밍 

객체지향 프로그래밍(OOP)은 소프트웨어 개발의 주요 패러다임 중 하나로, 프로그램을 객체들의 모임으로 구조화하는 프로그래밍 방식입니다. 이 방식은 실제 세계를 모델링하여 소프트웨어를 설계하고 구현하는 데 효과적입니다.

 

객체지향의 핵심 개념

a) 객체(Object): 데이터와 그 데이터를 조작하는 메서드를 하나의 단위로 묶은 것.

b) 클래스(Class): 객체를 생성하기 위한 템플릿 또는 청사진.

c) 캡슐화(Encapsulation): 객체의 내부 구현을 숨기고 외부에서는 정의된 인터페이스로만 접근할 수 있게 하는 개념.

d) 상속(Inheritance): 기존 클래스의 특성을 새로운 클래스가 물려받아 재사용성을 높이는 메커니즘.

e) 다형성(Polymorphism): 같은 인터페이스나 메서드가 다양한 형태로 동작할 수 있게 하는 개념.

 

객체지향의 장점

  • 코드 재사용성 증가
  • 유지보수의 용이성
  • 대규모 프로젝트에 적합한 구조
  • 실제 세계를 모델링하기 쉬움

객체지향과 추상화

객체지향 프로그래밍에서 추상화는 복잡한 시스템을 단순화하고 필수적인 특징만을 강조하는 과정입니다. 이는 불필요한 세부사항을 제거하고 문제의 본질에 집중할 수 있게 해줍니다.

추상화는 인터페이스와 추상 클래스를 통해 구현될 수 있으며, 이를 통해 코드의 유연성과 확장성을 높일 수 있습니다.

추상화 수준과 객체지향

추상화 수준은 객체지향 설계의 품질을 결정짓는 중요한 요소입니다. 적절한 추상화 수준을 유지함으로써, 우리는 객체들 간의 관계를 더 명확히 정의하고, 각 객체의 책임을 적절히 분배할 수 있습니다.

 

추상화와 추상화 수준이란?

추상화는 복잡한 시스템에서 핵심적인 부분만을 골라내는 과정입니다. 객체지향 언어에서는 객체의 공통된 특성을 뽑아 일반화하는 것을 의미합니다.

추상화 수준은 객체나 메서드가 얼마나 일반적이거나 구체적인지를 나타내는 정도입니다. 높은 추상화 수준은 더 일반적이고, 낮은 추상화 수준은 더 구체적입니다.

 

추상화 수준의 중요성

  • 코드 가독성 향상: 같은 추상화 수준의 코드는 읽기 쉽습니다.
  • 유지보수성 개선: 각 객체나 메서드가 한 가지 일만 담당하게 되어 수정이 용이합니다.
  • 테스트 용이성: 작은 단위로 나누어져 있어 단위 테스트가 쉬워집니다.
  • 재사용성 증가: 잘 나누어진 기능은 다른 곳에서도 쉽게 재사용할 수 있습니다.

실제 예시 : 쇼핑시나리오

낮은 수준의 추상화 코드

public void goShopping() {
    walkToStore();
    grabShoppingCart();
    findMilk();
    findEggs();
    goToCheckout();
    payForItems();
    walkHome();
}

이 코드는 너무 구체적이고 한 메서드가 여러 가지 일을 하고 있습니다.

 

높은 수준의 추상화 코드

public void goShopping() {
    Store store = new Store();
    ShoppingCart cart = store.getShoppingCart();
    List<Item> items = store.getItems(Arrays.asList("milk", "eggs"));
    cart.addItems(items);
    store.checkout(cart);
}

이 코드는 각 객체가 자신의 책임만 수행하도록 되어 있어 더 읽기 쉽고 유지보수하기 좋습니다.

 

실제 예시 : 자동차 경주

낮은 수준의 추상화 코드

class Car {
    private int position = 0;
    private IntSupplier powerGenerator;

    public void moveOnGeneratedPowerExceedsThreshold() {
        if (powerGenerator.getAsInt() > 4) {
            position++;
        }
    }
}

 

높은 수준의 추상화 코드

class Car {
    private Position position;
    private PowerGenerator powerGenerator;

    public void move() {
        if (powerGenerator.generatePower() > PowerThreshold.MOVE_THRESHOLD) {
            position.increase();
        }
    }
}

class Position {
    private int value = 0;
    public void increase() {
        value++;
    }
}

interface PowerGenerator {
    int generatePower();
}

 

추상화 수준 개선하기

a) 메서드 추출 : 긴 메서드를 여러 개의 작은 메서드로 나눕니다.

b) 새로운 클래스 도출 : 관련된 책임을 가진 메서드들을 새로운 클래스로 묶습니다.

c) 인터페이스 사용 : 구체적인 구현 대신 인터페이스를 사용하여 추상화 수준을 높입니다.

 

결론

추상화 수준을 일관되게 유지하는 것은 객체지향 프로그래밍의 핵심 원칙 중 하나입니다. 이를 통해 우리는 더 깔끔하고, 이해하기 쉬우며, 유지보수가 용이한 코드를 작성할 수 있습니다. 항상 "이 객체나 메서드가 한 가지 일만 하고 있는가?"를 질문하며 코드를 작성하고 리팩토링하는 습관을 들이면, 자연스럽게 좋은 추상화 수준을 유지할 수 있을 것입니다.

 

출처 : https://www.youtube.com/watch?v=1VwRtsLDiyM&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=4

 

 

 

728x90
반응형
728x90
반응형

인덱스란 무엇인가?

인덱스는 데이터베이스에서 검색 속도를 향상시키기 위해 사용되는 자료 구조입니다. 책의 찾아보기와 유사한 역할을 하며, 원하는 정보를 빠르게 찾을 수 있게 해줍니다.

예를 들어, 도서관에서 책을 찾는 상황을 생각해 봅시다. 인덱스가 없다면 모든 책장을 일일이 살펴봐야 하지만, 도서 분류 시스템(인덱스)이 있다면 원하는 책의 위치를 빠르게 찾을 수 있습니다.

 

인덱스의 작동 원리

인덱스는 주로 B-tree(Balanced Tree) 구조를 사용합니다. B-tree의 주요 특징은 다음과 같습니다:

a) 균형 트리: 모든 리프 노드가 같은 레벨에 있어 검색 성능이 일정합니다.

b) 탐색 트리: 항상 정렬된 상태를 유지하여 빠른 검색이 가능합니다.

c) 다중 데이터 저장: 하나의 노드에 여러 데이터를 저장할 수 있어 효율적입니다.

 

B-tree를 사용하면 데이터를 로그 시간 복잡도(O(log n))로 검색할 수 있어, 전체 데이터를 스캔하는 것보다 훨씬 빠릅니다.

 

인덱스의 종류

a) 클러스터드 인덱스 (Clustered Index)

  • 테이블의 물리적 데이터 순서를 결정합니다.
  • 테이블당 하나만 존재할 수 있습니다.
  • 주로 기본키(Primary Key)에 자동으로 생성됩니다.
  • 데이터 검색이 매우 빠르지만, 데이터 삽입/수정 시 비용이 높을 수 있습니다.

b) 논클러스터드 인덱스 (Non-clustered Index)

  • 별도의 인덱스 구조를 생성합니다.
  • 하나의 테이블에 여러 개 생성이 가능합니다.
  • 인덱스 구조에 실제 데이터의 위치 정보를 저장합니다.
  • 클러스터드 인덱스에 비해 검색은 조금 느리지만, 데이터 변경에 따른 부담이 적습니다.

인덱스 사용의 실제 예시

음식점 정보를 담은 테이블에서 '서울'에 있는 음식점을 찾는 상황을 가정해 봅시다.

  • 인덱스가 없을 때: 전체 데이터(예: 100만 개)를 순차적으로 스캔하며 '서울'인 주소를 찾습니다.
  • 성능: 매우 느림 (모든 데이터를 확인해야 함)
  • 주소에 인덱스가 있을 때:
    1. 인덱스 트리에서 '서울'을 빠르게 찾습니다.
    2. 해당 데이터의 실제 위치를 확인합니다.
    3. 필요한 데이터만 접근하여 결과를 반환합니다. 성능: 매우 빠름 (필요한 데이터에만 직접 접근)

실제 12만 개의 데이터에서 인덱스 사용 전후를 비교한 결과:

  • 인덱스 사용 전: 검색 시간 약 0.44초
  • 인덥스 사용 후: 검색 시간 약 0.02초 (약 20배 성능 향상)

효과적인 인덱스 사용시기

a) 적절한 컬럼 선택:

  • WHERE, JOIN, ORDER BY 절에 자주 사용되는 컬럼
  • 중복도가 낮은 컬럼 (예: 주민등록번호, 이메일 주소)
  • 범위 검색보다는 정확한 값 검색에 사용되는 컬럼

b) 복합 인덱스 고려:

  • 여러 컬럼을 함께 사용하는 쿼리가 자주 실행된다면 복합 인덱스를 고려하세요.
  • 컬럼 순서가 중요합니다. 가장 자주 사용되는 컬럼을 첫 번째로 지정하세요.

c) 인덱스 개수 제한:

  • 너무 많은 인덱스는 오히려 성능을 저하시킬 수 있습니다.
  • 데이터 변경 작업(INSERT, UPDATE, DELETE)시 모든 인덱스를 업데이트 필요. (쓰기가 많은 경우 비추천)

d) 주기적인 인덱스 관리:

  • 사용되지 않는 인덱스는 제거하세요.
  • 필요에 따라 인덱스를 재구성하여 최적의 상태를 유지하세요.

주의사항

  • 인덱스는 검색 성능을 향상시키지만, 데이터 변경 작업의 성능은 저하시킬 수 있습니다.
  • 작은 테이블에서는 인덱스의 효과가 미미할 수 있습니다. (대규모에서 추천)
  • 인덱스는 추가적인 저장 공간을 사용합니다.

출처 : https://www.youtube.com/watch?v=ywYdEls88Sw&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=99

 

728x90
반응형
728x90
반응형

[ 공부배경 ]

개발 공부를 시작하고, 내일배움캠프 끝자락쯤에 도커라는 단어를 들어봤다.

최종프로젝트로 바빠서 뭐하는 기술이지? 궁금해했지만

새로운 기술보다는 프로젝트 마무리가 더 급했다.

이후 프로젝트도 끝나고, 이력서 수백개씩 넣고 취업을 했고 1년이 지났다.

이제 이직준비를 하면서 많은 회사에서 도커와 쿠버네티스 경험을 필요로 한다는 것을 보고 궁금해졌다.

가볍게 유뷰트를 보고 정리해보려고 한다.

 

0. 요약

 

1. 서버와 컨테이너의 개념

  • 컨테이너는 일종의 서버로, 프로그램 소프트웨어가 실행되는 장소이다.
  • 서버는 단순히 하드웨어를 의미하며, 컴퓨터와 유사한 개념으로 이해하면 된다.
  • 모든 회사는 IT 서비스를 제공하기 위해 소프트웨어를 운영한다.
  • 개발자는 자신의 PC에서 소스 코드를 작성하고, 이를 테스트하기 위해 임시 소프트웨어를 실행한다.
  • 개발이 완료된 소프트웨어는 고객에게 서비스를 제공하기 위해 인터넷상 어디선가 실행되어야 한다.
  • 소프트웨어는 회사의 서버룸 또는 클라우드에서 실행될 수 있다.

 

2. 컴퓨터 메모리와 소프트웨어 가상화

  • PC에서 개발되었지만 온라인 서버도 사용 가능하다.
  • 소프트웨어는 일반적으로 2~4GB의 메모리를 필요로 하지만, 서버는 32GB 또는 64GB 메모리를 가지기도 한다.
  • 한 대의 서버에서 여러 개의 소프트웨어를 실행할 때 가상화 기술을 사용하여 효율적으로 운영할 수 있다.
  • 하나의 소프트웨어만 실행하는 경우 64GB 컴퓨터에서 4GB 소프트웨어를 실행하는 것은 비효율적이라고 한다.
  • 그러므로 기업은 가상화 기술을 활용하여 컴퓨터 한 대에서 여러 소프트웨어를 실행시켜 효율성을 높이는데 주력하고 있다.

 

3. 가상화 기술에 대한 이해: 가상머신과 컨테이너 가상화의 차이

  • 서버를 건물로 비유하면, 여러 사람이 사용하는 거주 공간을 분리할 수 있는 기술로 '가상화 기술'이 있다.
  • '가상머신' 방식은 오랫동안 사용됐고, 프로그램을 실행하는 방식으로 VM(가상머신)을 사용한다.
  • 반면 '컨테이너 가상화'는 가상 기술보다 가벼우며 빠르다. 컨테이너는 이사를 하는 것처럼 이동하며, 건물 안에 놓을 수 있다.
  • 가상화 기술에서 컨테이너를 사용하면, 기존 소프트웨어를 더 효율적으로 운영하고 더 많은 소프트웨어를 안전하게 실행할 수 있다.

 

4. 도커 컨테이너 생성 및 관리

  • 건물의 첫 주민이 도착하여 이사하려고 하는데, 도커를 활용한 컨테이너 생성이 필요하다.
  • 개인이 아닌 전문가의 도움(도커)으로 내부 구성물을 효율적으로 건설한다.
  • 도커를 통해 컨테이너를 손쉽게 관리하며, 집콕 전문가가 각 건물을 효율적으로 운영하도록 도와준다.

 

5. 도커와 쿠버네티스 관리

  • 도커를 운영하다 보면 지속적인 운영이 어려워질 수 있기 때문에 쿠버네티스를 고용한다. 쿠버네티스는 다수의 서버를 관리하기 위한 도구로, 오케스트레이션의 도구이다.
  • 쿠버네티스는 마치 다중 서버에서 지휘자처럼 각 서버에서 실행되며 도커에 지시를 내린다.
  • 쿠버네티스는 지능적인 직원으로 각 명령을 하나하나 내릴 필요 없이 컨테이너를 자동으로 관리한다.
  • 도커를 사용하면 서버에 안전하고 안정적인 소프트웨어 구동이 가능하며, 효율적인 컨테이너 관리를 위한 도구인 쿠버네티스를 배운다.

 

[출처] https://www.youtube.com/watch?v=eRfHp16qJq8

 

 

728x90
반응형
728x90
반응형

좋은 코드란 무엇인가?

‘좋은 코드’의 기준이 조금씩 다르고 각각의 경험을 기반으로 좋은 코드를 정의하고 있다. 세간에 좋은 코드의 정의는 정말 많다.

  • 읽기 쉬운 코드
  • 중복이 없는 코드
  • 테스트가 용이한 코드

결론은? 좋은 코드를 왜 작성해야 하는지부터 고민했던 과정을 글로 정리해보았다.

  • 코드 간의 의존성을 고민하자.
  • 합의된 규칙으로 일관성있게 작성하자.
  • 적절하게 확장 가능하도록 설계하자.
  • 어쩔 수 없는 코드는 주석과 함께 격리하자.
  • 답은 테스트 코드 기반의 자동화 테스트다.

 


 

객체지향 프로그래밍 (OOP)

객체 지향적 설계 원칙

  1. SRP(Single Responsibility Principle) : 단일 책임 원칙클래스는 단 하나의 책임을 가져야 하며 클래스를 변경하는 이유는 단 하나의 이유이어야 한다.
  2. OCP(Open-Closed Principle) : 개방-폐쇄 원칙확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.
  3. LSP(Liskov Substitution Principle) : 리스코프 치환 원칙상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다.
  4. ISP(Interface Segregation Principle) : 인터페이스 분리 원칙인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.
  5. DIP(Dependency Inversion Principle) : 의존 역전 원칙고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다.

 


 

RESTful API

 

우선, 위키백과의 정의를 요약해보자면 다음과 같다.

월드 와이드 웹(World Wide Web a.k.a WWW)과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식으로 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반에 대한 패턴

REST란, REpresentational State Transfer 의 약자이다. 여기에 ~ful 이라는 형용사형 어미를 붙여 ~한 API 라는 표현으로 사용된다. 즉, REST 의 기본 원칙을 성실히 지킨 서비스 디자인은 'RESTful'하다라고 표현할 수 있다.

REST가 디자인 패턴이다, 아키텍처다 많은 이야기가 존재하는데, 하나의 아키텍처로 볼 수 있다. 좀 더 정확한 표현으로 말하자면, REST 는 Resource Oriented Architecture 이다. API 설계의 중심에 자원(Resource)이 있고 HTTP Method 를 통해 자원을 처리하도록 설계하는 것이다.

RESTful 하게 API 를 디자인 한다는 것은 무엇을 의미하는가.(요약)

  1. 리소스 와 행위 를 명시적이고 직관적으로 분리한다.
  • 리소스는 URI로 표현되는데 리소스가 가리키는 것은 명사로 표현되어야 한다.
  • 행위는 HTTP Method로 표현하고, GET(조회), POST(생성), PUT(기존 entity 전체 수정), PATCH(기존 entity 일부 수정), DELETE(삭제)을 분명한 목적으로 사용한다.
  1. Message 는 Header 와 Body 를 명확하게 분리해서 사용한다.
  • Entity 에 대한 내용은 body 에 담는다.
  • 애플리케이션 서버가 행동할 판단의 근거가 되는 컨트롤 정보인 API 버전 정보, 응답받고자 하는 MIME 타입 등은 header 에 담는다.
  • header 와 body 는 http header 와 http body 로 나눌 수도 있고, http body 에 들어가는 json 구조로 분리할 수도 있다.
  1. API 버전을 관리한다.
  • 환경은 항상 변하기 때문에 API 의 signature 가 변경될 수도 있음에 유의하자.
  • 특정 API 를 변경할 때는 반드시 하위호환성을 보장해야 한다.
  1. 서버와 클라이언트가 같은 방식을 사용해서 요청하도록 한다.
  • 브라우저는 form-data 형식의 submit 으로 보내고 서버에서는 json 형태로 보내는 식의 분리보다는 json 으로 보내든, 둘 다 form-data 형식으로 보내든 하나로 통일한다.
  • 다른 말로 표현하자면 URI 가 플랫폼 중립적이어야 한다.

어떠한 장점이 존재하는가?

  1. Open API 를 제공하기 쉽다
  2. 멀티플랫폼 지원 및 연동이 용이하다.
  3. 원하는 타입으로 데이터를 주고 받을 수 있다.
  4. 기존 웹 인프라(HTTP)를 그대로 사용할 수 있다.

단점은 뭐가 있을까?

  1. 사용할 수 있는 메소드가 한정적이다.
  2. 분산환경에는 부적합하다.
  3. HTTP 통신 모델에 대해서만 지원한다.

 


 

TDD

Test-Driven Development(TDD)는 매우 짧은 개발 사이클의 반복에 의존하는 소프트웨어 개발 프로세스이다. 우선 개발자는 요구되는 새로운 기능에 대한 자동화된 테스트케이스를 작성하고 해당 테스트를 통과하는 가장 간단한 코드를 작성한다. 일단 테스트 통과하는 코드를 작성하고 상황에 맞게 리팩토링하는 과정을 거치는 것이다. 말 그대로 테스트가 코드 작성을 주도하는 개발방식인 것이다.

 

 

 


 

함수형 프로그래밍

 

함수형 프로그래밍의 가장 큰 특징 두 가지는 immutable data와 first class citizen으로서의 function이다.

immutable vs mutable

우선 immutable과 mutable의 차이에 대해서 이해를 하고 있어야 한다. immutable이란 말 그대로 변경 불가능함을 의미한다. immutable 객체는 객체가 가지고 있는 값을 변경할 수 없는 객체를 의미하여 값이 변경될 경우, 새로운 객체를 생성하고 변경된 값을 주입하여 반환해야 한다. 이와는 달리, mutable 객체는 해당 객체의 값이 변경될 경우 값을 변경한다.

first-class citizen

함수형 프로그래밍 패러다임을 따르고 있는 언어에서의 함수(function)는 일급 객체(first class citizen)로 간주된다. 일급 객체라 함은 다음과 같다.

  • 변수나 데이터 구조안에 함수를 담을 수 있어서 함수의 파라미터로 전달할 수 있고, 함수의 반환값으로 사용할 수 있다.
  • 할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.
  • 함수를 리터럴로 바로 정의할 수 있다.

Reactive Programming

반응형 프로그래밍(Reactive Programming)은 선언형 프로그래밍(declarative programming)이라고도 불리며, 명령형 프로그래밍(imperative programming)의 반대말이다. 또 함수형 프로그래밍 패러다임을 활용하는 것을 말한다. 반응형 프로그래밍은 기본적으로 모든 것을 스트림(stream)으로 본다. 스트림이란 값들의 집합으로 볼 수 있으며 제공되는 함수형 메소드를 통해 데이터를 immutable 하게 관리할 수 있다.

 

 



MVC패턴

다음 링크로 대체

http://asfirstalways.tistory.com/180

 

1. MVC 아키텍쳐에 대한 이해

Things 1. MVC 아키텍쳐에 대한 이해떠도는 여러 이미지들과 책에 나온 구성도를 내 나름대로 재구성해보았다. MVC에 대한 기본 개념은 모두 동일하기 때문에 Servlet과 JSP를 기준으로 설명하여 보다

asfirstalways.tistory.com

 

 


 

깃과 깃허브

 

Git 이란 VCS(Version Control System)에 대해서 기본적인 이해를 요구하고 있다.

Git 을 사용하기 위한 각종 전략(strategy)들이 존재한다. 해당 전략들에 대한 이해를 기반으로 Git 을 사용해야 하기 때문에 면접에서 자주 물어본다. 주로 사용되는 strategy 중심으로 질문이 들어오며 유명한 세 가지를 비교한 글을 첨부한다.

많은 회사들이 GitHub 을 기반으로 협업을 하게 되는데, (BitBucket 이라는 훌륭한 도구도 존재합니다.) GitHub 에서 어떤 일을 할 수 있는지, 어떻게 GitHub Repository 에 기여를 하는지 정리한 글을 첨부한다.

 

 


 

출처: https://github.com/JaeYeopHan/Interview_Question_for_Beginner#%EB%A9%B4%EC%A0%91%EC%97%90%EC%84%9C-%EB%B0%9B%EC%95%98%EB%8D%98-%EC%A7%88%EB%AC%B8%EB%93%A4

 

GitHub - JaeYeopHan/Interview_Question_for_Beginner: :boy: Technical-Interview guidelines written for those who started studying

:boy: :girl: Technical-Interview guidelines written for those who started studying programming. I wish you all the best. :space_invader: - GitHub - JaeYeopHan/Interview_Question_for_Beginner: :boy:...

github.com

 

 

 

728x90
반응형
728x90
반응형

1. Call by value와 Call by reference에 대해 설명해주세요.

자바스크립트에서는 원시 타입(primitive type)의 값은 call by value(값에 의한 호출)로 전달되고,
객체 타입(object type)은 call by reference(참조에 의한 호출)로 전달됩니다.

Call by value는 변수에 저장된 값을 복사해서 전달하는 방식입니다. 
이 방식에서는 변수의 복사본이 전달되므로
함수 내부에서 전달 받은 값을 변경해도 원래 변수의 값은 변경되지 않습니다.

반면에 call by reference는 변수 자체가 전달됩니다. 
이 방식에서는 해당 변수의 주소를 전달하므로 함수 내부에서 
전달 받은 값을 변경하면 원래 변수의 값도 변경됩니다.

Call by value는 변수에 저장된 값을 복사해서 전달하는 방식입니다.
장점은 복사하여 처리하기 때문에 매개변수로 전달된 값이 보존되고 안전합니다.
단점으로는 복사를 하기 때문에 메모리 사용량이 늘어납니다.

call by reference는 변수 자체가 전달됩니다. 
장점은 복사하지 않고 직접 참조를 하기 때문에 실행 속도가 빠릅니다. 
단점은 직접 참조를 하기 때문에 원래의 값이 영향을 받습니다.

 

🔥꼬리질문🔥

<  >

 

 

2. DDD와 MSA에 대해 설명해주세요.

DDD(Domain-Driven Design)는 도메인 주도 설계로 도메인 모델을 중심으로
설계하고 구현하는 것을 의미합니다.

도메인은 사건의 집합이라 생각하고,
여러 도메인들이 서로 상호작용하여 설계하는 것이 도메인 주도 설계입니다.
DDD의 핵심은 도메인을 서비스별로 분리하는 것 입니다.

MSA(Microservice Architecture)는 서비스를 작은 단위의 마이크로서비스로 분리하여
개발하는 아키텍처 패턴입니다. 이는 각 마이크로서비스가 독립적으로 배포 및 확장 가능하도록 설계됩니다. MSA의 핵심은 설계 및 정의할 때는 그 경계를 정하는 것이 핵심입니다.

DDD와 MSA는 객체지향과 많은 관련이 있습니다.
DDD와 MSA는 함께 사용하면 대규모 애플리케이션을 설계하고 개발하는 데 도움이 될 수 있습니다.
DDD를 사용하면 애플리케이션의 도메인 지식을 이해하고
MSA를 사용하면 애플리케이션을 작은 서비스로 분해할 수 있습니다.

 

DDD - 우아한 테크톡

참고 링크

https://huisam.tistory.com/entry/DDD

https://learn.microsoft.com/ko-kr/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/ddd-oriented-microservice

 

🔥꼬리질문🔥

<  >

728x90
반응형

+ Recent posts