Interview Prepare

24 minute read


title: “기술면접 준비 종합” date: 2019-05-21 15:05:28 -0400 categories: jekyll update — 출처 Java Collection Framework

  • Collection
    • List: 순서가 있는 저장 공간
      • LinkedList: 양방향 포인터 구조, 동기화 되지 않음, Deque 인터페이스를 구현함.
      • ArrayList: 단방향 포인터 구조, 순차적인 접근에 강점이 있다. 내부적으로 Object 배열을 필드로 갖는다.
          transient Object[] elementData; // non-private to simplify nested class access
        
      • Vector: 동기화되는 ArrayList
    • Set: 집합적인 저장 공강
      • HashSet: 가장 빠른 임의 접근 속도, 순서를 전혀 에측할 수 없음.
        • LinkedHashSet: 추가된 순서, 또는 가장 최근에 접근한 순서대로 접근 가능
      • SortedSet
        • TreeSet: 정렬된 순서대로 보관하여 정렬 방법을 지정할 수 있음.
  • Map
    • HashTable 동기화를 보장하는 Map 계열의 클래스 키와 값으로 null이 허용되지 않음 Why? HashTable에 데이터를 저장하거나 회수하기 위해서 키로 사용되는 Object들은 반드시 hashCode, equals 메소드를 구현해야한다고 한다. null은 Object가 아니므로 equals나 hashCode 메소드를 호출할 수 없다. 따라서 HashTable이 키로 사용하기 위해서 hash를 계산할 수 없다. ‘Hashtable is old. from JDK 1.0’
    • HashMap 동기화를 보장하지 않는 Map 계열의 클래스(싱글 스레드 환경이고 동기화 요구사항이 없다면 성능이 더 낫다. 동기화를 하는 데에는 비용이 들기 때문임.) 키와 값으로 null이 허용
      • LinkedHashMap Map에 있는 엔트리들의 연결 리스트가 유지되므로 입력한 순서대로 반복이 가능하다.
      • ConcurrentHashMap(출처) 대다수의 경우에 사용되지 않을 null 키와 값을 지원하기 위해 많은 일을 해야하기 때문에, 성능 상의 이유로 null을 허용하지 않는 제한을 두었다.

      HashTable과 마찬가지로 null을 허용하지 않는 주된 이유는 둘 다 멀티 스레드 환경에서 사용될 수 있기 때문이다. null이 허용된다고 가정해보자. get 메소드를 호출 했을 때 모호한 행동을 할 수가 있다. 키가 발견되지 않았을 때나 키가 있지만 값이 null 인 경우 모두 null을 리턴할 것이다. 전자인 경우 KeyNotFoundException 예외를 던지고 후자인 경우 contains 메소드로 키가 있는지 확인 후 get 메소드를 호출한다고 해보자. 다음과 같은 코드가 필요할 것이다.

        if (map.contains(key)) {
            return map.get(key);
        } else {
            throw new KeyNotFoundException;
        }
      

      위 코드는 멀티 스레드 환경에서 깨질 것이다. 즉 thread safe 하지 않은 코드이다.

      thread safe 하지만 전체 테이블에 대한 locking을 지원하지 않는다.

    • SortedMap
      • TreeMap

인성면접

  • 자기소개
  • 지원동기
  • 회사에 대한 정보 수집
  • 본인이 가장 자신있게 생각하는 과목과 관심있는 과목을 말해보세요.
  • 본인이 했던 프로젝트에 대해 구체적으로 설명해보세요.

기술면접

  • 핵데이때 한 것
  • 제출한 서류
  • 지원한 직무 관련하여 질문
  • 손코딩 3-4문제

운영체제

  • 프로세스 스레드
    • 프로세스
    • 스레드
      • 스레드를 왜 사용할까?(출처) 스레드는 경량 프로세스로 불리우는 만큼 프로세스에 비해 자원을 덜 사용한다. 따라서 프로세스에 비해서 스레드간 스위칭은 더 빠르다. 그리고 스레드 간에 공유하는 메모리 공간(heap)이 있어서 스레드 간의 통신이 더 쉽다.
      • 스레드와 공유 자원 사이의 상호작용을 제어할 때는 스레드 동기화 메커니즘을 써야 한다.
        • 모니터 상호 배제 자물쇠로 보호되는 루틴의 집합을 모니터라고 부른다. 개발자의 코드를 상호 배제 하게끔 만든 추상회된 데이터 형태이다. 공유 자원에 접근하기 위한 키 획득과 자원 사용 후 해제를 모두 처리한다. (세마포는 직접 키 해제와 공유자원 접근 처리가 필요하다.)
        • 세마포
        • 카운팅 세마포
        • 이진 세마포(뮤텍스)
      • 식사하는 철학자 기다리는 부분에서 시간 초과 기능을 추가하는 방법
  • 프로세스 간 통신 방식

  • race condition
  • critical section
  • 데드락
  • 멀티스레드 환경에서 신경써야할 부분은?
  • IPC

