CS 기본 지식

2. CS 기본 지식 - 프로그래밍

Beige00 2024. 4. 3. 14:31

* OOP란?

Object-Oriented Programming 의 약어이다. 즉, 객체 지향 프로그래밍이다.

객체 지향 프로그래밍의 특징은 현실 세계를 프로그래밍으로 옮겨와 각 사물들을 객체로 보고, 그 객체로부터 개발하고자 하는 특징과 기능을 뽑아와 프로그래밍하는 기법이다. OOP로 코드를 작성하면 재사용성변형가능성을 높일 수 있다.

또한 세부 기능들을 캡슐화 하기 때문에 은닉 효과도 있다. 

더보기

(ex : OOP로 Remote Controller를 개발했다고 치자. OOP의 특성상 최대한 추상화 시킨 RC의 Interface를 구성하고, 해당 Interface를 상속해서 구체화된 RC를 디자인할 것이다. 예를 들면 RC interface - "TV 용" RC Interface(혹은 abstract class) - "LG TV 용" RC class. 그러면 내가 "RC"를 개발하고자 할 때 처음부터 다 짤 필요가 없고 RC Interface를 사용하여 해당 단계부터 살을 붙여나가면 되는 것이다. 따라서 재사용성과 변형 가능성이 높다.)

 

* OOP의 5가지 설계 원칙(SOLID)

 

1. SRP(Single Responsibility Principle) : 단일 책임 원칙. 클래스는 단 하나의 목적을 가져야하며, 클래스를 변경하는 이유도 단 하나의 이유여야한다. 이것이 제대로 이루어지지 않았을 시 Error의 책임 소재가 불분명해지며 상속 관계가 복잡해지고 이는 총체적 난국으로 이어질 것이다.

 

2. OCP(Open-Closed Principle) : 개방 폐쇄 원칙. Class들은 자신을 이용하여 확장되는 것에는 열려 있어야 하나, 기존에 있는 기능을 "변경"하여 구현하는 것은 닫혀있어야한다. 해당 원칙을 명심하며 개발된 코드들은 재사용성이 증가한다.

 

3, LSP(Liskov Substitution Principle) : 리스코프 치환 원칙. 부모 객체를 자식 객체로 바꾸어도 프로그램은 일관되게 동작하여야한다. 부모 객체에서 제공되는 기능이 자식 객체에서 변경되거나 사라지면 안된다는 것이다. 

예를 들면 자동차에서 엔진의 Run이라는 기능을 이용하여 시동을 거는데, 이게 BMW 자동차 엔진이라는 자식 객체에 대입되었을 때, 작동이 달라지면 안된다는 것이다.

 

4. ISP(Interface Segregation Principle) : 인터페이스 분리 원칙. 사용하는 기능만 구성된 클래스를 써라. 이를 위해 큰 인터페이스에서 자기가 사용할 기능만 포함한 인터페이스로 분할 하여 해당 인터페이스를 상속하자.

 

5. DIP(Dependency Inversion Principle) : 의존 역전 법칙. 부모가 자식 객체에게 의존해서는 안됨. 따라서 상위 객체일수록 추상화 정도가 강해야함.

 

 

 

* 절차 지향 프로그래밍 vs OOP

- 절차 지향 프로그래밍 : 순서적인 코드의 처리, 컴퓨터의 처리 구조와 유사해 실행이 빠르다, 코드의 순서가 바뀌면 에러가 난다. (ex: 정의된 함수가 밑에 있고, 그 위에서 해당 함수를 사용하려면 일단 virtual 함수가 있거나, 위에 정의문이 있어야한다. C언어가 절차 지향 언어이다.)

 

- 객체 지향 프로그래밍 : 캡슐화, 상속, 다형성 등 여러 기능을 제공한다.(자세한 기능은 위에서 다 설명함), 대표적인 언어로는 Java가 있다. 코드의 재사용성과 확장성이 좋다.

 


* RESTful API

- 웹 서비스의 아키텍쳐 스타일. 네크워크 상태 전이의 표현법이다. Resource, Method, Representation의 3가지 표현법을 사용하며, 이 3가지를 통해 상태 전이를 표현한다면 RESTful 한 API 작성이 가능해진다.

