Skip to content

면접 준비 자기소개 및 개인적인 cs 지식 정리

적게 된 이유

비전공자로서 개발자로 취업을 하기 위해 2달 동안 준비를 하면서 개인적으로 모아놓은 답변입니다. 조금이나마 도움이 되면 좋을 것 같아서 정리하게 되었습니다. 정답은 아닐지라도 준비해서 더욱 발전하는데 도움이 되면 좋을 것 같아서 적게 되었습니다.

면접 질문 - 답변 포멧

1분 자기소개

만나서 반갑습니다. 0000 백엔드 개발자 포지션에 지원한 이동근 입니다. 저는 개발자로서 커리어 전환을 위해 부트캠프에서 공부를 했고 두 번의 웹 클론코딩과 챗봇을 만든 경험이 있습니다. 챗봇의 기능은 사용자 기반 주변의 영화관을 찾고 그 영화관의 영화시간, 잔여좌석 등의 정보를 전달해 주었습니다. 이렇게 제가 만든 서비스를 누군가가 사용을 해준다는 점에서 더욱 코딩의 매력에 빠지게 되었고 앞으로 많은 공부와 경험을 통해 비즈니스 마인드를 가진 개발자로 성장을 하는게 제 목표입니다.

개발자로서 전향한 이유

개발자라는 직업에 몹시 흥미를 느꼈습니다. 제 손으로 무언가를 만들고 결과물을 생성하는 것에 엄청난 매력을 느끼게 되었습니다. 혼자서 코딩을 할 때보다 함께 코딩을 하면서 배워가는 점도 무척이나 흥미롭고 다른 직업에서는 찾기 힘든 매력이 있다고 생각합니다. 다른 직업군에서는 발견하기 힘든 성장과 희열이 있는 것 같습니다.

다른 질문

지원동기, 해시테이블, 성격의 장단점, 어려운 부분이나, 고난 역경을 극복을 어떻게 했는지, 비전공자로서 가지고 있는 컴플렉스가 있는지, 개발자가 되기위해 어떻게 공부를 하게 됬는지, 앞으로 더욱 공부를 한다던지 배우고 싶은 부분, 회사에 대한 궁금한점, 본인의 가치관, 해당 산업에 대해서 관심을 가지게 된 계기


python

python의 장점

쉽고 간결하다. 그래서 빠른 개발이 가능하다. 빠른 개발은 빠른 배포로 이어져 시장의 피드백을 받을 수 있다. 오픈소스 언어이므로 많은 모듈 등이 존재한다.

python의 단점

인터프리터 언어이기 때문에 속도가 느리다.

기계어와 어샘블리어

이진법(0,1)로 이루어진 언어가 있는데 이를 기계어 라고 한다. 컴퓨터는 이진법만 읽을 수 있다. 기꼐어로 프로그래밍을 하는 것을 무척 어려운 일이기 때문에 숫자를 의미있는 언어로 만들어 사용했는데 이 언어를 어셈블리어 라고 한다.

고급언어와 저급언어

언어가 기계어와 유사할 수록 저급언어 라고 하고, 멀 수록 즉 사람들이 이해하기 쉬울 수록 고급언어라고 한다.

컴파일러와 인터프리터

한 언어를 다른 언어로 옮기는 것을 컴파일러라고 한다(고급언어를 기계어로) 이 컴파일러는 명령들을 전부 모아놓고 한번에 실행 ㅗ딘다. 인터프리터도 컴파일러와 같이 번역기능을 하지만, 컴파일러와 달리 한줄 한줄 읽어가며 명령을 처리하는 방식이다.

참고로 파이선은 인터프리터 c,java는 컴파일러

인터프리터는 개발 편의성은 높지만, 실행 속도가 느림 한 줄 한 줄 기계어로 번역하기 때문, 대신 디버깅이 좋다. 컴파일러는 개발 편의성은 떨어지지만, 실행속도느 빠름 문법오류시 컴파일을 아예 거부함

파이썬의 추상화

스마트폰의 작동원리를 몰라도 스마트폰을 사용할 수 있듯이, 복잡한 내용을 숨기고 주요 기능만 보여주는 것을 추상화 라고한다. 프로그래밍 언어에서는 변수, 함수, 객체를 추상화 역할로 사용한다. 이처럼 복잡한 내용을 숨기고 주요 기능만 보여주는 것을 추상화 라고 한다.

프로그래밍 언어에서는 변수, 함수, 객체를 추상화 역할로 사용한다.

변수는 값을 저장한는 것이고 함수는 명령을 저장하는 것이며, 객체는 변수와 함수를 가지고 있는 것을 말한다.

버그를 찾거나 정적 분석을 할 수 있는 어플리케이션이 있나요?

pychecker, 정적 분석에 사용한다. pylint 파이썬 무듈들이 표준 코딩을 만족하는지 체크

decorator는 언제 사용되나요?

선행적으로 실행이 되야하는 함수가 반복적으로 사용이 되야 할때, 함수의 내부를 수정하지 않고 기능에 변화를 주고 싶을 때 사용한다. 일반적으로 함수의 전처리나 후 처리에 대한 필요가 있을 때 사용한다. 또한 데코레이터를 사용하며, 반복을 사용하여 메소드를 확장한다.

리스트와 튜플의 주된 차이점 은 무엇인가요?

리스트는 mutable하고 튜플은 immutable 합니다.

파이썬에서 메모리 관리는 어떻게 하나요?

파이썬에서는 개별적인 힙을 사용해서 메모리를 유지합니다. 따라서 힙은 모든 파이썬 객체와 자료구조를 가지고 있습니다. 이 영역은 파이썬 인터프리터만이 접근가능하며 프로그래머는 사용할 수 없습니다.

파이썬은 가비지 컬렉터를 통해서 비사용되는 메모리에 대해서 힙공간을 관리합니다.

가비지 콜렉터(Garbage collector = GC)

GC는 모던한 언어에게는 필수적을 탑재가 되어있다. JAVA, PYTHON까지 우리는 응용프로그램을 돌리면서 수많은 메모리를 생각없이 사용해 왔습니다. 자동으로 GC가 해주니까

메모리를 직접 관리해주게 되면 애로사항이 있다. 필요없는 메모리를 비워주지 않으면 메모리 누구사 이어지고 이에 치명적인 문제가 될 수있다. 사용 중인 메모리를 비워버리면, 프로그램은 중단되고, 일부 데이터가 손상 될 수 있습니다.