데이터베이스

  • 데이터베이스에서 Null 의 의미?
    • missing
    • unknown
    • doesn’t apply
  • 쿼리 실행 절차(출처)
    1. 사용자로부터 요청된 SQL 문장을 잘게 쪼개서 MySQL 서버가 이해할 수 있는 수준으로 분리한다. (SQL 파싱)
    2. SQL의 파싱 정보(파스 트리)를 확인하면서 어떤 테이블부터 읽고 어떤 인덱스를 이용해 테이블을 읽을지 선택한다.
    3. 두번째 단계에서 결정된 테이블의 읽기 순서나 선택된 인덱스를 이용해 스토리지 엔진으로부터 데이터를 가져온다.
  • 트랜잭션 동작 원리(출처)
  • 저장 프로시저의 동작 원리
  • 쿼리의 반응속도를 빠르게 하려면 어떻게 해야 하나?
  • Key
    • 후보키 : 유일성 + 최소성 동시에 만족한다.
    • 릴레이션의 후보키(candiate key)를 구성하는 속성들을 prime attribute 라고 한다. 나머지 attribute 들은 non prime attribute이다.
  • 정규화
    • 1NF tuple 의 유일성 attribute 의 원자성
    • 2NF 모든 비주요 애트리뷰트가 주요 애트리뷰트에 대해서 완전 함수적 종속 키가 아닌 컬럼들이 각각의 후보키에 대해 결정되는 릴레이션 형태 if all of its nonkey attributes are dependent on all of the primary keys.
    • 3NF has no determinants except the primary key 이행적 종속성 제거된 형태(비주요 애트리뷰트가 비주요 애트리뷰트에 의해 종속되는 경우가 없는 릴레이션 형태)
    • BCNF if every determinant is a candiate key.
    • 4NF MVD 가 table 당 1개씩만
  • 인덱스 컬럼의 값과 해당 레코드가 저장된 주소를 키와 값의 쌍으로 인덱스를 만들어 두는 것이다. 인덱스는 항상 정렬된 상태를 유지하기 때문에 원하는 값을 탐색하는데는 빠르지만, 새로운 값을 추가하거나 삭제, 수정하는 경우에는 쿼리문 실행 속도가 느려진다.(정렬때문인가?) 인덱스는 데이터의 저장 성능을 희생하고, 대신 데이터의 읽기 속도를 높이는 기능이다.

    인덱스에 걸리는 컬럼의 수가 많아질 수록 데이터 저장 성능이 떨어지고(why?), 인덱스의 크기가 비대해져서 오히려 역효과를 불러올 수 있다.

    • 왜 인덱스에 b-tree 나 b+-tree 를 사용할까요? 하드 드라이브 같은 블록 디바이스에 저장된 데이터를 사용하기 위해서 최적화 된 자료구조이다. 반면 BST는 RAM 에 있는 자료구조를 위해 설계되고 최적화된 것이다. BST는 본질적으로 느립니다. 자가 균형을 하지도 않습니다.

    • 적합하지 않은 곳은?(출처)
      • 읽기보다 쓰기 작업이 많이 발생하는 테이블.
      • 카디널리티(중복도..)가 낮은, 즉 한 필드 내에서 중복되는 값의 개수가 적은 필드라면 사용하지마라. O(logN)의 성능을 살리려면 높은 카디널리티 필드에 대해 인덱스를 활용해야 한다.
      • 작고 고정된 크기의 테이블에 사용하지마라.
    • Composite Index(출처)
  • 레코드 삭제는 fragmentation을 일으킬 수 있다. 2가지 종류의 fragmentation
    1. logical fragmentation
    2. low page density
  • delete 문은 DML 이고, truncate 문은 DDL이다. DML에 대해서만 rollback segments 가 사용된다. delete 는 트랜잭션을 발생시키고, 트랜잭션 로그를 남긴다. truncate 는 트랜잭션을 남기지 않고, 데이터 딕셔너리를 직접 지운다. 트랜잭션 로그를 남기지 않는다. HWM(High Water Mark)(참고1, 참고2)

  • 클러스터링 vs 리플리케이션(출처1) 자동 fail over 나 active stanby 기능… 즉, 1분1초라도 서비스가 멈춰지질 원하지 않는다면 클러스터 리플리케이션은 문제 발생시 단독서버에 비해서 복구가 빠르지만 클러스터에 비하면 서비스가 멈춰 있는 시간이 발생하고 자동 fail over 기능도 없다. 클러스터는 동기화 방식, 리플리케이션은 비동기화 방식이다. 따라서, 리플리케이션은 일방적으로 데이터를 전달하여 복제를 하지만, 클러스터는 데이터를 복제한 후 결과를 확인하기 때문에 데이터 누락이 발생하지 않는다.

  • Query off Loading 처리량을 증가시키기 위한 설계 기법 DB 트랜잭션의 70~90%는 대부분 읽기와 관련된 것이다. 나머지 10~30% 가 create/delete/update와 같은 트랜잭션인데, 이 update 트랜잭션과 read 트랜잭션을 분리하는 기법이다.

    • Master -> Staging -> Slave 로의 복제는 어떤 기술을 사용할까? CDC(Change Data Capture) DBMS 들은 공통으로 C/U/D 와 같은 쓰기 관련 작업을 수행할 때, 데이터를 실제로 저장하기 전에 먼저 해당 작업에 대한 요청을 백로그라는 곳에 저장한다.(백로그는 일반적으로 로컬 파일임) 이는 실제로 데이터를 쓰기 전에 장애가 났을 때, 재시작하면서 이 백로그를 읽어서 복구를 위한 용도로 사용된다. CDC는 이 백로그를 이용해서 데이터를 복제하는데, Source DB로부터 이 백로그를 읽어서 복제하고자 하는 대상 DB에 Replay 하는 형식이다.
  • 샤딩(Sharding) 데이터베이스의 용량 한계를 극복하기 위한 기술이다. 데이터를 여러 개의 데이터베이스에 나눠 담는 방법이다.

    • 수직적(Vertical) 샤딩 연속된 데이터에 대해서 범위 별로 데이터를 나누는 방법 ex) 10대, 20대, … , 80 대의 연령대별로 나누기
    • 수평적(Horizontal) 샤딩 연속된 키가 아니라 ‘Category’와 같은 종류에 따라서 데이터를 수평적으로 분리하는 방법이다. ex) Korea, US, … , China

    이와 같이 의미 있는 데이터를 사용하는 것은 데이터의 몰림 현상이라는 것이 발생할 수 있다. 데이터 몰림 현상을 고려하여 각 샤드 서버의 성능을 비대칭적으로 설계할 수 있다. 데이터가 몰리는 20대, 30대의 샤드에 더 좋은 CPU와 메모리를 갖는 서버를 배치하는 것이다.

      만약, 데이터 편중 현상에 대한 예측이 어렵다면?
          의미 없는 키를 사용해서 샤딩을 할 수 있다.
          레코드를 등록할 때 키를 시퀀스를 이용해서 차례대로 부여한다. 그리고 이 키 값을 10으로 나눈 나머지 값을 가지고 샤드를 결정하면 데이터를 모든 샤드에 걸쳐서 골고루 분산시켜 배치할 수 있다.(해시방식)
    

    샤딩을 구현하는 방법은?

    • DBMS 단에서 샤딩을 지원하는 방법 ex. Azure 페더레이션 모델, MongoDB(1.6부터) 지원하는 DB 수준 샤딩
    • OR Mapper와 같은 DB 접근용 프레임워크에서 샤딩을 제공하는 방법 es. Hibernate Shard
    • 애플리케이션 코드 자체에서 지원하는 방법 키에 따라서 DB 인스턴스를 선택적으로 고를 수 있는 구조를 갖게 하기. 다른 샤드 간의 join 등은 불가능하기 때문에 구현할 때 이에 대한 고려가 필요하다.

    결론. 애플리케이션의 복잡도가 올라가고 데이터가 편중되는 것을 방지하는 등 여러 가지 요소를 고려한 후에 설계, 반영해야 한다.

