티스토리 뷰

ETC

DB, Framework, Deploy 면접 질문

Dev.Luv 2022. 2. 10. 15:48

1. DB

1.1 DBMS

NoSQL

Mongo db를 물어보셔서, 어떤 애인지 간단하게만 정리한다. NoSQL 데이터베이스는 단순 검색 및 추가 작업을 위한 매우 최적화된 키 값 저장 공간이다.

관계형 데이터베이스에 비해 설계의 단순성을 가지고, 더 단순한 수평 확장(관계형 데이터베이스의 문제)이 가능하다.

NoSQL 데이터베이스에 의해 사용되는 자료 구조(예: 키-값, 와이드 컬럼, 그래프, 도큐먼트)들은 관계형 데이터베이스에서 기본적으로 사용되는 것들과는 다르며 일부 작업들은 NoSQL에서 속도가 더 빠른 편이다.

관계형, 비관계형 DB의 장단점?

참고 링크: database 관계형 DB와 비관계형 DB의 차이점
[DB]SQL(관계형 데이터베이스)과 NoSQL(비 관계형 데이터베이스) 개념/비교/차이

관계형DB

특징

  • 트랜잭션(전부 아니면 무): 전체 트랜잭션이 하나의 단위로 기록. 실패 시 전체 롤백
  • 정규화: DB설계 시 중복을 최소화해서 구조화하는 프로세스

장점

  • 데이터의 성능이 일반적으로 좋아 정렬, 탐색, 분류가 빠름
  • 신뢰성이 높아 데이터의 무결성을 보장
  • 정규화에 따른 갱신 비용을 최소화

단점

  • 기존에 작성된 스키마를 수정하기 어려움
  • 데이터베이스의 부하를 분석하기 어려움
  • 빅데이터를 처리하는데 매우 비효율적임

비관계형 DB

특징

  • 거대한 Map으로서 key-value 형식을 지원함.
  • 관계형 db와 달리 PK,FK JOIN등 관계를 정의하지 않음.
  • 스키마에 대한 정의가 없다.

장점

  • 대용량 데이터 처리를 하는데 효율적임.
  • 읽기 작업보다 쓰기 작업이 더 빠르고 관계형 데이터베이스에 비해 쓰기와 읽기 성능이 빠름.
  • 데이터 모델링이 유연함.
  • 뛰어난 확장성으로 검색에 유리함.
  • 최적화된 키 값 저장 기법을 사용하여 응답속도나 처리효율 등에서 성능이 뛰어남.
  • 복잡한 데이터 구조를 표현할 수 있음.

단점

  • 쿼리 처리시 데이터를 파싱 후 연산을 해야해서 큰 크기의 document를 다룰 때는 성능이 저하됨.

비관계형 데이터베이스의 종류

1–1. NOSQL의 종류
1)키-밸류 스토리지형 키-밸류형: Redis, memcached, Oracle, Coherence,
2)열 지향 와이드 컬럼 스토어: Cassandra, HBASE, Cloud Database
3) 문서형: MongoDB, Couchbase, MarkLogic, PostgreSQL, MySQL, DynamicDB MS-DocumentDB
4) 그래프형: Neo4j

서버리스?

1.2 개념

1,2,3 정규형 설명

  • 정규화: 데이터베이스에서 이상 현상과 중복을 방지하기 위해 분리하는 작업.
  • 이상현상: 삽입이상, 갱신이상, 삭제이상
  • 1정규형: 원자값을 갖는다.
  • 2정규형: 완전 함수적 종속을 만족한다. 부분적 종속이 없어야 한다.
    - 예를 들어 학생, 나이, 선택 과목이라는 column이 있다면 나이는 학생에 대해서만 종속적이기 때문에 학생-나이, 학생-선택 과목으로 테이블을 분리해야 한다.
  • 3정규형: 이행적 함수 종속이 없어야 한다
    - 기본키 외에 다른 컬럼이 그 외의 컬럼들을 결정할 수 없다. 예를 들어 학생의 id라는 기본키를 가진 테이블에서 이름, 거주하는 주, 도시, zipcode라는 colum을 갖고 있다면, zipcode로 인해 주와 도시를 알 수 있어 분리해야 한다. (참고 링크)

DB index

  • 인덱스는 데이터베이스 분야에 있어서 테이블에 대한 동작의 속도를 높여주는 자료 구조를 일컫는다.
  • 인덱스는 테이블 내의 1개의 컬럼, 혹은 여러 개의 컬럼을 이용하여 생성될 수 있다.
  • 고속의 검색 동작뿐만 아니라 레코드 접근과 관련 효율적인 순서 매김 동작에 대한 기초를 제공한다.
  • 인덱스를 저장하는 데 필요한 디스크 공간은 보통 테이블을 저장하는 데 필요한 디스크 공간보다 작다.

책을 예를 들어 설명해보면? 1000 페이지(100페이지씩 10챕터) 중 'Alchemist'라는 단어를 갖고 있는 챕터를 찾기 위해서 나을 때까지 모든 페이지를 Full table scan을 해야 한다.

