DI(Dependency Injection)에 대한 설명과 해당 기술의 장점에 대해 설명해주세요.
DI란 멤버변수의 결정을 외부에서 정의하여 주입하는 방식입니다. 보통 내부 필드에 바로 주입하는 방법, 생성자를 통해 주입하는 방법, 세터를 통해 주입하는 방법이 존재합니다. DI를 사용하는 이유는 객체간 결합도를 감소시키기 위함입니다. 사용할 객체을 결정을 내부에서 하게 되면 객체간 강한 결합이 생겨 유지보수가 어려워지는 상황이 발생합니다. 예를 들어, 요리사 객체가 있고 여러가지 레시피 객체가 있을 때, 요리사가 사용할 레시피를 내부에서 정의해서 사용하게 된다면, 레시피가 변경될 경우 요리사 객체에 직접 접근하여 레시피 객체를 수정해 줘야 합니다. 하지만, DI를 사용하게 되면, 요리사 객체 생성시점에 레시피를 따로 외부에서 정의하여 주입해주면 되기 때문에, 추후 변경이 용이하게 됩니다. DI의 구현을 위해서는 의존관계역전 원칙에 따라 구체적인 것 보단 추상적인 것을 멤버변수타입으로 사용하는 것이 좋은데 방금의 예에서는 레시피 라는 인터페이스를 많은 레시피들이 구현하게 하면, 외부에서 선언하여 내부에서 사용하는 것이 가능해집니다. DI를 사용하게 된다면, 객체간 의존도를 감소시킴으로서, 유지보수가 용이해진다는 장점이 있습니다. 또한, 모듈화가 가능해짐으로서 필요한 부분만 주입받아 사용하는 것이 가능해집니다.
DB에서 인덱스를 잘 사용하면 어떤 장점이 있을까요?
DB에서 인덱스를 사용하게 되면 B-Tree를 통해 조회를 하게 됩니다. B-Tree의 시간복잡도는 최대 logN이므로, 조회속도에서 이점을 가장 크게 볼 수 있습니다. 하지만, 레코드의 카디널리티가 낮다면(=중복이 많거나) fullscan과 성능이 비슷할 가능성이 높고, where 절에 사용하지 않는데 인덱스를 생성하게 되면, 인덱스 테이블 용량만 차지할 가능성이 있습니다. 또한, 삽입 삭제가 자주 일어난다면, 계속적으로 인덱스 테이블이 수정됨으로서 조회속도가 느려지는 결과로 이어 질 수 있습니다. 따라서, 데이터의 카디널리티나, 사용량, 데이터의 CRUD에 대한 조건을 잘 따져서 인덱스를 생성하는 것도 중요합니다.
DI 를 사용하여 결합도가 낮아질 경우, 어떤 장점이 있나요?
유지보수가 용이해지는 대표적인 장점이 있습니다. 뮤지컬배우라는 예제를 들어 설명드리고 싶은데요. 뮤지컬배우는 가끔씩 배우의 사정으로 인해 펑크나서 다른 배우로 배역이 대체되곤 합니다. 그럴 수 있는 이유는 배우가 바껴도, 그 배우는 배역에 대한 대사정보들을 알고 있기 때문입니다. 이걸 객체지향으로 설계한다고 했을 때, 배역이라는 객체가 있을거고, 배우라는 객체가 있을 텐데, 배역이 배우라는 객체를 내부에서 정의한다고 하는 경우는, 이 배역에 대한 배우가 대체불가능한 결합을 갖게 되는 것 입니다. 이는 의존관계역전원칙을 위반함으로서, 배우와 배역간의 단단한 결합을 가지게됩니다. 하지만, 배우라는 객체를 외부에서 주입하는 경우는 어떻게 될까요? 배우객체가 잘 동작하지 않으면, 다른 배우객체를 주입하여 사용하면 됩니다. 배역은 그냥 어떤 배우를 주입받던지 주입받은 배우를 움직이도록 하기만 하면 됩니다. 이 처럼, 결합이 느슨해지는것은 유지보수가 용이해진다는 장점을 가지게 됩니다.
스프링에서 싱글톤을 사용하는 이유
Spring에서 싱글톤(Singleton) 패턴을 사용하는 이유는 다음과 같습니다.
자원 사용의 효율성: 객체 생성 비용을 줄일 수 있습니다. 객체를 생성하고 초기화하는 것은 시스템 리소스를 많이 소모하는 작업 중 하나입니다. 따라서 객체를 싱글톤으로 관리하면 객체를 생성하는 비용을 줄일 수 있어 시스템 자원을 효율적으로 사용할 수 있습니다.
상태 유지: 객체를 여러 번 생성하는 경우, 객체의 상태를 유지하기가 어렵습니다. 하지만 싱글톤으로 객체를 관리하면 상태를 유지할 수 있습니다. 예를 들어, DAO(Data Access Object) 객체에서는 DB 연결을 유지하거나 캐시를 관리하는 등의 작업을 수행해야 합니다. 이러한 작업을 싱글톤으로 관리하면 객체의 상태를 유지할 수 있습니다.
객체간 의존성 관리: 객체간의 의존성을 쉽게 관리할 수 있습니다. 스프링은 IoC(Inversion of Control) 컨테이너를 이용하여 객체의 생성과 의존성을 관리합니다. 이때 싱글톤으로 객체를 관리하면, 여러 객체가 동일한 객체를 참조할 수 있어 의존성을 쉽게 관리할 수 있습니다.
Thread-safe: 스프링에서는 싱글톤 객체를 생성할 때 동시성 문제를 고려하여 Thread-safe한 방식으로 객체를 생성합니다. 따라서 멀티스레드 환경에서도 안전하게 객체를 사용할 수 있습니다.
따라서, Spring에서 싱글톤 패턴을 사용하면 자원의 효율성과 상태의 유지, 객체간 의존성 관리, Thread-safe한 방식 등의 장점을 얻을 수 있습니다.
인덱스에 대해서 설명해주세요.
데이터베이스에서 인덱스를 생성하게 되면 기본적으로 B-Tree를 생성하게 됩니다. pk혹은 unique, not null 컬럼기준으로 인덱스를 생성하면, 해당 컬럼기준으로 페이지 내의 데이터가 재정렬됩니다. 이를 클러스터링 인덱스라고 합니다. 클러스터링 인덱스는 리프 페이지가 곧 실제 데이터 페이지 입니다. unique 혹은 커스텀 인덱스는 논-클러스터링 인덱스를 생성하며, 논-클러스터링 인덱스는 리프페이지에 실제 데이터페이지가 아닌, 실제 데이터 페이지의 주소와 순서를 표출합니다. 두개가 혼합되었을 경우, 논-클러스터링 인덱스가 단일로 사용되었을 때처럼 실제데이터 페이지의 주소와 순서를 저장하는것이 아니라, 클러스터링 인덱스가 적용된 실제 값이 저장되어 우선적으로 논-클러스터링 인덱스를 통해 조회를 진행 한 뒤 리프페이지에 있는 데이터를 기반으로 클러스터링 인덱스로 가서 실제 데이터 페이지로 접근한다고 합니다.
데이터베이스 페이지?
페이지는 데이터베이스에서 데이터를 저장하는 단위이다. MySQL InnoDB는 한페이지의 크기가 16KB로 고정되어 있습니다.
레디스는 싱글 스레드인가요 멀티 스레드인가요?
Redis는 기본적으로 싱글스레드로 동작합니다. 인메모리 캐시를 위해 고안되었기 때문입니다.