파이썬에 내장된 메모리를 관리하는 방법에는 GC, 레퍼런스 카운팅이 있습니다.

레퍼런스 카운팅

우리가 객체를 만들 때 마다 그 객체가 사용이 되고 있는지 카운팅을 하기 시작한다. 객체가 참조될 때 마다 증가가 되고

Lamdbd와 Def의 차이

def는 다중표현을 갖고 lambda는 단일함수 입니다. Def는 함수를 생성하고 이름을 지정하여 나중에 다시 호출합니다. Lambda는 함수 객체를 구성하고 반환합니다. Def는 선언 할 수 있지만, Lambda는 할 수 없습니다.

Docstring

파이썬의 모듈, 함수, 클래스, 매소드의 정의에 처음 부분에 선언되는 유니크한 텍스트 입니다.

function call 혹은 A Callable Object는 무엇인가요?

파이썬에서는 함수는 호출가능한 객체로 취급이 됩니다.

call by value, call by reference

call by value

함수의 인자를 받을 때, 변수에 담긴 값 자체를 stack에다가 복사하여 넘겨준다. 예를 들어 변수 a가 있고, 함수 def1이 있을 때 def1(a)에 전달 받은 a의 값은 a의 자체 값이 아니라 a의 레플리카 이다. 따라서 함수 내에서 해당 인자를 조작하여 바꾸었다 하더라도, 원본 a는 변하지 않는다. 원본을 건드리지 않아 안전하지만 함수의 사용으로 해당 전역 변수를 바꾸고 싶을 때는 리턴 값을 다시 전역 변수로 집어넣어야 하는 번거로움과, 시간 사용의 단점이 있다.

call by reference

함수의 인자를 받을 때, 변수가 가리키는 주소 값을 전달 한다. 변수 a가 있고 함수 def2가 있을 때 def2(a)는 a의 주소 값이기 때문에 함수 내에서 해당 인자를 조작하면 원본 변수의 주소 값으로 타고 들어가 해당 값 자체를 바꿔 버린다.

그럼 python은 두 개중에 무엇인가? -> call by assignment 또는 call by object-reference

python의 경우는 위의 경우 처럼 주소 값 참조나, 값 복사와는 다른다. -> python은 모든 것을 객체로 판단하기 때문이다.

파이썬에서 변수를 선언 할 때 a = 'aplace'라고 변수를 선언 하게 되면 'aplace'라는 문자열 객체가 생기고, a라는 이름표를 가지게 된다. python는 위의처럼 메모리에 공간을 할당받은 메모리가 아니라, 어떤 객체에 붙혀지는 이름표 이다.

파이썬에서는 global인지, local인지 영역에 따라 변수들의 정보를 저장하는 namespace가 따로 있다. 즉 전역변수를 함수에서 인자로 받아오더라도 함수 내에서는 지역변수(이름표)에 불가 하다.

예를 들어 전역변수로 list1=[1,2,3,4]라고 지정을 해놓고 함수 내에서 list=[5,6,7,8]로 지정을 해도, 함수가 끝나면 list1 은[1,2,3,4]이다.

그래서 전역 변수를 함수 인자로 받아오더라도 함수 내에서는 지역변수(이름표)에 불가하다.

하지만 그래서 immutable 한 포멧의 객체는 변경 할 수 없지만, mutable한 포멧의 객체는 변경 할 수 있다. 라고 할 수 있습니다.

*Args

N개의 매개변수를 넘기겠다는 표시입니다.

Kwargs는 무엇을 하나요?

N개의 변수를 파라미터를 넘기겠다는 것인데 이름 혹은 키워드를 가지고 있습니다.

파이썬에서 Mani() 메소드가 있나요?

파이썬은 인터프리터 언어이기 때문에 일반적으로는 code by code로 실행 됩니다. 현재 모듈 이름을 확인하는 방식으로 main함수를 사용할 수 있습니다.

GIL은 무엇인가요?

Global Interpreter Lock으로 파이썬 객체가 다중 스레드에 동시에 실행되지않도록 하는 것입니다.

파이썬에서 쓰레드의 안정성은

파이썬에서는 쓰레드에 대해 안정성 있는 접근을 보장합니다. 이를 위해서 GIL을 사용합니다. 만약 쓰레드가 GIL Lock을 잃었을 경우에 스레드로부터 코드를 안정성있게 만들어야 합니다.

파이썬에서는 어떻게 메모리를 관리하나요?

파이썬에서는 내부적으로 힙 매니저가 구현되어 있습니다. 힙 매니저는 모든 오브젝트와 자료구조를 가지고 있습니다. 또한, 힙매니저는 오브젝트에 대한 힙 스페이스의 할당과 할당 해제를 합니다.]]

파이썬에서 튜플은 무엇인가요?

튜플은 Collection 데이터 타입의 하나로 immutable한 자료형 입니다. 리스트와 비슷한 구조를 갖지만 수정이 가능하냐 안하냐느 차이가 있습니다.

파이썬에서 딕셔너리는 무엇인가요?

딕셔너리는 collection 데이터 타입의 하나로 key와 value의 구조로 이루어진 데이터 입니다. 해쉬, 맵 혹은 해쉬맵 이라고도 불립니다.

파이썬에서 Set은 무엇인가요?

Set은 순서가 없는 (Unordered)한 collection 데이터 객체의 하나로 유니크한 원소들만을 갖습니다.

파이썬의 딕셔너리는 어떻게 사용되나요?

딕셔너리 타입은 하나의 그룹(key)와 다른 그룹 (value)을 매핑하기 위해서 사용될 수 있습니다.

파이썬의 리스트는 연결리스트(Linked list) 인가요?

파이선의 리스트는 배열로 C스타일의 연결리스트와는 다릅니다. 내부적으로 다른 객체를 참조하기 위한 연속적인 배열을 가지며, 배열 변수에 대한 포인터와 그 길이를 목록 헤드 구조에 저장합니다.

파이썬에서 클래스는 무엇인가요?

파이썬은 객체지향 프로그래밍을 지원하며 거의 모든 OOP특징을 사용할 수 있도록 제공합니다. 파이썬의 클래스는 객체를 만들기 위한 청사진 입니다.

class의 Attribute와 Methods는 무엇인가요?