(Resource : 웹 상의 모든 HTTP URL로 표현 가능한 것들, Method : GET, POST 등과 같은 요청 방식, Representation : JSON과 같은 자원의 형태.)

 

* 웹 API는 클라이언트와 웹 리소스 사이의 게이트웨이라고 생각할 수 있다.


* 함수형 프로그래밍

함수형 프로그래밍은 계산을 수학적 함수의 평과로 취급하고, 상태 변경이나 가변 데이터를 최대한 피하는 프로그래밍 패러다임이다. 해당 패러다임의 주요 특징은 "순수 함수"를 사용하는 것인데, 순수 함수는 동일한 입력에 대해 항상 동일한 결과를 반환하며 side effects가 없다. 즉, 최대한 값의 변경을 피하는 쪽이다.

이에 반해, 다른 프로그래밍 기법은 함수의 결과를 기존 파라미터에 반영시키고, 해당 사실을 이용하는 등의 구조를 취한다.

더보기
const numbers = [1, 2, 3, 4];
const double = x => x * 2;
const doubledNumbers = numbers.map(double);

console.log(doubledNumbers); // [2, 4, 6, 8]

다음은 JavaScript에서 함수형 프로그래밍 방식으로 배열의 각 요소를 두 배로 만드는 예시이다.

map 함수는 각 배열의 요소에 대해 double 함수를 호출하고, 결과를 새 배열에 모아 반환한다. 

이때 double 은 순수함수로, 항상 동일한 입력에 대해 동일한 2배가 된 배열을 반환하며, 실행의 결과로 다른 부분의 영향을 미치지 않는다.

 


* 메모리 구조

- 코드 영역 : 실행할 프로그램의 코드가 저장되는 영역. 사용자가 프로그램 실행 명령을 내리면 OS가 저장소에서 메모리로 실행 코드를 로드해온다. 그 뒤 CPU는 코드 영역에 저장된 명령어를 하나씩 처리한다.

( 실행 명령 -> OS가 해당되는 코드를 저장소에서 메모리로 로드 -> CPU는 코드 영역의 명령어 처리 )

 

- 데이터 영역 : 프로그램의 전역 변수와 정적 변수가 저장되는 영역이다. 즉, 프로그램의 시작에서 코드 영역에 프로그램 코드가 올라갈 때, 함께 로드되며 해당 변수들의 Scope이 프로그램 종료시까지인 것이다. 따라서 전역 변수와 정적 변수의 지나친 남발은 메모리 적 관점에서 좋지 못하다.

 

- 힙 영역 : 프로그래머가 직접 관리 가능한 메모리 영역. 이 공간에 메모리를 할당하는 것을 "Dynamic Assign"이라고 한다.

따라서 언어가 가비지 컬렉터 등을 지원하는 언어가 아닌 이상, 해당 공간에 malloc 등을 사용하여 선언 시 반드시 해제해줘야한다. 그렇지 못한다면, Dangling pointer 가 발생하게되고 이는 메모리 누수와 부족으로 이어진다.

 

- 스택 영역 : "함수의 호출" 과 함께 할당되며, 지역 변수와 매개 변수가 저장되는 영역이다. 스택 영역에 저장되는 함수의 정보를 "스택 프레임"이라고 한다. 즉 함수의 호출이 인식되면 지금까지 진행되던 정보와 함수가 return 될 시 돌아올 정보를 현재 메모리 공간에 저장하고 새로운 함수의 스택 프레임을 작성하기 시작한다. 함수가 return 되면 삭제된다.

 

* Call By Value Vs Call By Reference

Call By Value

1. 파라미터를 복사하여 처리하는 방식

2. 따라서 파라미터로 불러온 값을 함수 내부에서 바꾸고 함수가 return 되어 스택 프레임이 수거되면, 파라미터로 넘겨준 변수의 값은 변해있지 않다.

3. 값을 복사하여 넘겨 메모리 사용량이 증가된다. 또한 Object Class 등을 인자로 쓰면 Copy 부분을 정의해줘야하는 경우가 있을 수도 있다.

 

Call By Reference

1. 인자로 받은 주소에 있는 값을 건드는 방식

2. 직접 참조하므로 메모리 사용도 없고 속도도 빠르다.

