[CS 지식] 기술 면접 대비[CS 지식] 기술 면접 대비

June·2021년 4월 4일
2

취업 대비

목록 보기
1/1

신입 개발자 전공 지식 & 기술 면접 백과사전

https://github.com/WeareSoft/tech-interview/blob/master/contents/java.md#java-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%B4%EB%9E%80

개발 상식

객체지향 프로그래밍

가장 중요한 점은, 객체 내부에 자료형(필드)와 함수(메소드)가 같이 존재하는 것이다.

이제 도서관리 프로그램을 만들 때, 해당하는 책의 제목, 저자, 페이지와 같은 자료형과 읽기, 예약하기 등 메소드를 '책'이라는 객체에 한번에 묶어서 저장하는 것이 가능해졌다.

이처럼 가능한 모든 물리적, 논리적 요소를 객체로 만드려는 것이 객체지향 프로그래밍이라고 말할 수 있다.

객체지향으로 구현하게 되면, 객체 간의 독립성이 생기고 중복코드의 양이 줄어드는 장점이 있다. 또한 독립성이 확립되면 유지보수에도 도움이 될 것이다.

추상화

추상화(Abstraction)
필요로 하는 속성이나 행동을 추출하는 작업

추상적인 개념에 의존하여 설계해야 유연함을 갖출 수 있다.

즉, 세부적인 사물들의 공통적인 특징을 파악한 후 하나의 집합으로 만들어내는 것이 추상화다

캡슐화

낮은 결합도를 유지할 수 있도록 설계하는 것

쉽게 말하면, 한 곳에서 변화가 일어나도 다른 곳에 미치는 영향을 최소화 시키는 것을 말한다.

(객체가 내부적으로 기능을 어떻게 구현하는지 감추는 것!)

결합도가 낮도록 만들어야 하는 이유가 무엇일까? 결합도(coupling)란, 어떤 기능을 실행할 때 다른 클래스나 모듈에 얼마나 의존적인가를 나타내는 말이다.

즉, 독립적으로 만들어진 객체들 간의 의존도가 최대한 낮게 만드는 것이 중요하다. 객체들 간의 의존도가 높아지면 굳이 객체 지향으로 설계하는 의미가 없어진다.

우리는 소프트웨어 공학에서 객체 안의 모듈 간의 요소가 밀접한 관련이 있는 것으로 구성하여 응집도를 높이고 결합도를 줄여야 요구사항 변경에 대처하는 좋은 설계 방법이라고 배운다.

이것이 바로 캡슐화와 크게 연관된 부분이라고 할 수 있다.

그렇다면, 캡슐화는 어떻게 높은 응집도와 낮은 결합도를 갖게 할까?

바로 정보 은닉을 활용한다.

외부에서 접근할 필요가 없는 것들은 private으로 접근하지 못하도록 제한을 두는 것이다.

(객체안의 필드를 선언할 때 private으로 선언하라는 말이 바로 이 때문!!)

상속

일반화 관계(Generalization)라고도 하며, 여러 개체들이 지닌 공통된 특성을 부각시켜 하나의 개념이나 법칙으로 성립하는 과정

일반화(상속)은 또 다른 캡슐화다.

자식 클래스를 외부로부터 은닉하는 캡슐화의 일종이라고 말할 수 있다.

아까 자동차를 통해 예를 들어 추상화를 설명했었다. 여기에 추가로 대리 운전을 하는 사람 클래스가 있다고 생각해보자. 이때, 자동차의 자식 클래스에 해당하는 벤츠, BMW, 아우디 등은 캡슐화를 통해 은닉해둔 상태다.

사람 클래스의 관점으로는, 구체적인 자동차의 종류가 숨겨져 있는 상태다. 대리 운전자 입장에서는 자동차의 종류가 어떤 것인지는 운전하는데 크게 중요하지 않다.

새로운 자동차들이 추가된다고 해도, 사람 클래스는 영향을 받지 않는 것이 중요하다. 그러므로 캡슐화를 통해 사람 클래스 입장에서는 확인할 수 없도록 구현하는 것이다.

이처럼, 상속 관계에서는 단순히 하나의 클래스 안에서 속성 및 연산들의 캡슐화에 한정되지 않는다. 즉, 자식 클래스 자체를 캡슐화하여 '사람 클래스'와 같은 외부에 은닉하는 것으로 확장되는 것이다.

이처럼 자식 클래스를 캡슐화해두면, 외부에선 이러한 클래스들에 영향을 받지 않고 개발을 이어갈 수 있는 장점이 있다.

다형성(Polymorphism)

서로 다른 클래스의 객체가 같은 메시지를 받았을 때 각자의 방식으로 동작하는 능력

객체 지향의 핵심과도 같은 부분이다.

다형성은, 상속과 함께 활용할 때 큰 힘을 발휘한다. 이와 같은 구현은 코드를 간결하게 해주고, 유연함을 갖추게 해준다.

즉, 부모 클래스의 메소드를 자식 클래스가 오버라이딩해서 자신의 역할에 맞게 활용하는 것이 다형성이다.

이처럼 다형성을 사용하면, 구체적으로 현재 어떤 클래스 객체가 참조되는 지는 무관하게 프로그래밍하는 것이 가능하다.

상속 관계에 있으면, 새로운 자식 클래스가 추가되어도 부모 클래스의 함수를 참조해오면 되기 때문에 다른 클래스는 영향을 받지 않게 된다.

객체 지향 설계 원칙

SOLID라고 부르는 5가지 설계 원칙이 존재한다.

SRP(Single Responsibility) - 단일 책임 원칙
클래스는 단 한 개의 책임을 가져야 한다.