기능을 정의하지 않은 클래스는 쓸모가 없습니다. 속성을 추가하므로 이 문제를 해결 할 수 있는데 속성은 데이터와 기능을 위한 컨테이너 역할을 합니다. 또한 Attribute를 직접 class내부에 추가 할 수 있습니다.

Attribute에 관하여

속성은 클래스 내부에 포함 되어 있는메서드나 변수를 의미합니다. python에서 속성은 크게 클래스 속성과 인스턴스 속성으로 나뉩니다. 클래스 속성은 클래스 내부의 메소드 단계와 동일한 영역에 위치한 변수를 의미합니다. 클래스 속성에 접근할 경우, 모든 클래스에 동일하게 영향을 미칩니다.

인스턴스 속성은 self를 통해 할당된 인스턴스만의 변수를 의미합니다. 주로 init이나 메서드 내부에서 할당된 변수를 의미합니다.

클래스 속성 메서드와 동일 단계에 작성하게 됩니다. self를 사용하지 않고 정의합니다. 그러므로 모든 클래스에 동일하게 영향을 미칩니다. 인스턴스가 생성될 때 초기화되지 않으므로, 클래스명.클래스 속성으로 참조가 가능합니다.

인스턴스 속성 인스턴스를 초기화 할 때 생성됩니다. self를 사용해 정의합니다. 인스턴스 내에서만 영향을 미칩니다.

런타임에 클래스 속성에 값을 할당하는 방법은 무엇인가요?

클래스에 init메소드를 추가하고 최초에 변수를 입력해 줍니다.

파이썬에서 상속은 무엇인가요?

상속이란 OOP에서 객체가 부모 클래스의 특징에 접근할 수 있는 것을 말합니다.

python composition

파이썬 상속의 한 종류로 기본클래스에서 상속을 하지만 파생 클래스의 멤버 역할을 하는 기본 클래스의 인스턴스 변수를 사용합니다.

파이썬에서 Erros와 Exceptions는 무엇인가요?

Erros는 코딩 이슈로서 프로그램이 비정상적으로 종료되게 됩니다. Exceptions는 외부적인 이벤트로 인해 발생하는 것으로 인터럽트 같은 경우가 있습니다.

파이썬의 iterators는 무엇인가요?

iterators는 배열과 같은 객체로서 next()로 다음 구성 성분으로 이동하는 것이 가능한 것을 의미한다.

iterators(반복자)와 itrables의 차이는 무엇인가요?

iterable의 의미는 member를 하나씩 차례로 반환 가능한 object를 말합니다. iterable의 예로는 sequence type인 list, str, tuple이 대표적입니다.

리스트, 튜플, 딕셔너리 및 세트와 같은 컬렉션 유형은 모두 반복 가능한 객체인 반면 순회하는 동안 반복자를 반환하는 반복 가능한 컨테이너이기도 합니다.

그럼 list는 iterable(하나로 차례로 반환 가능한 object)하지만 iterator는 아니다.

generator는 무엇인가요?

iterator를 생성해주는 function이다.(iterator는 next() 메소드를 이용해 데이터에 순차적으로 접근이 가능한 object이다.) yield를 사용해 값을 반환한다.

yield를 만나게 되면 해당 함수는 그 상태로 정지되며, 반환 값을 next()를 호출한 쪽으로 전달하게 된다. 함수에서 사용된 local 변수나 instruction pointer 등과 같은 함수 내부에서 사용된 데이터들이 메모리에 그대로 유지되는 것이다.

왜 generator를 사용하는가?

먼저는 memory를 효율적으로 사용할 수 있다.

list는 list안에 속한 모든 데이터를 메모리에 적재하기 때문에 list의 크리 만큼 차지하는 메모리 사이즈가 늘어나게 된다. 하지만 generator의 경우 데이터 값을 한꺼번에 메모리에 적재하는 것이 아니라 next() 메소드를 통해 차례로 값에 접근할 때마다 메모리에 적재하는 방식이다.

lazy evaluation 즉 계산 결과 값이 필요할때 까지 계산을 늦추는 효과를 볼 수 있다.

Enumerate는 무엇인가요?

iterators와 함꼐 사용 가능한 것으로 iterators의 횟수를 셀 수 있습니다.

globals()

global로 정의된 변수들을 딕셔너리 테이블 처럼 반환 할 수 있습니다.

'self'는 어떤 키워드 인가요?

self는 객체 인스턴스가 가지고 있는 변수들을 나타냅니다.

파이썬 프로그램에서 어떻게 코드를 디버깅 하나요?

python debugger를 사용하면 됩니다.

pypy

유연함과 쉬운 실험을 위해 파이썬 프로그래밍 언어 자체로 작성된 파이썬 구현체이다. 이 프로젝트의 목적중 하나는 최적화된 PyPy의파이썬 구현이 현재의 C구현보다 빠르도록 하는 것이다.

Cpython

C와 python으로 작성된 C파이썬은 이 언어에 가장 널리 사용되는 기본 구현체이다. C파이썬은 인터프리트과정 이전에 파이썬 코드를 바이트 코드로 컴파일 하기 때문에 인터프리어티이기도 하고 컴파일러이기도 하다.

Operating System

커널(kenel)

컴퓨터의 운영 체제의 핵심이 되는 컴퓨터 프로그램의 하나로, 시스템의 모든 것을 완전히 통제한다. 운영체제의 다른 부분 및 응용 프로그램 수행에 필요한 여러가지 서비스를 제공한다.

프로그램

파일이 저장 장치에 저장되어 있지만 메모리에는 올라가 있지 않은 정적인 상태를 말한다.(다시 말해 프로그램이라는 단어는 아직 실행되지 않은 파일 코드 그 자체를 의미한다.)

여기서 프로그램이 실행이 되면 정적인 프로그램 상태에서 동적인 상태로 바뀌게 되고 이 상태를 프로세스 라고 한다. 메모리에 프로그램을 할당을 해준 것을 의미한다.

시간이 흐를수록 프로세스가 복잡해지면서 프로세스 하나만을 사용해서 프로그램을 실행하기에는 벅차게 되었다. 운영체제는 안전성을 위해 프로세스마다 자신에게 할당된 메모리 내의 정보만 접근할 수 있게 해놨다. 이를 벗어나면 오류가 발생한다.