3. 기존 값이 초기화되므로 리스크가 있다.


* 프레임 워크 Vs 라이브러리

라이브러리 : 사용자가 흐름에 대한 제어를 하며 필요한 상황에 가져다가 쓸 수 있다.

프레임 워크 : 전체적인 흐름의 제어권이 있다.


* Synchronous Vs Asynchronous

Synchronous (동기) :

1. 요청을 보내고 실행이 끝나면 확인 후 다음 동작을 처리하는 방식

2. 순서에 맞추어 진행이 보장된다.

3. 동시처리가 불가능해 효율이 떨어진다.

 

Asynchronous (비동기):

1. 요청을 보내고 확인을 안하고 바로 요청을 계속 보낸다.

2. 작업 완료 확인이 필요 없어 속도가 빠르다.

3. 작업이 완료된 결과를 제어하기가 어렵다.


* Docker와 Kubernates

기존에는 하드웨어를 가상화하였기 때문에 Host OS 위에 Guest OS를 설치해야했다

그러나 프로세스를 격리시킨 컨테이너를 통해 가상화를 하는 기능으로 이 단점을 극복한 것이 Docker이다.

여기서 컨테이너는 애플리케이션과 그 애플리케이션을 실행하는 데 필요한 모든 것이다.

글고 Docker를 통해 구동되는 컨테이너를 관리하기 위한 Kubernates가 등장하게 되었다.

더보기

운영 체제의 내용이긴 하지만,

본래 운영체제는 커널과 그 외의 주변 부분으로 구성된다.

주변 부분이 프로그램의 연락 내용을 커널에 전달하고, 커널이 하드웨어를 다루는 것이다.

Docker에서는 컨테이너가 완전히 격리된 또 다른 프로세스 위에서 돌아간다.

즉 OS 위에 도커 엔진이 동작하고 그 위에서 컨테이너가 돌아가는 것이다.

이를 통해 어플리케이션은 Docker 위에서 돌아가며, Application의 요청은 해당 하드웨어의 OS가 처리하는 방향으로 작업이 돌아가는 것이다.

이 과정을 통해, 애플리케이션과 그 종속성을 컨테이너 단위로 패키지해서 배포하여 작업에 일관된 환경을 제공할 수 있다. 즉, "개발 환경에서는 잘 됐는데, 왜 내 컴퓨터에서는 안되는거지?"를 방지하는 것이다.

 


* TDD ( Test-Driven Development )

- 매우 짧은 개발 사이클의 반복에 의존하는 개발 프로세스.

개발자는 우선 요구되는 기능에 대한 테스트케이스를 작성하고, 그에 맞는 코드를 작성하여  테스트를 통과한 뒤에 상황에 맞게 리팩토링하는 테스트 주도 개발 방식을 의미한다. 개발 전에 요구사항에 집중할 수 있도록 도와주지만 테스트를 위한 진입 장벽과 작성 코드량 증가의 단점이 있다.

 

* DDD ( Domain-Driven Design )

실세계에서 사건이 발생하는 집합인 Domain을 중심으로 설계하는 방법.

이 Domain들의 상호작용으로 설계하는 것이 도메인 주도 설계이다.

(ex: 손님들이 주문하는 Domain, 점주들이 관리하는 Domain 등.)


* MSA ( Microservices Architecture )

서비스를 독립적으로 배포가능한 각각의 서비스로 분할. 각각의 서비스는 API를 통해 데이터를 주고 받으며 하나의 큰 서비스를 구성하는 설계 접근 방식

장점 :

1.일부 서비스에 장애가 발생하여도 전체 서비스에 장애가 발생하지 않는다. 

2.각각의 서비스들은 서로 다른 언어와 프레임워크로 구성될 수 있다.

3. 서비스의 확장이 용이하다.

 

단점 :

1. 서비스가 분리되어있어 테스팅이나 트랜잭션 처리가 어렵다.

2. 서비스간 통신 비용이 발생한다.

'CS 기본 지식' 카테고리의 다른 글

4. CS 기본 지식 - 네트워크  (0) 2024.04.08
3. CS 기본 지식 - 알고리즘  (0) 2024.04.04
1. CS 기본 지식 - 자료구조  (0) 2024.04.02