네트워크

  • OSI 7계층 vs 인터넷 4계층
  • DNS
  • TCP/IP
    • 연결 과정(3 way handshake)
    • 해제 과정(4 way handshake)
  • CDN CDN은 전 세계 여러 데이터 센터에 배치된 리버스 프락시 서버들의 분산 네트워크를 의마한다. CDN의 목적은 고가용성과 고성능을 보장하면서 최종 사용자와 더 가까운 곳에서 콘텐츠를 전송하여 네트워크 왕복 지연을 줄이는 것이다.
  • HTTP/1.1
    • 파이프라이닝 클라이언트가 모든 요청을 동시에 전송할 수 있는 기능이다. 서버는 요청을 동시에 받더라도 여전히 순서대로 응답해야 한다. 이는 어떤 한 요청을 처리하는 데 시간이 오래 걸리는 경우, 이 HOL 블로킹 현상으로 인해 다른 요청들에 대한 응답도 함께 지연됨을 의미한다. (브라우저는 여전히 전송된 순서대로 하나씩 응답을 수신한다.) 이 때문에 웹페이지의 전송과 렌더링이 중단될 수 있다. 요즘 브라우저는 특정 호스트에 최대 6개의 연결을 열고 각 연결로 요청을 전송해 어느 정도 병렬 처리가 가능하다. 하지만 각 연결은 여전히 HOL 블로킹의 영향을 받을 수 있다.

디자인패턴

OOP

  • 클래스? 클래스란 동일한 속성과 행위를 수행하는 객체의 집합이다.
  • 추상화? 어떤 영역에서 필요로 하는 속성이나 행동을 추출하는 작업을 의미한다. 추상화 덕분에 관심이 쏠리는 부분에 더욱 집중할 수 있는 힘을 얻을 수 있다. 사물들의 공통된 특징, 즉 추상적 특징을 파악해 인식의 대상으로 삼는 행위다. 추상화가 가능한 개체들은 개체가 소유한 특성의 이름으로 하나의 집합을 이룬다. 구체적인 사물들의 공통적인 특징을 파악해서 이를 하나의 개념으로 다루는 수단이 추상화다.
  • 캡슐화? 응집도는 클래스나 모듈 안의 요소들이 얼마나 밀접하게 관련되어 있는지를 나타낸다. 결합도는 어떤 기능을 실행하는 데 다른 클래스나 모듈들에 얼마나 의존적인지를 나타낸다. 높은 응집도낮은 결합도를 유지할 수 있도록 설계해야 요구사항을 변경할 때 유연하게 대처할 수 있다. 캡슐화는 특히 낮은 결합도를 유지할 수 있도록 해주는 객체지향 설계 원리다. 캡슐화는 정보은닉(알 필요가 없는 정보는 외부에서 접근하지 못하도록 제한하는 것)을 통해 높은 응집도와 낮은 결합도를 갖도록 한다. 정보은닉은 왜 필요한거야? SW는 결합이 많을수록 문제가 많이 발생한다. 한 클래스가 변경이 발생하면 변경된 클래스에 의존하는 다른 클래스들도 변경해야 할 가능성이 커진다는 뜻이다. 따라서 정보은닉을 통해 알 필요가 없는 정보는 외부에서 접근하지 못하도록 하여 외부 클래스에 대한 결합도를 낮춰야하는 것이다.
  • 일반화? 집합론적 관점에서 일반화는 상호 배타적인 부분 집합으로 나누는 과정으로 간주할 수 있으며, 이를 이용해 상호 배타적인 특성이 요구되는 상황에 일반화 관계를 적용할 수 있다.
  • 다형성? 서로 다른 클래스의 객체가 같은 메시지를 받았을 때 각자의 방식으로 동작하는 능력이다. 다형성은 일반화 관계와 함께 자식 클래스를 개별적으로 다룰 필요 없이 한 번에 처리할 수 있게 하는 수단을 제공한다. 다형성을 사용하는 경우에는 구체적으로 현재 어떤 클래스 객체가 참조되는지와 무관하게 프로그래밍을 할 수 있다.

자료구조&알고리즘

  • 정렬, 서칭
  • 스택, 큐 등 자료구조의 차이점

  • 주소창에 주소 입력 후 일어나는 과정에 대해 설명해보세요.

기타

  • IDE?
  • 블로킹/논블로킹, 동기/비동기

Java

  • volatile(참고)
  • 인터페이스와 추상클래스의 차이? 일반적으로 추상클래스는 그것을 베이스 클래스로 상속해서 더 구체적인 클래스를 만들어서 쓰는 경우에 쓰기 좋다. 특히 서브클래스에서 써먹을 수 있는 공통적인 기능을 추상 베이스 클래스에 집어넣을 필요가 있을 때 좋다. 서로 관련이 없는 클래스에서 개념적으로 연관된 기능을 작동시킬 수 있는 공통된 방식이 필요하지만 그 기능을 구현하는 방법은 제각기 다른 경우에는 인터페이스가 좋다.
  • try-with-resources 란? Java7 부터 AutoCloseable를 구현한 클래스는 자원 종료를 명시적으로 하지 않아도 되게 해준다.
      try(final FileReader reader = new FileReader("/tmp/dataFile")){
          final char[] buffer = new char[128];
          reader.read(buffer);
      } catch (IOException e) {
          // 예외 처리
      }
    
  • String
    • 인터닝(interning) 이란? 클래스가 JVM에 로드되면 모든 리터럴이 상수 풀에 위치하게 된다. 그리고 String 리터럴의 모든 반복은 풀 안의 같은 상수를 참조해서 이루어지는데, 이를 String 인터닝이라고 한다. String 인턴 풀은 컴파일할 때 단지 String 리터럴을 가져오는 게 아니라 intern 메소드를 이용해서 모든 String 인스턴스를 이 풀에 추가한다.
  • 제네릭 매개변수화된 타입이라고도 알려져 있다. 컬렉션 클래스에서 제네릭을 사용했을 때, 컴파일러는 특정 타입만 포함될 수 있게 컬렉션을 제한한다. 실행할 때 발생할 수 있는 잠재적인 모든 예외가 실제 컴파일러 에러로 이어진다. 이러한 예외는 개발 수명 주기에서 훨씬 빨리 발견되어 코드를 신속하게 수정하고 정리할 수 있게 해준다.
  • StringBuffer 와 StringBuilder 의 차이점은? StringBuffer 는 변경 가능하지만 thread-safe 하다. 반면 StringBuilder 는 synchronization 이 적용되어 있지 않아서 thread-safe 하지 않는다.
  • Class objects?
  • main 메소드가 static 인 이유?
  • Object Class
  • Why not static? static 은 객체지향적이지 않다. static 변수는 프로그램이 실행되고 있는 내내 살아있게 된다. 즉, 그 클래스를 이용한 작업을 끝내더라도 static 변수가 점유하고 있는 메모리는 GC에 의해 회수되지 않게 된다. static 은 재사용성이 떨어진다. ; static 메소드는 인터페이스를 구현하는데 사용할 수 없다.(객체지향을 방해함) static variable 로 참조되는 객체는 GC 되지 않는가? 그렇지 않다. static variable을 갖는 클래스 자체가 참조되지 않는다면 GC의 대상이 된다. 그렇다면 언제 클래스 자체가 참조되지 않게 될까? if the application (or framework) dynamically creates a classloader, dynamically loads classes
  • JVM 클래스 로더가 클래스를 메모리에 로드하면 JVM은 바이트코드가 유효한지 검증한다. 검증하고 나면 JVM은 코드가 실행되는 아키텍처와 운영체제에 맞는 명령어로 바이트코드를 해석할 수 있다. 하지만, 이는 처리 시간이 오래 걸릴 수 있고, 일부 초기 JVM에서는 실제로 그랬다고 한다.(특히 GUI 작업에서…) JIT 컴파일러는 동적으로 실행 중인 바이트 코드를 명령어로 변환한다. 그래서 바이트코드를 번역할 필요가 없다. 이렇게 동적으로 실행되면 JIT은 실행되는 동안 애플리케이션의 상태에 따라 높은 최적화 수준을 가진 머신코드를 만들 수 있다.