이런 프로세스 특성의 한계를 해결하기 위해 나온 것이 스레드

스레드는 프로세스의 코드에 정의된 절차에 따라 실행되는 특정한 수행 경로다.

프로세스와 스레드의 차이

프로세스는 운영체제로 부터 자원을 할당받은 작업의 단위 이고 스레드는 프로세스가 할당받은 자원을 이용하는 실행 흐름의 단위 이다.

스레드는 프로세스 안에 포함이 되어 있어 개념의 범위 부터가 다르다. 운영체제가 프로세스 안에 stack, heap, data, code 메모리 영역을 할당해 주는 반면 Stack의 메모리 영역을 제외한 다른 메모리 영역을 같은 프로세스 내 다른 스레드와 공유한다.

스레드는 기본 구조 자체가 메모리를 공유하는 구조이기 때문에 다른 스레드와의 정보 공유가 쉽다. 때문에 멀티태스킹 보다 멀티 스레드가 자원을 아낄 수 있다

멀티 프로세스 대신 멀티 스레드를 사용하는 이유

우선 기본적으로 프로세스는 서로 간의 접근이 안된다 하지만 IPC, LPC를 사용하면 접근 가능해서 사용가능하다. 하지만 이런 멀티프로세스를 사용하기 위해 이런 번거로운 것을 하기 보단 원래 접근이 가능한 스레드로 멀티 스레드를 사용하는 것이 더욱 효율적이고 자원을 아낄 수 있다. 하지만 운영체제의 가장 작은단위가 프로세스 이기때문에 스레드의 동기화가 일어나게 될 경우 프로그래머가 처리를 해줘야 한다.

Thread safe

멀티 스레드 프로그래밍에서 일반적으로 어떤 변수, 혹은 객체가 여러 스레드로부터 동시에 접근이 이루어져도 프로그램의 실행에 문제가 없음을 뜻한다.

동기화 객체의 종류

커널에서 제공하는 객체로서 스레드 사용시 문제되는 자원의 공유시 충돌에 대한 해법을 제시하는 것을 의미한다. 크리티컬 색션 - 주요 보호 대상은 전역 객체이고 Lock, UnLock를 사용하여 자원의 동기화를 유지시킨다. 뮤텍스 - 스레드 동기화 + 프로세스 동기화 세마포어 - 한번에 스레드의 접근만 가능하게 하는 위의 동기화 객체와는 달리 동시에 스레드의 접근을 허용할 수 있도록한다.

뮤텍스와 세파모어의 차이

뮤텍스는 동기화 대상이 오직 하나뿐일 때, 세파모어는 동기화 대상이 하나 이상일 때 사용한다. 세파모어는 시스템 범위에 걸쳐있고 파일 시스템 상의 파일 형태로 존재한다. 반면 뮤텍스는 프로세스 범위를 가지며 프로세스가 종료될 떄 자동으로 해제 된다.

스케쥴링

다중 프로그래밍을 가능하게 하는 운영체제의 동작 기법이다. 운영 체제는 프로세스들에게 CPU 등의 자원 배정을 적절히 함으로써 시스템의 성능을 개선할 수 있다.

동기와 비동기

동기는 상담원 으로 비교할 수 있다. 상담원은 한 개의 상담이 끝나야지만 다른 상담을 처리할 수 있듯이 요청에 대한 응답이 와야지만 다른 요청을 보내는 것을 동기 라고 합니다. 하지만, 비동기는 인터넷 이메일 처럼 이메일에 대한 답신이 오지 않아도 다른 이메일을 보낼 수 있는 것처럼, 요청에 대한 응답이 오지 않더라도 다른 요청을 보낼 수 있는 것을 의미합니다.

프로세스 동기화란?

여러 프로세스가 공유하는 자원의 일관성을 유지하는 것이다. 가령 여러 프로세스가 동시에 하나의 공유된 자언에 접근하려고 할 때 이 프로세스들의 순서를 정하여 데이터의 일관성을 유지시켜줘야 한다. 공유하는 자원의 일관성을 유지하는 것이다. 가령 여러 프로세스가 동시에 하나의 공유된 자원에 접근하려고 할 때 이 프로세스들의 순서를 정하여 데이터의 일관성을 유지시켜주어야 한다.

가상메모리?

한정된 크기의 메모리 내에서 최대한 많은 프로세스를 할당하여 효율적으로 사용하기 위해 만든 기술로 간단히 말하자면 보조기억장치를 주기억장치처럼 사용할 수 있게 하는 기술이다.

메모리 관리 전략

메모리는 CPU가 직접 접근하는 유일한 저장장치로 메모리 시스템(하드웨어)은 주소(메모리 위치)를 관리하며 할당과 접근을 제어한다.

Overhead

어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 메모리 등을 말한다.

관리전략-swap

CPU에서 실행 중이지 않은 프로세스의 메모리 이미지를 저장장치에 이동(메모리 사용의 효율성 증가) 단점 : Contexting-switching overhead: 해당 CPU는 아무런 일을 하지 못한다 따라서 Context switching이 잦아지면 오히려 overhead가 발생해 효율이 떨어진다.

관리전략-연속메모리 할당

각 프로세스가 필요로 하는 메모리 요구량을 분석해서 필요한 메모리를 연속으로 메모리에 할당하는 방식 동적 메모리할당: 어떤 프로세스가 실행했을 때 이 프로세스가 들어갈 적당한 곳을 찾아 할당하는 것

메모리 할당 정색 연속할당 - 주소 변환이 매우 간단하지만 단편화 문제가 많이 발생(고정된 크기로 분할, 가변분할) 비연속 할당 - 연속 할당에 비해 단편화 문제는 적지만 주소변환이 복잡(페이징, 세그멘테이션)

캐시의 지역성

캐시는 CPU의 처리속도와, 메모리의 처리속도차에 따른 병목 현상을 줄이기 위한 범용 메모리이다. 이러한 역할을 수행하기 위해서는 CPU가 어떤 데이터를 원할 것인가를 어느 정도 예측할 수 있어야 한다. 캐시의 성능은 작은 용량의 캐시 메모리에 CPU가 이후에 참조할, 쓸모 있는 정보가 어느 정도 들어있느냐에 따라 좌우되기 때문이다.