하지만 index 페이지가 있으면 해당 단어를 찾아 적혀있는 페이지로 바로 이동하면 된다. index가 10장정도라고 할 때 책은 총 1010장으로 페이지수가 증가하긴 하지만, 검색 속도를 빠르게 향상시킬 수 있다는 장점이 있다. (참고 링크)

Thus, the index is a separate section that stores values of indexed column + pointer to the indexed row in a sorted order for efficient look-ups.

내용에 의한 참조

DBMS에서 foreign key를 당연하게 사용하고 있었는데, 막상 왜 쓰는지에 대해서 물어보니 말문이 막혔다. 영문명은 content reference로, 데이터베이스에 있는 데이터를 참조할 때 데이터 레코드의 주소나 위치에 의해서가 아니라 사용자가 요구하는 데이터 내용으로 찾는 것을 말한다.

외래키는 테이블과 테이블을 연결하고, 중복을 방지하기 위해서 사용된다. (참고 링크)

linked list?

면접에서 물어보진 않았지만, DB index를 검색하다 나온 개념이어서 추가 검색.

포인터

프로그래밍 언어에서 다른 변수, 혹은 그 변수의 메모리 공간주소를 가리키는 변수를 말한다. 포인터가 가리키는 값을 가져오는 것을 역참조라고 한다.

2. Framework

2.1 Django

공통점

Queryset을 가져올 때 related objects까지 다 불러와주는 함수다. 불러온 data들은 모두 cache에 남아있게 되므로 DB에 다시 접근해야 하는 수고를 덜어줄 수 있다. 이렇게 두 함수 모두 DB에 접근하는 수를 줄여, performance를 향상시켜준다.

차이점 (참고 링크)

  • select_related
    • 셀렉트할 객체가 역참조하는 single object(one-to-one or many-to-one)이거나, 또는 정참조 foreign key 일 때 사용한다.
    • query에서 JOIN을 사용한다.
    • query를 한 번날리고, prefetch_related에 비해 속도가 빠르다.
  • prefetch_related
    • 구하려는 객체가 정참조 multiple objects(many-to-many or one-to-many)이거나, 또는 역참조 Foreign Key일때 사용한다.
    • query가 아닌 Python에서 joinning을 한다.
    • query를 두 번 하지만, many-to-many 관계를 핸들링할 수 있다.

ForeignKey와 정참조와 역참조

  • FK를 가진 클래스에서 가지지 않는 클래스를 참조할 때는 정참조
  • FK를 가지지 않은 클래스에서 가진 클래스를 참조할 때는 역참조

N+1 쿼리

N+1 Problem은 쿼리 1번으로 N건의 데이터를 가져왔는데 원하는 데이터를 얻기 위해 이 N건의 데이터를 데이터 수 만큼 반복해서 2차적으로 쿼리를 수행하는 문제다. 이 문제의 해결방식으로 Eager-Loading방식이 있다.

어플리케이션에서 한번의 호출로 N개의 모델을 가져온 뒤 N개의 모델을 순회 하면서 각각 모델 관련된 릴레이션 모델에 접근 할 때, DB에 또 다시 호출하게 되는데 이때 N번 호출하게 되어 성능에 좋지 않는 영향을 끼치게 됩니다.

예제 코드(참고 링크)

class Place(models.Model):
    name = models.CharField(max_length=50)
    address = models.CharField(max_length=80)

    def __str__(self):
        return self.name


class Restaurant(models.Model):
    place = models.OneToOneField(Place, on_delete=models.CASCADE, related_name='restaurant')
    name = models.CharField(max_length=50)
    severs_pizza = models.BooleanField(default=False)

    def __str__(self):
        return self.name
        
>>> for place in Place.objects.all():
...     print(place.restaurant.name)
... 
TestRestaruant1
TestRestaruant2
TestRestaruant3
TestRestaruant4
TestRestaruant5
TestRestaruant6

# 쿼리를 찍어봤을 때

[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.000'}, 
{'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.000'},
{'sql': 'SELECT `photo_place`.`id`, `photo_place`.`name`, `photo_place`.`address` FROM `photo_place`', 'time': '0.000'},
{'sql': 'SELECT `photo_restaurant`.`id`, `photo_restaurant`.`place_id`, `photo_restaurant`.`name`, `photo_restaurant`.`severs_pizza` FROM `photo_restaurant` WHERE `photo_restaurant`.`place_id` = 1 LIMIT 21', 'time': '0.000'},
{'sql': 'SELECT `photo_restaurant`.`id`, `photo_restaurant`.`place_id`, `photo_restaurant`.`name`, `photo_restaurant`.`severs_pizza` FROM `photo_restaurant` WHERE `photo_restaurant`.`place_id` = 2 LIMIT 21', 'time': '0.000'},
{'sql': 'SELECT `photo_restaurant`.`id`, `photo_restaurant`.`place_id`, `photo_restaurant`.`name`, `photo_restaurant`.`severs_pizza` FROM `photo_restaurant` WHERE `photo_restaurant`.`place_id` = 3 LIMIT 21', 'time': '0.000'},
{'sql': 'SELECT `photo_restaurant`.`id`, `photo_restaurant`.`place_id`, `photo_restaurant`.`name`, `photo_restaurant`.`severs_pizza` FROM `photo_restaurant` WHERE `photo_restaurant`.`place_id` = 4 LIMIT 21', 'time': '0.000'},
{'sql': 'SELECT `photo_restaurant`.`id`, `photo_restaurant`.`place_id`, `photo_restaurant`.`name`, `photo_restaurant`.`severs_pizza` FROM `photo_restaurant` WHERE `photo_restaurant`.`place_id` = 5 LIMIT 21', 'time': '0.001'},
{'sql': 'SELECT `photo_restaurant`.`id`, `photo_restaurant`.`place_id`, `photo_restaurant`.`name`, `photo_restaurant`.`severs_pizza` FROM `photo_restaurant` WHERE `photo_restaurant`.`place_id` = 6 LIMIT 21', 'time': '0.000'}]