Java GC

  • JVM Memory types
    • Heap Memory new 키워드는 자바 heap 영역에 메모리를 할당한다. 힙은 애플리케이션 영역에 접근할 수 있는 메모리의 메인 영역이다. 힙은 generation 이라는 몇 가지 영역으로 구분된다. 가비지 컬렉션에서 객체가 수집 대상에서 제외된다면 다른 generation으로 옮겨진다. 클래스 인스턴스와 배열들은 heap 메모리에 저장된다. Shared memory 라고 불린다. 여러 스레드들이 동일한 데이터를 공유하는 장소이기 때문이다.

    • Non-heap Memory
      • Method Area per-class structure(런타임 상수static field를 의미함.), 메소드와 생성자에 대한 코드가 저장된다.
    • Memory Pool heap 이나 non-heap에 속할 수 있다.

    • Runtime Constant Pool 클래스 파일 안에 있는 상수 풀 테이블에 대한 per-class / per-interface run time representation 이다. 각각의 Runtime Constant PoolMethod area에 할당된다.

    • Java Stack 스레드 전용으로 생성된다. 모든 스레드는 PC와 Java Stack을 갖는다. PC는 java stackintermediate values, dynamic linking, return values for methods and dispatch exception을 저장하는데 사용한다.
  • Memory Generations(Young + Old generation) : Heap은 generation이라는 몇 가지 영역으로 구분된다.
    • Young Generation
      • Eden 짧은 기간 동안 살아있는 객체들은 Eden space에서 이용할 수 있다. 모든 객체들은 Eden space에서 생명주기가 시작된다. GC가 일어날 때 객체가 여전히 alive 하면 Survivor space로 이동된다. 참조되지 않는 객체들은 제거된다.
      • Survivor
    • Old Generation(Tenured + PermGen)
      • Tenured: GC는 Survivor space로부터 살아있는 객체들을 tenured generation으로 이동신킨다.
    • PermGen: VM, class, method objects에 대한 메타데이터를 포함한다. 일반적으로 클래스 정의나 String 상수 같이 JVM에서 실행되는데 필요한 불변(immutable) 상태가 포함된다. Java 7 부터 String constant poll의 위치는 Heap 영역으로 변경되었다.(출처1) PermGen 은 고정된 사이즈고 런타임에 사이즈가 확장되지 않는다. 따라서 Java 6 까지는 String의 intern() 메소드 호출은 OOM을 발생 시킬 수 있어서 거의 사용하지 않는 것이 맞다. Heap 영역으로 String constant poll의 위치가 변경됨으로써 문자열도 GC의 대상이 될 수 있게 되었다.(참조 카운트로 따짐) Java 8에서 PermGen 은 물리 메모리에 위치할 Metaspace라는 새로운 영역으로 변경되었다. PermGen은 Java Heap 이었던 적이 없다. 단지 Java Heap 에 연속된 메모리 공간에 할당되어있을 뿐이다. 하지만 Metaspace로 바뀌면서 이런 연속된 메모리 할당은 존재하지 않게 되었다. Metaspace는 운영체제의 native memory에 할당된다.(출처2, 출처)
  • 가비지 컬렉션이란 무엇인가? 프로그래밍 언어에서 효율을 높이기 위해 메모리를 자동으로 관리하는 시스템이다.

    • 가비지 컬렉션 알고리즘? 더 이상 참조되지 않는 메모리를 찾은 후 메모리를 할당할 때 이용할 수 있도록 반환한다는 공통의 목적이 있다. 전통적인 GC는 mark-and-sweep 방식이라고 한다. 실행 중인 코드에서 참조하는 객체는 live로 표시되며 해당 객체에서 참조하는 것들 역시 확인해서 live로 표시한다. 이는 현재 동작하는 객체의 모든 경로가 확인될 때까지 계속된다. 이 과정이 끝나면 Heap에 있는 각 객체들을 찾아다니며 live로 표시되지 않은 메모리 위치에 메모리를 할당할 수 있게 만든다. 과정이 진행되는 동안에는 메모리를 재배치 하려고 JVM의 모든 스레드가 정지되는데, 이를 stop-the-world라고 한다. GC는 이 작업에 소요되는 시간을 최소화하려고 노력한다. Why does the JVM full GC need to stop-the-world? 결국 가비지 컬렉션은 다른 generation으로의 이동과 가능한 한 많은 여유 공간을 남겨두려는 목적으로, 메모리에서 객체들을 옮기고 자주 접근되는 객체들을 묶어두는 등의 다른 연산을 수행한다.(Compaction이라고 한다)

    • 5가지 reachability(출처3)
      • strongly reachable
      • softly reachable 오직 SoftReference 객체로만 참조된 객체는 Heap에 남아 있는 메모리의 크기와 해당 객체의 사용 빈도에 따라 GC 여부가 결정된다.
      • weakly reachable GC를 수행할 때마다 회수 대상이 된다.
      • phantomly reachable GC 대상 여부를 결정하는 부분에 관여하는 softly, weakly 와는 달리 phantomly 는 파이널라이즈와 메모리 회수 사이에 관여한다. finalize 되었지만 아직 메모리가 회수되지 않은 상태이다. 파이널라이즈 이후에 처리해야 하는 리소스 정리 등의 작업이 있다면 유용하게 사용할 수 있다.
      • unreachable root set으로부터 시작되는 참조 사슬로 참조되지 않는 객체
    • GC 대상인 객체를 찾는 작업GC 대상인 객체를 처리하여 메모리를 회수하는 작업은 즉각적인 연속 작업이 아니다. GC 대상 객체의 메모리를 한 번에 모두 회수하지도 않는다.

    • GC 대상 객체를 처리하는 작업(finalize)과 할당된 메모리를 회수하는 작업도 연속된 작업이 아니다.