이때 적중률(Hit rate)을 극대화 시키기 위해서 데이터(지역성)의 원리를 사용한다. 지역성의 전제조건으로 프로그램은 모든 코드나 데이터를 균등하게 Access 하지 않는다는 특성을 기본으로 한다.

지역성이란 기억 장치 내의 정보를 균일하게 Access하는 것이 아닌 어느 한 순간에 특정 부분을 집중적으로 참조하는 특성인 것이다.

시간 지역성 - 최근에 참조된 주소의 내용은 곧 다음에 다시 참조되는 특성 공간 지역성 - 대부분의 실제 프로그램이 참조된 주소와 인접한 주소의 내용이 다시 참조되는 특성

캐시 라인(caching line)

캐시는 프로세서 가까이에 위치하면서 빈번하게 사용되는 데이터를 놔두는 장소이다. 하지만 캐시가 아무리 가까이 있떠라도 찾고자 하는 데이터가 어느 곳에 저장되어 있는지 몰라 모든 데이터를 순회해야 한다면 시간이 오래 걸리게 된다. 그래서 캐시에 데이터를 저장할 때 특정 자료구조를 사용하여 묶음으로 저장하게 되는데 이것을 캐싱 라인 이라고 한다.

교착상태(deadlock)

두 개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리고 있기 때문에 결과적으로 아무것도 완료되지 못하는 상태를 가리킨다.

사용자 수준 스레드와 커널 수준 스레드의 2가지 차이점은 무엇인가?

메모리 영역은 사용자에 의해서 할당되는 메모리 공간인 유저 영역과 운영체제라는 하나의 소프트웨어를 실행시키기 위해서 필요한 메모리 공간인 커널 영역으로 나뉜다.

커널 모드와 유저 모드를 제공하는 대상은 Window운영체제가 아니라 프로세서 이다. 커널 레벨 쓰레드와 유저 레벨 쓰레드는 생성 주체가 누구냐에 따라 구분된다. 프로그래머 요청에 따라 쓰레드를 생성하고 스케줄링 하는 주체가 커널이면 커널레벨 쓰레드 라고 한다.

커널이 쓰레드 모델을 지원하지 않거나 제공하는 쓰레드 모델이 마음에 들지 않을 경우, 커널에 의존적이지 않은 형태로 쓰레드의 기능을 제공하는 라이브러리를 활용할 수 있는데 이러한 방식으로 제공되는 쓰레드가 유저레벨 쓰레드 이다.

커널 레벨 쓰레드의 장점은 커널이 직접 제공해 주기 때문에 안정성과 다양한 기능이 제공된다. 단점은 유저 모드에서 커널 모드로의 전환이 빈번하게 이뤄져 성능 저하가 발생한다.

유저 레벨 쓰레드의 장점은 커널은 쓰레드의 존재조차 모르기 때문에 모드 간의 전환이 없고 성능 이득이 발생한다.

유저 레벨 쓰레드의 단점은 하나의 스레드가 커널에 의해 블로킹 되면 프로세스 전체가 블로킹되고, 이를 해결하려면 프로그래밍이 어려워지고 커널레벨 쓰레드에 비해 결과 에측이 어려워 진다.

내부 단편화, 외부 단편화

메모리에 50MB의 빈공간이 남아있을때 30MB의 프로세스를 넣게 되면 20MB가 남게 되는데 이 공간은 너무 작아 다른 작업들이 사용하지 못하게 되는데 이러한 작은 빈 공간들을 내부 단편화 라고 한다.

외부 단편화는 메모리에 남아 있는 공간은 100MB인데 70MB의 프로세서가 실행되면 50과 50으로 구분되어진 메모리에는 용량이 남아 있지만 실행이 될 수 없다.

이를 해결하기 위해서는 압축을 해서 프로세스를 실행 하면 된다.

Database

데이터베이스

조직에 필요한 정보를 얻기 위해 논리적으로 연관된 데이터를 모아 구조적으로 통합해 놓은것

connection pool

동시 접속자가 가질 수있는 connectiond을 하나로 모아놓고 관리한다는 개념입니다. 데이터베이스와 연결된 Connection을 미리 만들어서 Pool 속에 저장해 두고 있다가 필요할 때 Connection을 Pool에서 쓰고 다시 Pool에 반환하는 기법을 말합니다.

쉽게말해 pool에 데이터베이스와 연결된 객체를 저장해 놓고, 필요할 때 마다, Connection Pool에서빌려오는 것 연결이 끝나면 다시 Pool에 돌려준다. Connection Pool을 너무 크게 해놓으면 메모리 소모가 클 것이고, 적게 해놓으면 Connection이 많이 발생할 경우 대기시간이 발생하기 때문에 웹사이트 동시 접속자 수 등 서버 부하에 따라 크기를 조정해야 한다.

데이터 베이스풀이란?

애플리케이션의 스레드에서 데이터베이스에 접근하기위해서는 Connection이 필요하다. connection Pool은 Connection을 여러 개 생성해 두어 저장해 놓은 공간(캐시), 또는 이공간의 Connection을 필요할 때 꺼내 쓰고반환하는 기법

DB에 접근하는 단계

  • 웹 컨테이너에 실행되면서 DB와 연결된 Connection 객체들을 미리 생성하여 Pool에 저장한다.
  • DB에 요청 시, pool에서 Connection 객체를 가져와 DB에 접근한다.
  • 처리가 끝나면 다시 pool에 반환한다.

Connection이 부족할 때

모든 요청이 DB에 접근하고 있고 남은 Connection이 없다면, 해당 클라이언트는 대기 상태로 전환 시키고 pool에 Connection이 반환되면 대기 상태에 있는 클라이언트에게 순차적으로 제공 된다.

Pool이 사용 이유

매 연결마다 Connection 객체를 생성하고 소멸시키는 비용을 출일 수 있다. 미리 생성된 Connection 객체를 사용하기 때문에 DB 접근시간이 단축된다. DB에 접근하는 Connection의 수를 제한하여, 메모리와 DB에 걸리는 부하를 조정할 수 있다.

Thread Pool

매 요청마다 요청을 처리할 Thread를 만드는 것이 아닌, 미리 생성한 pool내의 Thread를 소멸 시키지 않고 재사용하여 효율적으로 자원을 활용하는 기법

트랜잭션(Transaction)

데이터베이스의 상태를 변환시키는 하나의 논리적 기능을 수행하기 위한 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 의미한다.

트랜잭션의 격리수준