lazy loading

ORM에서 명령을 실행할 때마다 데이터베이스에서 데이터를 가져오는 것이 아니라, 모든 명령 처리가 끝나고 실제로 데이터를 불러와야 할 시점이 왔을 때 데이터베이스에 쿼리를 실행하는 방식이다. (참고 링크)

eager loading

Eager-Loading방식은 사전에 쓸 데이터를 포함하여 쿼리를 날리기 때문에 비효율적으로 늘어나는 쿼리 요청을 방지할 수 있다.

user = User.objects.all()
parent = user.prefetch_related('parent')  # parent를 가져오는 쿼리를 사전에 날림

좋은 글 : 장고에서 쿼리셋 효과적으로 사용하기
Django에서는 QuerySet이 당신을 만듭니다

2.2 Flask

orm 쓰지 않고 raw query사용한 이유

ORM

위 N+1쿼리를 검색하다가 잘 정리한 글이 있어서, 질문 받진 않았지만 넣어본 ORM의 장단점.

장점

  • 객체 지향적인 코드로 인해 더 직관적이고 비즈니스 로직에 더 집중할 수 있게 도와준다.
  • 재사용 및 유지보수에 용이하다.
  • DBMS에 대한 종속성이 줄어든다.

단점

  • ORM으로만 완벽한 서비스를 구현할 수 없다.
  • 프로시저가 많은 시스템에선 ORM의 객체 지향적인 장점을 활용하기 어렵다.
  • 프로젝트의 복잡성이 크면 구현하는 난이도가 상승한다

flask

  • 비주류 프레임워크인데 왜 썼어요?
  • Try catch를 많이 썼던데 데코레이터 왜 안 썼어요?
  • 왜 async.io 썼어요?
  • 비동기 처리하려면 다른거 뭐 쓸 수 있을 것 같아요? (multiprocessing 이라고 대답)

django와 flask의 차이

django는 full stack framework인 반면, flask 가볍고 확장 가능한 framework이다.

3. 배포

3.1 AWS

aws의 주 서비스?

배포 과정 설명

3.2 네트워크

VPC 설정했나요?

CIDR

사이더(Classless Inter-Domain Routing, CIDR)는 클래스 없는 도메인 간 라우팅 기법으로 1993년 도입되기 시작한, 최신의 IP 주소 할당 방법이다. 사이더는 기존의 IP 주소 할당 방식이었던 네트워크 클래스를 대체하였다.

CIDR 기법은 사이더 블록이라 불리는 그룹으로 IP 주소들을 그루핑하고 그룹들을 계층적으로 관리함으로써 기존의 Network Class 방식에 비해 유연하게 동작할 수 있도록하며, IP 주소 체계를 보다 효율화한다.

CIDR 네트웍 주소는 다음과 같은 형태로 나타내어 진다. 192.30.250.00/18

Public IP & Private IP

공인 IP

인터넷 사용자의 로컬 네트워크를 식별하기 위해 ISP(인터넷 서비스 공급자)가 제공하는 IP 주소이다. 공용 IP 주소라고도 불리며 외부에 공개되어 있는 IP 주소이다.

  • 공인 IP는 전세계에서 유일한 IP 주소를 갖는다.
  • 공인 IP 주소가 외부에 공개되어 있기에 인터넷에 연결된 다른 PC로부터의 접근이 가능하다. 따라서 공인 IP 주소를 사용하는 경우에는 방화벽 등의 보안 프로그램을 설치할 필요가 있다.

사설 IP

일반 가정이나 회사 내 등에 할당된 네트워크의 IP 주소이며, 로컬 IP, 가상 IP라고도 한다. IPv4의 주소부족으로 인해 서브넷팅된 IP이기 때문에 라우터에 의해 로컬 네트워크상의 PC 나 장치에 할당된다.


  • TCP 3way handshaking
  • MVC 패턴을 사용했을 때 장점
  • 자바: 컴파일 언어 파이썬:인터프리터 언어

'ETC' 카테고리의 다른 글

하둡(Hadoop) 면접 질문  (0) 2022.02.10
CS 기술면접 면접 질문  (0) 2022.02.10
안드로이드 면접 질문  (0) 2022.02.10
Front End Interview Handbook  (0) 2022.02.10
Tech Interview FOR BEGINNER  (0) 2022.02.10
댓글