스프링 프레임워크

  • 빈의 생명주기 InitializatingBean, DisposableBean 인터페이스 구현 or @PostConstruct, @PreDestroy 어노테이션 사용
  • 컨텍스트에서 싱글턴 빈이 제공될 때는 현재 실행 중인 스레드 몇 개가 동시에 해당 인스턴스를 이용한다는 것을 기억해야 한다. 그러므로 모든 연산이 스레드 세이프해야 한다는 것이 매우 중요하다.
  • AutoWiring 애플리케이션 컨텍스트가 클래스 사이의 의존성을 알아내는 과정이다.
  • 의존성 주입과 컴포넌트들이 서로 어떻게 결합되는지?
  • 빈이 어떻게 생성되고, 어떻게 서로 상호작용하는지?

Git

  • rebase 가 뭐야?

프로젝트 관련 정리

  1. Hackday 크롬드라이버 빈으로 만들지 않는다. 빈으로 만들 때 이점이 없다. 배치에서는 빈을 db 접속할 때만 쓴다.

    static 메소드를 어떻게 mocking 하는가? Method Object Pattern을 사용하자.

     private static final MethodObject methodObject = new MethodObject();
     public static void doSomething(){
         methodObject.doSomething();
     }
    
    • 병렬처리할 때 chromedriver 인스턴스는 어떻게 관리할 것인가?
    • 크롬드라이버의 크롤링 과정에서 timeout 발생했을 때 어떻게 처리할 것인가? 재시도를 한다. 하지만 바로 재시도를 하면 같은 원인으로 에러가 날 수 있다. 따라서 일정시간을 기다렸다가 재시도를 한다. 기다리는 시간은 재처리 횟수에 비례해서 늘려주는 게 좋은데, 예를 들어, 첫 번째 에러가 났을 경우 1초 후 재시도, 두 번째는 5초 후, 세 번째는 30초 후 식으로 늘려주면 비즈니스 컴포넌트가 장애에서 복구될 때까지 충분한 시간을 벌 수 있다.
  2. 안기다
    • 왜 Node.js 썼어요? 빠른 개발과 생산성… 팀원들의 기술 스택…
  3. SSMS
    • 데이터베이스 리플리케이션 구축
    • Redis 사용해서 세션 저장소 구축 express-session 의 기본값인 MemoryStore 는 세션 정보를 메모리에 저장하기 때문에 multiple instance 에서는 사용할 수 없다. 따라서 Redis를 세션 정보를 저장하는 공용 저장소로서 사용했고, multiple instance 를 사용하여 무중단 서비스를 구축할 수 있었다.
    • PM2 다중 인스턴스로 무중단서비스 구축