클래스를 변경하는 이유는 단 한개여야 한다.

이를 지키지 않으면, 한 책임의 변경에 의해 다른 책임과 관련된 코드에 영향이 갈 수 있다.

OCP(Open-Closed) - 개방-폐쇄 원칙
확장에는 열려 있어야 하고, 변경에는 닫혀 있어야 한다.

기능을 변경하거나 확장할 수 있으면서, 그 기능을 사용하는 코드는 수정하지 않는다.

이를 지키지 않으면, instanceof와 같은 연산자를 사용하거나 다운 캐스팅이 일어난다.

LSP(Liskov Substitution) - 리스코프 치환 원칙
상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다.

상속 관계가 아닌 클래스들을 상속 관계로 설정하면, 이 원칙이 위배된다.

ISP(Interface Segregation) - 인터페이스 분리 원칙
인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.

각 클라이언트가 필요로 하는 인터페이스들을 분리함으로써, 각 클라이언트가 사용하지 않는 인터페이스에 변경이 발생하더라도 영향을 받지 않도록 만들어야 한다.

DIP(Dependency Inversion) - 의존 역전 원칙
고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다.

저수준 모듈이 고수준 모듈에서 정의한 추상 타입에 의존해야 한다.

즉, 저수준 모듈이 변경돼도 고수준 모듈은 변경할 필요가 없는 것이다.

함수형 프로그래밍

MVC 패턴

Java

JVM

JVM은, 다른 프로그램을 실행시키는 것이 목적이다.

갖춘 기능으로는 크게 2가지로 말할 수 있다.

자바 프로그램이 어느 기기나 운영체제 상에서도 실행될 수 있도록 하는 것
프로그램 메모리를 관리하고 최적화하는 것

JVM은 코드를 실행하고, 해당 코드에 대해 런타임 환경을 제공하는 프로그램에 대한 사양임

JVM에서의 메모리 관리
JVM 실행에 있어서 가장 일반적인 상호작용은, 힙과 스택의 메모리 사용을 확인하는 것

실행 과정

  1. 프로그램이 실행되면, JVM은 OS로부터 이 프로그램이 필요로하는 메모리를 할당받음. JVM은 이 메모리를 용도에 따라 여러 영역으로 나누어 관리함
  2. 자바 컴파일러(JAVAC)가 자바 소스코드를 읽고, 자바 바이트코드(.class)로 변환시킴
  3. 변경된 class 파일들을 클래스 로더를 통해 JVM 메모리 영역으로 로딩함
  4. 로딩된 class파일들은 Execution engine을 통해 해석됨
  5. 해석된 바이트 코드는 메모리 영역에 배치되어 실질적인 수행이 이루어짐. 이러한 실행 과정 속 JVM은 필요에 따라 스레드 동기화나 가비지 컬렉션 같은 메모리 관리 작업을 수행함

자바 컴파일러
자바 소스코드(.java)를 바이트 코드(.class)로 변환시켜줌

클래스 로더
JVM은 런타임시에 처음으로 클래스를 참조할 때 해당 클래스를 로드하고 메모리 영역에 배치시킴. 이 동적 로드를 담당하는 부분이 바로 클래스 로더

자바 컴파일러
자바 소스코드(.java)를 바이트 코드(.class)로 변환시켜줌

클래스 로더
JVM은 런타임시에 처음으로 클래스를 참조할 때 해당 클래스를 로드하고 메모리 영역에 배치시킴. 이 동적 로드를 담당하는 부분이 바로 클래스 로더

Runtime Data Areas
JVM이 운영체제 위에서 실행되면서 할당받는 메모리 영역임

총 5가지 영역으로 나누어짐 : PC 레지스터, JVM 스택, 네이티브 메서드 스택, 힙, 메서드 영역

(이 중에 힙과 메서드 영역은 모든 스레드가 공유해서 사용함)

PC 레지스터 : 스레드가 어떤 명령어로 실행되어야 할지 기록하는 부분(JVM 명령의 주소를 가짐)

스택 Area : 지역변수, 매개변수, 메서드 정보, 임시 데이터 등을 저장

네이티브 메서드 스택 : 실제 실행할 수 있는 기계어로 작성된 프로그램을 실행시키는 영역

: 런타임에 동적으로 할당되는 데이터가 저장되는 영역. 객체나 배열 생성이 여기에 해당함

(또한 힙에 할당된 데이터들은 가비지컬렉터의 대상이 됨. JVM 성능 이슈에서 가장 많이 언급되는 공간임)

메서드 영역 : JVM이 시작될 때 생성되고, JVM이 읽은 각각의 클래스와 인터페이스에 대한 런타임 상수 풀, 필드 및 메서드 코드, 정적 변수, 메서드의 바이트 코드 등을 보관함

가비지 컬렉션(Garbage Collection)

자바 이전에는 프로그래머가 모든 프로그램 메모리를 관리했음 하지만, 자바에서는 JVM이 프로그램 메모리를 관리함!

JVM은 가비지 컬렉션이라는 프로세스를 통해 메모리를 관리함. 가비지 컬렉션은 자바 프로그램에서 사용되지 않는 메모리를 지속적으로 찾아내서 제거하는 역할을 함.

실행순서 : 참조되지 않은 객체들을 탐색 후 삭제 → 삭제된 객체의 메모리 반환 → 힙 메모리 재사용

Call by value 와 Call by Reference

java와 c/c++의 차이점

java의 접근 제어자의 종류와 특징

Database

키 정리

JOIN

SQL vs NoSQL

인덱스

DML DDL DCL TCL

정규화

무결성

운영체제

프로세스와 스레드 차이

가상 메모리

기타

UI UX

0개의 댓글