여러 스레드에서 동시에 하나의 자원에 접근하는 경우가 있다. 트랜잭션의 4단계의 격리 수준에 따라 트랜잭션이 끝나기 전까지 해당 데이터를 잠그고 다른 트랜잭션에서 참조하지 못하게 하는 것이다.

Join

데이터 베이스에서 중복 데이터를 피하기 위해서 데이터를 쪼개 여러 테이블로 나눠서 저장합니다. 이렇게 분리되어 저장된 데이터에서 원하는 결과를 다시 도출하기 위해서 여러 테이블을 조합할 필요가 있습니다. 관계형데이터베이스에서는 조인(JOIN)연산자를 사용해 관련 있는 컬럼 기준으로 행을 합쳐주는 연산입니다.

SQL injection

응용 프로그램 보안 상의 허점을 의도적으로 이용해, 악의적인 SQL문을 실행되게 함으로써 데이터베이스를 비정상적으로 조작하는 코드 인젝션 공격방법이다.

정규화

관계형 데이터베이스에서 중복을 최소화하게 데이터를 구조화 하는 것을 정규화 라고 합니다. 이렇게 하면 무결성을 유지할 수도 있고 중복된 데이터가 없기 때문에 용량도 줄일 수 있습니다.

데이터베이스의 인덱스

추가적인 쓰기 작업과 저장 공간을 활용하여 데이터베이스 테이블의 검색 속도를 향상시키기 위한 자료구조 이다. 책의 색인과 비슷하다.

데이터베이스 인덱스를 잘 사용하면 효율이 좋아진다. UPDATE, DELETE 사용시에 특정 칼럼에 접근을 해야하는데 만약 index를 지정해 두지 않으면 full scan을 UPDATE, DELETE가 실행 될 때 마다 해줘야 한다.

인덱스의 장점 테이블을 조회하는 속도와 그에 따른 성능을 향상 시킬 수 있다. 전반적인 시스템의 부하를 줄일 수 있다.

단점 인덱스를 설정 해줘야 하기 때문에 야 10%에 해당하는 저장공간이 필요하다.

인덱스를 관리하기 위해 추가 작업이 필요하다. 인덱스를 잘못 사용할 경우 오히려 성능이 저하되는 역효과가 발생 할 수 있다.

잘못사용한 경우 UPDATE나, DELETE가 빈번한 속성에 인덱스를 걸게 되면 인덱스의 크기가 비대해져서 성능이 오히려 저하되는 역효과가 발생할 수 있다. DELTE와 UPDATE는 인덱스를 삭제하는 것이 아니라, 사용하지 않음 처리를 해주기 때문에 어떤 테이블에 빈번하게 발생이되면 실제 데이터는 10건 이지만 100건이 넘어가는 등 SQL문 처리시 비대해진 인덱스에 의해 오히려 성능이 떨어지게 될 것이다.

SQL(Structure Query Language)

관계형 데이터베이스 관리 시스템에 저장된 데이터를 관리하기 위해 설계된 프로그래밍 언어 이다.

스키마(Skima)

데이터베이스를 구성하는 개체, 속성, 관계 및 제약조건 등에 관해 전반적으로 정의한 메타데이터의 집합

RDBMS와 NoSQL은 무엇이고 차이점은?

데이터베이스란 여러사람들이 공유하고 사용할 목적으로 통합 관리되는 데이터들의 모임이다.

DBMS(Database Management System)의 약자로서 사용자와 데이터베이스 사이에서 사용자의 요청을 해석하여 데이터베이세 저장된 정보를 관리할 수 있도록 해주는 소프트웨어

여기서 R Relational이 추가가 되면서 관계형 데이터베이스를 의미하게 되는데, RDBMS는 엑셀과 비슷한 2차원 테이블의 형태로 구성되며 속성과, 값으로 데이터를 저장하고 관리한다. 그리고 이러한 테이블들은 서로 관계를 맺으며 존재합니다. 그리고 이들은 사용자의 요청을 처리하기위해 SQL이라는 언어를 활용합니다.

RDBMS 방식으로는 더 이상 처리할 수 없을만큼의 복잡하고 큰 데이터들의 등장으로 NoSQL에 대한 필요성이 부각이 되기 시작했습니다. 테이블간의 관계를 따로 정의하지 않습니다. 그래서 보다 자유롭게 데이터를 저장할 수 있습니다. 따라서 Key값만 가지고 데이터에 대한 입,출력을 수행 할 수 있습니다.

RDBMS의 장단점

데이터의 분류, 정력, 탐색 속도가 비교적 빠르다. SQL이라는 구조화된 질의를 통해 데이터를 다룰 수 ㅇㅆ다. 작업의 완전성을 보장한다. 데이터의 UPDATE가 빠르다.

단점 반드시 스키마의 규격에 맞춰서 데이터를 다뤄야 한다. 데이터 처리에 대한 부하 발생시, 처리가 어렵다.

NoSQl

장점 데이터간의 관계를 정의하지 않는다.(join 불필요) RDBMS 보다 복잡도가 떨어져, 훨씬 대용량의 데이터를 저장, 관리 할 수 있다. 테이블에 스키마가 정해져 있지 않아 데이터 저장이 비교적 자유로움 많은 양의 데이터를 저장, 처리 할 수 있다.

단점 key값에 대한 입출력만 가능 스키마가 정해져 있지 않아 데이터에대한 규격화가 되어 있지 않다. DATA를 UPdate하는데 비교적 느리다.

아직 RDBMS를 사용하는데가 많고, NoSQL, RDBMS 사이의 장 단점이 명확하기 때문에, 다양한 방식으로 쓰일 것으로 예상이 된다.

Redis와 mongodb의 공통점과 차이점

두 개 모두 NoSQL이고, 서버의 데이터베이스로 사용된다.

Redis

  • 메모리 DB로 속도가 빠르다
  • 성능 목적의 캐시에 사용된다.
  • 키, 값으로 데이터를 저장한다. 확실히 key-value 값으로 사용되어 쉽게 저장할 수 있고 빠른 성능을 기대할 수 있다. 또한 상대적으로 MongoDB와 비교해서는 복잡하지 않고 단순한 편이다.

MongoDB

  • 물리디스크에 저장
  • Json과 유사한 문서를 사용하여 스키마 없는 데이터를 저장한다.
  • 메인 저장소나 로그 목적 용도로 사용된다.

몽고디비의 경우 NoSQL이므로 주 데이터베이스로 사용되거나 특별한 목적으로 부가적인 DB형태로 쓰이는 경우가 많다. 하지만 Redis는 빠른 성능을 장점으로 하기에 주 데이터베이스로 사용하기 보다 캐시를 통한 성능의 목적으로 사용이 된다.

옵티마이저

딕셔너리에 있는 오브젝트 통계, 시스템 통계 등의 정보를 사용해서 예상되는 비용을 산정한다. 옵티마이저는 여러 개의 실행 계획 중에서 최저비용을 가지고 있는 계획을 선택해서 SQL을 실행 한다.

즉 SQL을 작성하여 실행 할때 옵티마저는 SQL을 어떻게 실행할 것인지를 계획하게 된다. SQL 실행 계획을 수립하고 SQL을 실행 한다.

SQL 개발자가 작성한 SQL문을 어떻게 실행하느냐에 따라 성능이 달라진다.

Replication

주 서버와 보조서버간의 데이터 배포방식이다. 주 서버(게시서버)가 보조서버(배포서버)에게 데이터를 전달 후 배포서버가 다른 구독서버들에게 데이터를 전달하여 각 구독서버들이 최종 사용자에게 데이터를 전달하는 방식

파티셔닝(Partitioning)

데이터베이스를 여러 부분으로 분할 하는 것이다. 데이터가 너무 커져서, 조회하는 시간이 길어질 때 또는 관리의 용이성, 성능, 가용성 등의 향상을 이유로 행해지는 것이 일반적이다.

샤딩

조각내다 라는 뜻으로 데이터베이스 저장 기법 중 하나이며, 같은 테이블 스키마를 가진 데이터를 다수의 데이터베이스에 분산하여 저장하는 방법을 의미한다.

orm

객체와 관계형 데이터베이스의 데이터를 자동으로 매핑해주는 것을 말한다. 객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다. 이는 불일치가 존재하는데 이때 ORM을 통해 객체간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결한다.

orm의 장점

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

orm의 단점

완벽한 orm으로만 서비스를 구현하기가 어렵다. 프로시저가 많은 시스템에선 ORM의 객체 지향적인 장점을 활용하기 어렵다.

django에는 orm이 있나요?

네 사용할 수 있습니다.

네트워크

데이터가 의도된 목적지에 닿을 수 있도록 보장해주는 통신 규약이다. 국제표준화 기구에서 만든 규약은 OSI 7계층 과 TCP/IP 두 가지가 있다. 그중 OSI7계층 보단 TCP/IP가 많이 사용되는데 그 이유는 점유율 면에서 차이가 나기 때문이다.

OSI 7 계층

국제 표준화 기구에서 개발한 모델로 컴퓨터 네트워크 프로토콜 디자인과 통신을 계층으로 나누어 설명한 것이다. 일반적으로 OSI 7계층 이라고 한다.

TCP/IP

TCP

데이터가 의도된 목적이제 닿을 수 있도록 보장해주는 통신 규약이다. TCP는 두 호스트가 교환하는 데이터와 승인 메세지의 형식을 정의하여, 서버와 클라이언트 간의 데이터를 신뢰성있께 전달하기 위해 만들어진규약이다.

데이터가 전송 될때 구리선일 수도 있고, 광케이블 일 수도 있고 인공위성 일 수도 있찌만 데이터가 손실될 가능성이 있다. 그떄 TCP는 일렬번호를 부여함으로써 데이터의 손실을 찾아내고 교정하고, 순서를 재조합하여 클라이언트에게 전달 할 수 있게 해준다. TCP의 장점은 복잡해서 신뢰성인 높다는 것이다.

IP

컴퓨터와 컴퓨터간에 데이터를 전솧하기 위해서 각 컴퓨터의 주소가 필요하다. 프로토콜은 4바이트로 이루어진 컴퓨터의 주소이며, 3개의 마침표로 나뉘어진 숫자로 표시된다. IP는 TCP와 달리 데이터의 재조합이나 손실여부 확인이 불가능하며, 단지 데이터를 전달하는 역할만을 담당한다.

그래서 TCP/IP는 IP기반에 TCP가 사용되서 이렇게 불린다고 한다. TCP가 데이터의 추적을, IP가 배달을 처리한다고 보면 된다.

웹 동작 방식

  1. 사용자가 브라우저에 URL을 입력
  2. 브라우저는 DNS를 통해 서버의 진짜 주소를 찾음
  3. HTTP 프로토콜을 사용하여 HTTP 요청이 서버로 전송됨
  4. TCP/IP 연결을 통해 HTTP 요청이 서버로 전송됨
  5. 서버는 HTTP 프로토콜을 활용해 HTTP 응답 메세지를 생성함
  6. TCP/IP 연결을 통해 요청한 컴퓨터로 전송
  7. 도착한 HTTP 응답 메세지는 웸페이지 데이터로 변환 되고 웸 브라우저에 의해 출력되어 사용자가 볼 수 있게 됨

TCP와 UDP

TCP(Transmission Control Protocol)의 약자이고 UDP(User Datagram Protocol) 두 프로토콜은 모두 패킷을 한 컴퓨터에서 다른 컴퓨터로 전달해주는 IP프로토콜을 기반으로 구현되어 있지만 서로 다른 특징을 가지고 있다.

TCP는 양방향 프로토콜이고 UDP는 단방향, 일방적인 송신이다.

그래서 신뢰성이 요구되는 애플리케이션에서는 TCP를 사용하고 간단한 데이터를 빠른 속도로 전송하고자 하는 애플리케이션에서는 UDP를 사용한다.

TCP와 UDP의 공통점은 포트 번호를 이용하여 주소를 지정한다. 데이터 오류 검사를 위한 체크섬이 존재한다.

차이점 - TCP는 연결이 성공해야 통신이 가능(연결형 프로토콜) 이지만 UDP는 비연결형 프로토콜 이다.(연결없이 통신이 가능하다.) - 데이터의 경계를 구분하지 않는다. 데이터의 경계를 구분한다. - 신뢰성 있는 데이터 전송, 비신뢰성 있는 데이터의 전송(데이터의 재전송 없음) - 일 대 일 통신, 일대일 일대 다 다 대 다 통신

HTTP가 무었인가?

HTTP는 WWW(World Wide Web)상에서 정보를 주고 받을 수 있는 프로토콜이다. 주고 HTML 문서를 주고받는데 쓰인다.

HTTPS는 HyperText Transfer Protocol over Secure 이렇듯이 HTTP에 암호화 과정이 추가가 되었다.

HTTP는 암호화가 추가되지 않았기 때문에 보안이 취약한 반면, HTTPS는 안전하게 데이터를 주고 받을 ㅅ ㅜ있다. 하지만 HTTPS를 이용하면 암호화/복호화의 과정이 필요하기 떄문에 HTTP보다 속도가 느리다. 또한 HTTPS는 인증서를 발급하고 유지하기 위한 추가 비용이 발생한다. 하지만 지금은 HTTP HTTPS와 관련해서 속도의 차이는 거의 없다.

개인 정보와 같은 민감한 데이터를 주고받아야 한다면 HTTPS를 이용해야 하지만, 단순한 정보 조회 등만을 처리하고 있다면 HTTP를 이용하면 된다.

HTTPS의 동작과정

SSL과 같은 프로토콜을 사용하여 공개키/개인키 기반으로 데이터를 암호화 하고 있다. 데이터는 암호화되어 전송되기 떄문에 임의의 사용자가 데이터를 조회하여도 원보의 데이터를 보는 것은 불가능 하다.

그럼 이제 서버는 클라이언트가 요청을 보낼 때 암호화를 하기 위한 공개키를 생성해야 하는데, 일반적으로는 인증된 기관에 공개키를 전송하여 인증서를 발급받고 있다.

호환된 인증서는 CA의 개인키로 암호화되었기 때문에, 신뢰성을 확보할 수 있고, 클라이언트는 A 기업의 공개키로 데이터를 암호화하였기 때문에 A기업만 복호화하여 원본의 데이터를 얻을 수 있다. HTTPS는 이러한 공개키/개인키 기반의 대칭키 암호화 방식을 활용하여 안전성을 확보하고 있다.

HTTP 메소드

GET, POST GET은 지정된 리소스를 요청 POST 서버가 클라이언트의 폼 입력 필드 데이터의 수락을 요청, 클라이언트는 서버로 HTTP Body에 Data를 전송 HEAD는 문서의 헤더 정보만 요청하며, 응답 데이터(body를 받지 않는다.)

CORS(Croess Origin Resource Sharing)

도메인 또는 포트가 다른 서버의 자원을 요청하는 매커니즘을 말한다. 서버와 클라이언트가 분리되어 있는 앱에서는 cross-origin HTTP 요청을 서버에서 승인해주는 것이 좋다.

REST와 RESTful의 차이

REST는 API를 효율적으로 하기 위한 규약 입니다. 이러한 규약을 지키면서 만든 API를 REESTAPI라고 하고 RESTful은 이애하기 쉽고 사용하기 쉬운 REST API를 만드는 것을 의미한다.

socket(소켓)

컴퓨터 네트워크를 경유하는 프로세스 간 통신의 종착점이다. 오늘날 컴퓨터 간 통신의 대부분은 인터넷 프로토콜을 기반으로 하고 있으므로, 대부분의 네트워크 소켓은 인터넷 소켓이다. 네트워크에서 데이터를 통신 할 수 있도록 연결 해주는 연결부 라고 할 수 있습니다.

socket io와 ws(Web Socket)의 차이

WS(Web Socket)

HTTP는 서버와 클라이언트 사이의 연결이유지되지 않는다. 이로 인해 실시간 통신을 구현하는덴 어려움이많았고 이를 보완하기 위해 Websocket이 나왔다. 서버와 클라이언트 사이의 연결이 계속 유지되는 특성이 있고 이로 인해 양방향 통신을 가능하게 한다.

Web Socket은 TCP 프로토콜에서 양방향 커뮤니케이션을 가능하게 하는 통신 프로토콜이다. HTTP의 프록시를 지원할 수 있게 했기 때문에 HTTP와의 프로토콜과도 호환이 가능하다. 웹소켓을 사용하기 위해서는 HTTP Upgrade header라는 걸 사용하여 HTTP 프로토콜에서 WebSocket 프로토콜로 전환된다. 이 과정을 WebSocket HandShake라고 한다.

WebSocket 프로토콜을 이용하면 이전에 양방향 통신을 가능하기 하기 위해서 사용한 polling 방식보다 overhead가 확실히 작아진다. 이는 클라이언트가 먼저 서버에게 요청하지 않고, 서버가 클라이언트에게 contents를 보내고 이 연결이 열린채로 유지되기 때문에 가능하다.

socket.io

WebSocket 프로토콜 라이브러리는 아니다. 브라우저와 웹 서버의 종류와 버전을 파악하여 가장 적합한 기술을 선택하여 실시간 웹을 구현할 수 있도록 한다.

그럼 차이는?

둘 다 서버에는 모듈 설치가 필요하지만 ws는 웹소켓 표준이라 클라이언트에 추가적인 설치를 요구하지 않는다. ws에서는 new WebSocket으로 객체 생성을 바로 사용할 수 있지만, socketio는 js 파일을 추가해야 합니다.

ws는 string형으로 데이터를 전송한다. socket i.o는 이벤트명과 데이터를 명확하게 구분하고 모든 자료형을 주고 받을 수 있지만 ws는 string 자료형 하나로 데이터를 주고 받습니다. 이벤트명도 데이터에 포함해서 받으므로 데이터를 parsng하는 과정이 필요합니다.

socket i.o에는 계속해서 연결을 시도한다. socket.io는 주기적으로 연결을 시도한 반면에 ws는 한 번 연결이 끊어졌을 때, 복구되지 않으므로 같은 기능을 구현하려면 추가적인 코드가 필요합니다.

결론

둘 다 같은 기능을 작동하지만 socket.io가 ws의 확장판의 느낌으로 편하기 때문에 더 사용이 많다.

Frame, packet, Segment, Datagram

tcp - segement ip - packet data link - frame physical - bits

PDU(Protocol Data Unit)

데이터 통신에서 상위 계층이 전달한 데이터에 붙이는 제어정보를 의미한다.

데이터 자체는 동일하지만 각 레이어를 거치면서 헤더 정보가 추가 되면서 이름이 달라진다.


작성자: 이동근

작성일: 2021-07-11