서버 아키텍처

  • failover(출처) 백업 시설로 프로덕션을 스위칭하는 프로세스
  • failback 재난이나 계획된 유지보수 기간 후에 프로덕션을 원래 위치로 되돌려 놓는 프로세스

  • 메시징모델
    • 큐(Queue) 모델 메시지가 쌓여있는 큐로부터 메시지를 가져와서 consumer pool 에 있는 consumer 중 하나에 메시지를 할당하는 방식
    • 발행-구독(pub-sub) 모델 topic 을 구독하는 모든 consumer 에게 메시지를 브로드캐스팅하는 방식이다.

    • 카프카
      • Consumer 와 Consumer Group (출처) 파티션은 consumer group 당 오로지 하나의 consumer 의 접근만을 허용하며, 해당 consumer 를 partition owner 라고 부른다. Consumer 가 추가/제거되면 해당 consumer 가 속한 consumer group 내에서 partition 재분배가 발생하고, broker 가 추가/제거되면 전체 consumer group 에서 partition 재분배가 발생한다. parition 개수와 consumer 수의 적절한 설정이 필요하다.

      • 분산 환경에서 용량뿐 아니라 복사본을 다른 노드에 저장함으로써 노드 장애에 대한 대응성을 가지고 있기 때문에 용량에는 확실하게 강점을 보인다.

      • 파일 시스템을 활용한 고성능 디자인 kafka 는 기존 메시징 시스템과는 다르게 메시지를 메모리 대신 파일 시스템에 쌓아두고 관리한다. 파일시스템을 쓰지만 기존 메시징 시스템보다 더 뛰어난 성능을 보여준다. Why? kafka 는 메모리에 별도의 캐시를 구현하지 않고, OS의 페이지 캐시에 이를 모두 위임한다. kafka 의 메시지는 하드디스크로 부터 순차적으로 읽혀지기 때문에, 하드 디스크의 랜덤 읽기 성능에 대한 단점을 보완함과 동시에 OS 페이지 캐시를 효과적으로 활용할 수 있다. 메시지를 파일 시스템에 저장하여 얻는 부수적인 효과도 있다. 메시지가 JVM 객체로 변환되며 크기가 커지는 것 방지 JVM의 GC로 인한 성능저하 회피 캐시 관리를 OS에 위임하기 때문에, 프로세스를 재시작 해도 OS의 페이지 캐시는 그대로 남아 있다. -> 프로세스 재시작 후 캐시 워밍업이 필요하지 않음 zero-copy 기법을 사용하여 데이터 전송 성능을 향상시켰다. -> 커널모드와 유저모드 간의 불필요한 데이터 복사를 피할 수 있다.

  • Object Storage AWS S3 왜 썼어요? Object Storage는 기존 파일 시스템과는 다르게 OS에서 디스크 형태로 마운트해서 사용하는 것이 아니라, HTTP/REST 와 같은 다른 파일 IO 인터페이스를 사용한다. 다른 인터페이스를 사용하기 때문에 파일 시스템으로의 접근은 OS 에 대한 제약을 받지 않는다. NFS와 같은 공유 파일 시스템은 중앙 컨트롤러를 통해서 접근하기 때문에 컨트롤러 병목에 의해서 동시 접속 클라이언트가 많을 경우 성능 저하가 올 수도 있다. 그러나, 이러한 Object Storage 같은 경우 처음부터 중앙 집중형 접속 포인트를 두지 않고, 아무 노드에나 접속을 가능하게 하는 형태이고, 파일 저장 구조 역시 전체 노드에 걸쳐서 분산해서 저장하기 때문에, 많은 사용자가 동시에 접속하는 대용량 파일 서비스 구조에 적합하다.
  1. Business Layer
    • 스크립트 플랫폼 vs 자바 플랫폼 자바 플랫폼의 경우에는 여러 개의 데이터베이스를 묶어서 단일 트랜잭션으로 처리하는 분산 트랜잭션은 XA(eXtended Architecture) 라는 규격으로 지원해서 복잡한 트랜잭션 관리가 가능하고, 여러 프레임워크를 조합하여 복잡한 비즈니스 로직을 구현할 수 있다.
  • 스레드 풀 클라이언트로부터 요청이 오면 스레드를 미리 만들어 놓은 스레드 풀에서 스레드를 꺼내서 클라이언트의 요청을 처리하게 한다. 처리가 끝나면 스레드 풀로 돌려보낸 후 다른 요청이 오면 다시 꺼내서 요청을 처리하게 하는 구조이다. 동시에 처리할 수 있는 요청의 수는 스레드 풀의 스레드 개수와 같은데, 물리적으로 생성할 수 있는 스레드의 수는 한계가 있다. 즉, 동시에 처리할 수 있는 요청 수에 한계가 있다.

  • IO 효율 클라이언트 요청에 할당된 스레드는 IO 작업(DB, 네트워크, 파일)이 있을 경우 IO 호출을 해놓고 해당 스레드는 CPU를 사용하지 않는 대기(Wait) 상태로 빠져 버리게 된다. 즉, IO 응답 대기(Wait) 상태에서는 스레드를 점유하고 있으면서 아무 일을 하지 않는 비효율성이 발생하게 되는 것이다.

  • C10K 문제 현대의 대용량 서비스는 수만 건의 요청을 처리해야 하는 문제가 있기 때문에 대용량 시스템에서는 일반적인 스레드 풀 기반의 애플리케이션 서버로는 감당이 어렵다. 또는 위에서 살펴본 바와 같이 IO 블록킹 문제로 말미암아 IO 효율 상 성능 저하가 있을 수 있기 때문에, 근래에는 Node.js와 같은 싱글 스레드 기반의 비동기 서버를 사용하기도 한다.

  • Node.js 나 Nginx 는 하나의 스레드만을 사용해서 여러 클라이언트에게서 오는 요청을 처리한다. 단, IO 작업이 있을 경우, 앞에서 설명한 비동기 IO 방식으로 IO 요청을 던져놓고, 다시 돌아와서 다른 작업을 하다가, IO 작업이 끝나면, 이벤트를 받아서 처리하는 구조이다. 싱글 스레드 서버의 문제점은 CPU를 점유하고 무엇인가 작업을 하고 있을 때는 다른 요청을 처리하지 못한다는 것이다. 즉, 요청 처리에 걸리는 시간이 길다면 다른 요청을 처리하지 못하고 지연되기 때문에 CPU 사용량이 많은 로직에는 적절하지 않고, 빠른 처리가 가능한 간단한 로직에는 적절하다.

  • SN 아키텍처 확장성과 안정성을 보장하기 위한 SN(Shared Nothing: 무공유) 아키텍처라는 것이 있다. 분산 처리 시스템을 구성하는 여러 개의 노드가 서로 종속성을 가지지 않고 독립적으로 작동하는 아키텍처로, 종속성이 없기 때문에 이론적으로 노드를 무제한으로 늘릴 수 있으며, 노드 수에 비례하여 전체 시스템의 용량이 늘어나며, 특정 노드의 장애가 전체 시스템에 영향을 주지 않는 아키텍처를 일컫는다.

    노드 간의 종속성을 발생시키는 것이 노드 간의 공유 정보, 즉 상태 정보이다. HTTP 세션 정보가 대표적인 사례 이러한 상태 정보는 애플리케이션 서버의 클러스터링 기능을 이용하여 각 노드 간에 복제 되는데, 이 복제가 종속성을 유발한다. 이러한 공유 상태 정보를 제거해야 SN 아키텍처를 구현할 수 있다.

    상태 정보를 애플리케이션 서버에 저장하지 않으려면 어떻게 해야할까요? 다른 계층에 상태 정보를 저장하면 된다. 가장 쉽게 생각할 수 있는 건, 클라이언트에 상태 정보를 저장하는 방법으로, 쿠키를 사용하는 방법이 있다. 하지만, 쿠키는 저장할 수 있는 정보의 양에 한계가 있다. Memcached와 같은 캐시, 데이터 그리드 계층, NFS와 같은 공유 파일 시스템을 이용할 수 있다.

  • 데이터 그리드를 이용한 상태 정보 저장소 일종의 메모리 클러스터이다. 여러 개의 서버와 메모리를 연결하여 수십 기가의 메모리 저장소를 만들어놓고, 이를 애플리케이션 서버에서 접근해서 사용하는 방식이다. 주로 캐시, HTTP 세션, 사용자 로그인 정보와 같은 상태 정보를 여러 애플리케이션 서버에서 공유하는 등의 용도로 사용된다. 서버 간 클러스터링이 되어 있어서 서버 간에 데이터를 상호 복제하고 있고, 그래서 특정 서버가 장애가 나더라도 자동으로 fail over(장애가 나지 않은 서버가 그 역할을 내려 받음)하기 때문에 장애에 대한 HA를 가지고 있고, 서버를 추가함으로써 전체 용량을 늘릴 수 있는 확장성을 제공한다. 단점은 메모리 클러스터인 만큼 전체 서버가 다운되면 모든 데이터가 날아간다는 휘발성 특징을 갖는다. Redis 의 경우는 메모리에 저장된 내용을 주기적으로 디스크에 저장하고, 또한 클러스터링을 통한 확장을 지원하지 않기 때문에, 엄밀히 보면 데이터 그리드로 볼 수 없고, IMDB로 봐야 한다.

  • 메시지 큐를 이용한 비동기 요청 처리 비동기 방식은 요청을 보낸 후 비즈니스 로직이 처리가 완료되지 않은 상태에서 다음 로직을 진행한다. 비동기 방식은 요청만 보내놓고 응답이 오는 것과 상관없이 클라이언트가 대기 하지 않고 다음 로직을 수행한다. 콜백은 클라이언트에게 비동기로 요청된 작업이 끝났음을 알려주는 호출이다. 주로 시간이 오래 걸리는 대규모 작업에 유리하다. 동영상 인코딩과 같은 변환 작업이나, 시간이 오래 걸리는 계산 작업, 또는 하나의 메시지를 보냈지만 여러 개의 작업이 필요한 경우 이러한 비동기식 패턴 구현에는 일반적으로 메시지 큐라는 것을 사용한다.

    큐는 비동기 처리 솔루션이다. -> 즉, 응답 시간에 그렇게 민감하지 않다.

    • 에러 처리 메시지 큐에서 해당 메시지를 읽어서 처리하는 서버가 장애를 일으켜서 정지하였다고 가정해볼까요? 메시지는 유실되고 처리되지 않게 된다. 메시지 처리 중 에러가 났을 때 해당 메시지를 에러 큐라는 재처리용 쿠로 전달한다. 메시지의 에러 정책을 정해서 에러 처리를 어떻게 할지를 정할 수 있는데, 일반적으로 다음과 같이 크게 4가지 정책을 사용한다.
      1. 재처리(Retry) 다시 처리하도록 시도하는 방법이다. 비즈니스 컴포넌트가 일시적 장애(네트워크 문제, 리소스 부족 등)일 경우에는 효율적으로 사용할 수 있다. 재처리를 할 때, 에러 발생 후 바로 재처리를 시도하면 같은 원인으로 같은 에러가 날 수 있기 때문에 일정 시간을 기다렸다가 다시 처리하는 것이 좋다. 따라서 일정시간을 기다렸다가 재시도를 한다. 기다리는 시간은 재처리 횟수에 비례해서 늘려주는 게 좋은데, 예를 들어, 첫 번째 에러가 났을 경우 1초 후 재시도, 두 번째는 5초 후, 세 번째는 30초 후 식으로 늘려주면 비즈니스 컴포넌트가 장애에서 복구될 때까지 충분한 시간을 벌 수 있다.
      2. 무시(Ignore) 에러가 난 메시지는 무시하고 메시지를 없애 버리는 방식이다. 중요하지 않은 로그 정보를 저장할 때와 같이 메시지 유실이 허용되는 경우에만 사용한다.
      3. 알림(Notify) 메시지 처리 중 에러가 발생했을 때, 이메일, SNS 등을 이용하여 관리자에게 통보하여 관리자가 직접 에러에 대한 후처리를 할 수 있도록 해주는 방식이다.
      4. Human Interaction 에러 발생 시, 자동으로 처리하지 않고 관리자가 직접 처리할 수 있는 사용자 인터페이스를 제공한다. 에러 재처리 부분이 복잡하거나 규모가 큰 경우, 이런 메시지에 대한 에러 처리를 Error Hospital 이라 불리는 별도의 컴포넌트로 구현한다.
    • 비동기 메시지 패턴
    • Fire & Forget 패턴 클라이언트가 호출한 후 큐에 메시지가 제대로 들어갔으면 메시지의 처리 결과에 관계없이 응답을 기다리지 않고 바로 반환한다. 큐에 저장된 메시지는 비즈니스 컴포넌트에 의해 나중에 처리된다.
    • Publish & Subscribe 패턴 메시지 큐에 구독자를 등록하면 클라이언트에서 보낸 하나의 메시지가 등록된 모든 구독자에게 전달되어 처리된다. 1:N 관계의 비동기 처리를 구현하고자 할 때 사용된다.
    • Routing 패턴 큐에 저장된 메시지를 조건에 따라 특정 비즈니스 컴포넌트로 라우팅하는 기능이다. 특정 메시지는 조건에 따라서 특정 비즈니스 컴포넌트 한 개에만 전달된다.
    • Call Back 패턴 비즈니스 컴포넌트에서 처리가 끝나면 서버는 다시 클라이언트에 처리가 끝났다는 응답과 함께 처리 결과(response) 메시지를 콜백으로 보낸다. 서버가 응답 메시지를 보내면 이벤트 핸들러 방식에 의해서 응답 메시지를 처리하는 이벤트 핸들러를 호출하여 응답 메시지를 처리하도록 한다. 부가적인 정보가 필요하다. 1. 콜백 주소: 클라이언트 IP 주소와 포트 2. Correlation ID: 콜백 응답 메시지가 어느 요청에 대한 응답 메시지인지를 식별할 수 있게 해줌.

    • 메시지 큐 구성 시 고려해야 할 사항
    • 성능 및 fail over를 고려한 Persistence의 선택 메모리에 저장하는 모델이 빠르기는 하지만, 서버 장애가 났을 경우 처리되지 않은 메시지들이 유실될 수 있는 위험이 있다. 파일 저장 방식은 비교적 성능은 좋은 편이지만, 여러 개의 메시지 큐를 클러스터링 해서 사용할 경우 클러스터된 인스턴스 중 특정 인스턴스가 죽었을 경우 처리되지 않은 메시지를 살아있는 인스턴스로 넘기기 위해서는 이 파일 시스템이 인스턴스 간에 공유되어야 하는 경우가 있다. NFS와 같은 공유 파일 저장소를 사용해야 하는데 NFS 성능 저하 때문에 전체 메시징 시스템의 성능 저하가 올 수도 있다. RDBMS를 사용하면, 클러스터링 구성 시 Fail Over도 비교적 잘되고, 메시지에 대한 관리도 매우 쉽다는 장점을 가지지만, 3가지 구조 중에서 ` 가장 느리고 추가로 RDBMS 운영이 필요하다는 단점`을 갖는다.
    • 펜딩 메시지로 말미암은 Out of Memory 메시지 큐 미들웨어는 메모리 과다 사용으로 인한 OOM에러에 주의해야 한다. 이렇게 쌓여 있는 메시지들을 펜딩 메시지(Pending Message)라고 하는데, 이 펜딩 메시지에 의한 OOM에러는 메시지 저장소를 메모리로 사용하지 않더라도 발생하는 경우가 있다. 메시지 큐 미들웨어 특성상 성능 향상을 위해서 메시지를 파일이나 RDBMS에 저장하더라도 최소한의 메시지에 대한 메타 정보(메시지 ID와 같은 인덱스 정보)를 메모리에 저장할 때에 발생할 수 있다.
    • 트랜잭션 지원 기능 에러가 났을 경우의 메시지를 다시 큐에 복귀 시키거나, 에러 큐로 보내려면 트랜잭션 지원 기능이 필요하다. 분산 트랜잭션을 지원하는 메시지 큐 시스템은 데이터베이스와 큐의 트랜잭션을 하나로 묶어서 자동을 이러한 작업을 처리하는 반면에, 트랜잭션을 지원하지 않을 때에는 에러가 발생했을 때 개발자가 에러 큐로 메시지를 던지거나 다시 큐에 넣는 작업을 해줘야 한다.
    • 클러스터링 기능 메시지 큐에서 클러스터링이란 여러 개의 메시지 큐를 하나의 클러스터로 묶는 기능을 말한다. 두 가지 관점에서 장점을 생각해볼 수 있다.
      1. 클러스터링을 통해서 특정 인스턴스 장애 시 다른 인스턴스들이 장애가 난 인스턴스의 메시지를 받아서 처리하는 fail over 기능이 있을 수 있다.
      2. 한 대의 서버로 처리할 수 없는 양의 메시지를 여러 대의 서버에서 분산 처리하면서 올 수 있는 장점이 있다.
  • Map & Reduce 기반의 분석 시스템 하나의 큰 데이터를 여러 개의 조각으로 나눠서 처리하는 단계, 어떤 데이터의 집합을 받아들여 새로운 데이터를 생성하는 프로세스 -> Map 처리 결과를 모아서 하나로 합쳐서 결과를 내는 단계 -> Reduce

  • 검색 엔진의 구조
    • 검색 서버의 역할(검색을 하는 시스템) 만들어진 인덱스에서 결과를 뽑아 이용자에게 건내주는 것
    • 검색 백엔드의 역할(인덱스 생성하는 시스템)
      • 크롤링 다수의 크롤러로 웹페이지 수집 임시 저장소 영역에 보관
      • 인덱스 생성 임시 저장소에 저장된 웹 페이지를 꺼내 검색용 인덱스를 만들어 내는 과정
    • 인덱스의 역할 인덱스는 이용자가 앞으로 요청할 온갖 검색 결과들이 가능한 한 미리 계산되어 들어가 있는 것 검색을 위해 필요한 디스크 액세스는 최소한으로 억제해야 한다. -> 인덱스의 크기가 작아야 한다.
  • 마이크로 서비스 아키텍처
    • 장점
      • 배포 유연한 배포 모델이 장점이다. 각 서비스가 다른 서비스와 물리적으로 완벽하게 분리되기 때문에 변경이 있는 서비스 부분만 부분 배포가 가능하다. 변경이 있는 부분만 재배포 하면 되기 때문에, 전체 시스템의 영향을 최소화한 수준에서 빠르게 배포를 진행할 수 있다.
      • 확장성 부하가 많은 특정 서비스에 대해서만 확장할 수 있어서 조금 더 유연한 확장 모델을 가질 수 있다.
    • 문제점
      • 성능 서비스 간의 호출을 API 통신을 이용하기 때문에 값을 JSON 이나 XML 에서 프로그래밍에서 사용하는 데이터 모델로 변환하는 마샬링 오버헤드가 발생하고, 호출을 위해서 이 메시지들이 네트워크를 통해서 전송하기 때문에 그만큼 시간이 추가로 소요된다.
      • 메모리 현대 인프라 환경에서는 크게 문제가 되지 않는다.
      • 어려운 테스팅 테스트 환경 구축이나 문제 발생 시 분리된 여러 개의 시스템을 동시에 봐야 하기 때문에 테스팅의 복잡도가 올라간다.
      • 운영관점의 문제 운영해야 할 대상 시스템의 개수가 늘어나고 필요한 기술의 수도 늘어나게 된다.
      • 서비스 간 트랜잭션 처리 아예 애플리케이션 디자인 단계에서 여러 개의 API를 하나의 트랜잭션으로 묶어 분산 트랜잭션 시나리오 자체를 없애는 방안이다. 보상 트랜잭션? 출금하고 나서 다른 계좌로 이체하던 중 에러가 발생했을 때 명시적으로 돈을 원래 계좌로 돌려주는 에러 처리 로직을 구현해야 한다. 복합 서비스? 트랜잭션을 묶어야 하는 두 개의 시스템을 트랜잭션을 지원하는 네이티브 프로토콜을 이용해서 구현한 다음 이를 API로 노출하는 방법이다.
  • API Gateway 프락시 서버처럼 API들 앞에서 모든 API에 대한 엔드포인트를 통합하고 몇 가지 추가적인 기능을 제공하는 미들웨어이다.
    • 엔드포인트 통합 및 토폴로지 정리 마이크로 서비스 아키텍처의 문제점 중 하나는 각 서비스가 다른 서버에 분리/배포되기 때문에 API의 엔드포인트, 즉 서버의 URL이 각기 다르다는 것이다. API를 사용하는 클라이언트에서 서버 간의 통신이나 API 통신은 P2P 형태로 토폴로지가 복잡해지고 거미줄 모양의 서비스 컴포넌트 간 호출 구조는 향후 관리의 문제를 일으킬 수 있다. 하나의 엔드포인트를 변경하였을 때 제대로 관리가 되지 않을 경우가 있다. 이러한 토폴로지의 문제점을 해결하기 위해 중앙에 서비스 버스와 같은 역할을 하는 채널을 배치 시켜서 전체 토폴로지를 P2P에서 Hub&Spoke 방식으로 변환시켜서 서비스 간 호출을 단순화할 수 있다.
    • 오케스트레이션 여러 개의 서비스를 묶어서 하나의 새로운 서비스를 만든느 개념이다. 예를 들면, 포인트 적립 + 물품 구매 => 물품 구매 시 포인트 적립이라는 새로운 서비스를 만들어 낼 수 있다.
    • 공통 기능 처리 API에 대한 인증이나 로깅과 같은 공통 기능에 대해서 서비스 컴포넌트별로 중복 개발해야 하는 비효율성을 유발할 수 있다. API Gateway 에서 이러한 공통 기능을 처리하게 되면, API 자체는 비즈니스 로직에만 집중하여 개발 중에 발생할 수 있는 중복을 방지할 수 있다.
    • 중재

    • 배포
    • 확장성
    • 컨웨이의 법칙

Updated: