React.lazy() 와 Suspense 먼저 알아보겠다. (해당 기록은 학습한 내용을 전반적으로 기록하면서 정리한 내용이다.)

코드 분할과 지연된 컴포넌트 로딩은 초기 시간이 감소, 성능향상에 장점이 있다.

React.lazy()

React.lazy 함수를 사용하면 dynamic import를 사용해 컴포넌트를 렌더링할 수 있다. 

다이나믹 임포트는 spa 이므로 한번에  사용하지 않는 컴포넌트까지 불러오는 단점이 존재한다.

리엑트에서는 React.lazy 를 통하여 동적으로 import 즉 모듈등 페이지를 불어올 수 있도록 제공한다. 

이렇게 React.lazy를 사용하면 처음부터 불러오는게 아니라 동적으로 필요할때 불러오기 떄문에

초기 렌더링 지연시간을 어느정도 줄일 수 있다.

 

구문은

import Component from './Component';

const Component = React.lazy(() => import('./Component'));

 

 React.lazy로 감싼 컴포넌트는 단독으로 쓰일 수는 없고, React.suspense 컴포넌트의 하위에서 렌더링을 해야 한다.

 


React.Suspense

라우터로 분기가 나누어진 컴포넌트들을 위 코드처럼 lazy 를 통해 임폴트 하면 해당 path로 이동할때 컴포넌트를 불러온다 이 과정에서 로딩하는 시간이 생기게 된다.

 

서스펜스는 아직 렌더링이 준비되지 않은 컴포넌트가 있을 떄 로딩 화면을 보여주고, 로딩이 완료되면 렌더링이 준비된 컴포넌트를 보여주는 기능이다.

기본 문법

<Suspense fallback={<Spinner />}>
  <UserList />
</Suspense>

 

위와 같이 사용하여 감싸고 사용하며 비동기 동기(useEffect, useState)api 호출등으로 사이드 이펙트가 발생할때 그 부작용을 방지할 수 있으며 해결 방안이 된다.


 

React.lazy와 Suspense의 적용

앱에 코드 분할을 도입할 곳을 결정하는것은 사실 까다롭다. 중간에 적용시키는 것보다는 웹 페이지를 불러오고 진입하는 단계인 route 에 이 두기능을 적용하는게 좋다.

import { Suspense, lazy } from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';

const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));

const App = () => (
  <Router>
    <Suspense fallback={<div>Loading...</div>}>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </Suspense>
  </Router>
);

 

라우터에 Suspense를 적용하는 것은 간단한 편이라고 한다.

라우터가 분기되는 컴포넌트에서 각 컴포넌트에 React.lazy를 사용하여 import한다.

그리고 Route 컴포넌트들을 Suspense로 감싼 후 로딩 화면으로 사용할 컴포넌트를 fallback 속성으로 설정해주면 된다.

초기 렌더링 시간이 줄어드는 분명한 장점이 있으나 페이지를 이동하는 과정마다 로딩 화면이 보여지기 때문에 서비스에 따라서 적용 여부를 결정해야 한다.

프론트개발자라고 해서 devops 를 모르는건 현 시대에 동떨어진 생각이라고 생각한다.

따라서 프론트엔드도 알아야하는 서버의 운영방식과 클라우드 컴퓨팅에서 알아보고자 한다.

 

● 서버란?

서버는 네트워크를 통해 다른 컴퓨터나 장치에 서비스를 제공하는 컴퓨터 시스템이다. 주로 서버는 클라이언트-서버 모델에서 서비스를 제공하고, 클라이언트는 서버에서 제공하는 서비스를 사용하는 역할을 합니다.

간단히 말하면, 서버는 데이터, 파일, 웹페이지, 애플리케이션 등을 클라이언트에게 제공하거나 처리하는 역할을 한다. 서버는 항상 켜져 있고, 네트워크를 통해 다양한 요청에 응답하며 필요한 데이터나 서비스를 제공한다.

서버는 여러 종류가 있을 수 있다. 예를 들면:

웹 서버 (Web Server): 웹 페이지, 이미지, CSS, JavaScript 등을 클라이언트에게 제공하여 웹 서비스를 가능하게 한다.

데이터베이스 서버 (Database Server): 데이터베이스에 접근하여 데이터를 저장, 검색, 수정, 삭제하고, 클라이언트 애플리케이션에 필요한 데이터를 제공한다.

파일 서버 (File Server): 파일이나 데이터를 클라이언트에게 공유하거나 저장하기 위한 서버이다.

애플리케이션 서버 (Application Server): 특정 애플리케이션을 실행하고 그 결과를 클라이언트에게 전달하는 서버이다.

서버는 일반적으로 고성능, 고용량, 신뢰성이 높아야 합니다. 또한 보안에도 신경을 써야하며, 여러 클라이언트로부터 동시에 요청을 처리할 수 있도록 설계되어야 한다.

 

서버를 운영하는 방법 2가지

크게 두가지로 나뉜다. 

- 온 프레미스

온프레미스 서버는 기업이나 조직의 내부 시설 안에 직접 구축하고 유지하는 서버를 말한다. 즉, 클라우드 서비스를 사용하지 않고 자체적으로 하드웨어와 소프트웨어를 구매하고 관리하는 방식을 의미한다. 여기에는 몇 가지 주요 특징이 있다.

물리적 위치: 온프레미스 서버는 조직이나 기업의 물리적인 시설 내에 존재합니다. 이는 보통 전용 서버 룸, 데이터 센터, 또는 서버 랙 안에 배치된다.

직접적인 관리: 온프레미스 서버는 해당 조직의 IT 팀 또는 담당자에 의해 직접 관리된다 이는 하드웨어의 유지보수, 소프트웨어 업데이트, 보안 등을 내부에서 책임지는 것을 의미한다

비용 및 자원 제어: 조직은 하드웨어와 소프트웨어를 직접 구매하므로 초기 투자비용이 높을 수 있다. 하지만 이후에는 운영 비용을 상대적으로 효율적으로 관리할 수 있다.

보안 및 컨트롤: 조직은 자체 보안 정책을 적용하고 데이터를 직접 관리할 수 있어 보안 및 컨트롤 측면에서 높은 수준의 유연성을 제공한다.

온프레미스 서버는 클라우드 서비스와 대조적으로 자체 인프라를 소유하고 운영하는 모델이며, 특히 보안 및 컨트롤이 중요한 조직이나 규제가 높은 업종에서 선택되는 경향이 있다.(유지보수가 어렵고 다시 구축하는등 어려움이 있어 많은 기업이 클라우드로 선택하는 기업들이 늘어나는 추세이다.)여기서 오는 단점도 있으나 장점으로는 서버를 온전히 통제가 가능하다는 장점이 존재한다.

 

- 클라우드 컴퓨팅

클라우드 컴퓨팅은 인터넷을 통해 컴퓨터 리소스(서버, 스토리지, 네트워크 등)를 제공하고 액세스하는 기술로, 필요한 서비스를 유연하게 이용할 수 있게 한다. 사용자는 자체적으로 하드웨어를 소유·운영하지 않고 필요한 만큼의 자원을 신속하게 확장하거나 축소하여 비용을 절감하며, 데이터와 애플리케이션을 온라인으로 관리한다.

 

간단하게 설명하면 다른 클라우드 기업에서 온프레미스로 서버를 운영하고 있는 부분을 빌려서 사용한다. 이것을 클라우드 컴퓨팅을 사용한다고 하는것이다.

 

- 클라우드 컴퓨팅의 구분

클라우드 컴퓨팅은 제공하는 서비스로 3개의 계층으로 구분지은다.

 

 IaaS(Infrastructure as a Service)

 IaaS 는 클라우드 컴퓨팅의 가장 기본적인 형태 인프라를 구축하기 위해 필요한 컴퓨터를 대여해주는것을 의미

 IaaS 대여받은 컴퓨터의 대부분의 리소스에 접근하여 서비스를 구성 관리하며 가장 많은 제어권을 가지고 있지만 가장많은 부분을 사용자가 구성하고 관리 해야하는 단점이 존재한다.

- > AWS EC2

- EC(eleastic cloud computing) 탄력적으로 빌려쓸 수 있는 컴퓨터
- 컴퓨터 빌려 쓰기 
- 가장 많은 제어권을 가짐
- 윈도우 등 어떤 os를 쓸건지 내가 다 일일이 정해야한다.

 

PaaS(Platform as a Service)

PaaS는 IaaS에 더불어 소프트웨어를 개발하고 운영하기 위해 필요한 구성요소들을 플랫폼화해서 제공해주는 서비스다. PaaS를 사용하면 개발자들은 소프트웨어의 운영에 대한 관리를 PaaS에 위임할 수 있기 때문에 효율적인 개발이 가능하다. 다만, 플랫폼의 형태로 제공된다는 점으로 인해 특정 플랫폼에 종속적이 될 수 있다는 점, 해당 플랫폼에서 접근을 허용하지 않는 부분은 제어할 수 없다는 점, IaaS에 비해 더 높은 비용을 지불해야 할 수도 있다는 점 단점들도 있다.
-> AWS Elastic BeanStalk, Heroku, Github Pages(배포 플랫폼 서비스)
- 개발자야 웹서비스 운영할거야? 웹서비스 운영하기 편하게 플랫폼화 시켜서 너희들에게 제공해줄게
- 약간 프레임워크같은 느낌 플랫폼에서 제공하는 것들만 사용할 수 있다는 단점을 가짐

 

 

SaaS(Software as a Service)

SaaS는 클라우드 서비스에 더불어, 고객이 이를 사용할 수 있는 소프트웨어가 함께 제공되는 형태를 의미한다. 클라우드 서비스를 통해서 제공받기에 명시적으로 애플리케이션을 PC에 설치할 필요가 없으며, 서비스를 활용하기 위해 만들어진 소프트웨어가 제공되기에 이를 통해 편리하게 여러 기능등을 제공받고 활용할 수 있는 형태이다.

-> DropBox, iCloud, Netflix, Google Apps, Slack

 

-  AWS S3

AWS의 S3서비스는 Simple Storage Service의 약자입니다. Storage라는 표현 그대로 특정한 파일을 저장하고 인터넷상으로 접근할 수 있게 해주는 서비스이다. 보통 서비스에 필요한 이미지나 파일등을 저장해두는 용도로 사용하지만 정적인 파일들을 안정적으로 제공할 수 있다는 점을 이용해서 정적 웹사이트 호스팅에도 사용할 수 있다.

Create React App을 이용해서 만든 리액트 프로젝트의 경우 build 명령어를 실행하면 정적인 build 파일들이 생성되고 이를 브라우저에서 접근해서 실행하면 Client Side Rendering을 통해서 동작하는 특징을 이용해서 S3서비스를 통해서 배포를 할 수 있다.
csr 같이 검색이 필요없는 (관리자페이지) 등은 s3로 호스팅이 가능하다 => S3로 호스팅 할 수 있음

Next.js는 동적이고 ssr 기능이 필요하여 호스팅을 못한다. => S3 호스팅할 수 없음 

 

 

'Cloud > Aws' 카테고리의 다른 글

정적인(Static) React 앱을 (CSR)로 구축하고 배포  (0) 2023.12.24

이번글은  깔끔하면서 체계적인 모듈화 및 코드를 작성할 수있도록 리액트 클린 아키텍처를 작성해보겠다.

 

아키텍처의 중요성은 로버트 c 마틴의 클린 아키텍처에서 서술하기를 기능은 구조에 의지한다는 것이다. 이 점을 이해하기위해서는 코딩이라는 행위에 담겨져 있는 내재적 관점을 살펴 봐야 한다. 우리가 회사에 들어가서 하는 행위는 코딩이며 목정적성을 생각하면 다음과 같다.

 

우리는 코드를 이해하고 읽으며 수정/ 추가 유지보수 하는 일을 많이 하게된다. 따라서 이런 행위를 우리는 제일 먼저 프로젝트의 구조를 파악하고 아키텍처와도 밀접한 관계성을 갖는다. 예를 들어 지저분한 방에서 물건을 찾을 때 와 정돈된 방에서 물건을 찾는 속도는 차이가 나듯이 프로젝트의 구조에서도 정돈된 구조는 개발자의 속도에도 영향을 끼친다.

 

회사의 입장에서는 클린한 코드로 최소한의 인력으로 최대의 이익을 창출해야 하며 이는 소프트웨어 아키텍처의 목표인 필요한 시스템을 만들고 유지보수하는데 투입되는 인력을 최소화 하는것과 상응하게 된다.

 

클린 아키텍처란?

로버트 가 제안한 방법으로 관심사를 확실히 분리하여 효율적으로 재사용이 높은 컴포넌트를 구현 할 수 있게끔 만들수 있는 아키텍처 이다. 최소한의 노력으로 최대의 효율을 얻게 해주는 것이다.

 

 

클린 아키텍처의 기본 이론

  • 체계적으로 계층이 분리되어야한다.
  • 각 계층은 서로 맡은 역할을 충실히 수행한다.
  • 계층간의 의존성 관계가 잘 이루어져야한다.

핵심 개념

  • 안쪽의 원(비즈니스 로직) 바깥의 원(UI나 data source)에 대해 전혀 알지 못한다.
  • 안쪽 영역으로 갈수록 추상화와 정책의 수준이 높아지며, 반대로 갈수록 구체적인 세부사항으로 구성된다.

클린아키텍처 구조의 이해

 

이 글에서는 Next.js 프로젝트를 대상으로 위의 규칙을 준수하여 구성해 보겠다.
Next.js의 많은 예제들의 수준과 비슷하게 한다면, 아래와 같은 계층을 가진 구조의 모양이 나올 수 있다.

Core

입력과 출력으로부터 거리가 멀기 때문에 고수준이라고 볼 수 있는 계층이다.
앞서 말한 원칙에서 세부적인 도메인 로직이 아닌, 웹 애플리케이션 로직과 추상화된 코드들이 들어간다.
예를 들면 아래와 같은 성격의 코드들이 들어갈 수 있다.

  • 애플리케이션이 외부와의 통신을 위해 필요한 구현체
  • 도메인과 연관이 없는 고수준의 유틸리티
  • 재사용가능한 컴포넌트
    • ex) Button, Input, Select
  • 중요도가 높은 외부 모듈(라이브러리)의 어댑터

Core 계층에 있는 코드들은 절대 Core 원의 외부에 있는 계층(lib/components, pages)을 참조하면 안 된다.

Components / Lib

이 계층은 도메인에 종속적이며, Core 계층의 코드들을 참조할 수 있고, 아래 예시와 같은 코드들이 들어간다.
( 주문이라는 도메인이 속한 프로젝트라고 가정. )

 

- src
     - lib
         - order
             - constatns
             - hooks
             - mutations
             - queries
             - utils
             - ....
 
 - src
     - components
         - order
             - ItemList.tsx
             - Price.tsx
             - Payment.tsx
             - ...

 

  • Lib
    • 도메인에 관련되어 있는 로직들.
    • components 계층과 pages 계층에서 참조되어진다.
  • Components
    • 도메인에 관련되어 있는 컴포넌트.
    • 도메인에 국한되어 재사용성은 낮다.
    • pages 계층에서 참조되어진다.

Pages

도메인에 의존도가 높은 계층. 입력/출력과 밀접해있으며, 가장 저수준이라고 볼 수 있다.
Next.js의 기본 설정 값인 파일 시스템 기반으로 라우팅 처리를 하며, Components Lib 계층의 코드들을 참조하여 구성할 수 있다.

- src
   - pages
     - api
       - order
         - [...slug].tsx  // src/lib/order/.. 참조
         - ...
     - order
       - [id].tsx // src/components/order/.. 참조
       - _middleware.tsx // src/lib/order/.. 참조
       - ...

 

Dependency diagram

위의 구조와 규칙을 가지고 간략히 의존성 그래프로 표현하면 아래와 같은 모양이 될 것이다.

의존성은 모두 단방향으로만 흘러가고, 역으로 참조해서는 안 된다.

예를 들어, core 계층에 API 통신을 위한 구현체가 있다고 가정해 보자.
이 구현체는 UI의 형태 혹은 상태, 세부적인 도메인 로직를 알아서는 안되며, 알아도 좋을 게 없다.
마찬가지로 도메인에 종속적인 코드들 또한, 이 구현체가 비동기 통신을 위하여 어떤 객체를 사용하여 구현이 되었는지, 어떻게 API 서버와 통신을 하는지 전혀 알 필요가 없다.

이러한 관심사의 분리로 인해 각 모듈은 여러 책임에서 벗어나기 쉽고, 테스트하기도 더 쉬워지며, 유지 보수 비용도 줄어들 것이다.

 

아래는 내가 직접 응용한 구조이다. 

 

 

core -> common에 api 를 담은 폴더와 타입들을 지정해둔 각 서비스 마다 dto 폴더를 생성하여 정의하였고

useCasese -> 각 서비스 아래에 폴더이른과매칭되는 ts 파일로 어플리케이션 비즈니스 로직을 수행하는 영역으로 api 통신에 있어 중간다리하는 역할 하는 부분으로 구분을 지었다. 

controller -> 부분은 pages 폴더 추후에 추가할 custom hook 폴더를 추가할 예정이다.

 

결론

실무에서 업무를 하다보면 직관적이지 못한 프로젝트 구조들로 인해 많은 시간을 낭비하였다. 좋은코드구조는 남들이보기에 한눈에 들어오는 구조이며 누구나 이해할 수 있는 영역이라고 생각한다.그런 구조를 생각하면서 구조를 짜고 코드를 생성 한다면 개발자의 시간 등이 많이 아껴지리라고 본다.

 

 

깃허브 https://github.com/asdf132645/reactToyProject

 

실무에서 추상화 작업을 할때 구현체를 구현할때 사용하는건 type 과 인터페이스를 사용했다.

type 을 사용할떄는 인터페이스의 확장성이 필요없을 경우 사용한다.

 

 

타입스크립트에 인터페이스는 일급 클래스 원시타입을 제공한다. 한객체가 다른 객체를 상속할 수 있게 해주는거를 말한다. 

interface WithId {
  id: string
}

interface UserInfo extends WithId {
  name: string
}

const user: UserInfo = {
  id: 'coin',
  name: 'kjy',
  password: 0000, // Error!
}

 

이런식으로 상속이 가능하게 해준다. 

 

타입을 사용시에는 새로운 속성을 추가하기 위해서 다시 같은 이름으로 선언을 하지 못한다 const 와 같은 맥락이라고 생각하면된다. 하지만 인터페이스에서는 항상 선언적확장이 가능하다. 그차이에 대해서 아래와 같은 예제가있다.

 

nterface Window {
  title: string
}

interface Window {
  ts: TypeScriptAPI
}

// 같은 interface 명으로 Window를 다시 만든다면, 자동으로 확장이 된다.

const src = 'const a = "Hello World"'
window.ts.transpileModule(src, {})

 

type Window = {
  title: string
}

type Window = {
  ts: TypeScriptAPI
}

// Error: Duplicate identifier 'Window'.
// 타입은 안된다.

 

인터페이스에서는 무조건 객체 구현체를 만드는 부분만 가능 이건 상식중에 상식이다.

타입은 컴퓨티드에 value의 사용 

interface FooInterface {
  value: string
}

type FooType = {
  value: string
}

type FooOnlyString = string
type FooTypeNumber = number

// 불가능
interface X extends string {}

 

type names = 'firstName' | 'lastName'

type NameTypes = {
  [key in names]: string
}

const yc: NameTypes = { firstName: 'hi', lastName: 'yc' }

interface NameInterface {
  // error
  [key in names]: string
}

 

성능을 위해서는 인터페이스를 사용하는것이 좋다.

결론은 현 프로젝트에서 인터페이스가 적합한지 아니면 타입이 적합한지 통일은 필요하며 객체 타입간의 합성등을 고려해봤을떄는 인터페이스를 쓰는것이 더 좋지 않을까 싶다.

'타입스크립트,자바스크립트' 카테고리의 다른 글

타입스크립트 스타일 정의  (0) 2024.12.20

1. 스키마 (Schema)
GraphQL 스키마는 데이터의 형태와 어떤 요청을 할 수 있는지 정의합니다. 스키마는 타입 정의와 쿼리, 뮤테이션, 서브스크립션 등을 포함합니다.

 

type Query {
  user(id: ID): User
  users: [User]
}

type User {
  id: ID
  name: String
  email: String
}

 

위의 예제에서는 Query 타입에 user와 users 필드가 정의되어 있습니다. User 타입은 사용자의 속성을 정의합니다.

 

2. 쿼리 (Query)
GraphQL에서는 클라이언트가 서버에게 어떤 데이터를 요청할 지를 명시적으로 정의합니다.

query {
  users {
    id
    name
    email
  }
}

위의 쿼리는 서버로부터 사용자의 id, name, email을 요청합니다.

3. 뮤테이션 (Mutation)
뮤테이션은 데이터를 변경하거나 새로운 데이터를 생성하는 데 사용됩니다.

mutation {
  createUser(input: { name: "John Doe", email: "john@example.com" }) {
    id
    name
    email
  }
}

 

위의 뮤테이션은 새로운 사용자를 생성하는 요청을 나타냅니다.

GraphQL 코드 예제
1. 서버 예제 (Node.js + Express + express-graphql)

 

const express = require('express');
const { graphqlHTTP } = require('express-graphql');
const { buildSchema } = require('graphql');

// 스키마 정의
const schema = buildSchema(`
  type Query {
    user(id: ID): User
    users: [User]
  }

  type User {
    id: ID
    name: String
    email: String
  }
`);

// 더미 데이터
const users = [
  { id: '1', name: 'John Doe', email: 'john@example.com' },
  { id: '2', name: 'Jane Smith', email: 'jane@example.com' },
];

// 레졸버 함수
const root = {
  user: ({ id }) => users.find(user => user.id === id),
  users: () => users,
};

const app = express();

// GraphQL 미들웨어 설정
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: root,
  graphiql: true, // 개발용 GUI
}));

const port = 4000;
app.listen(port, () => {
  console.log(`GraphQL server is running at http://localhost:${port}/graphql`);
});

 

2. 클라이언트 예제 (React + Apollo Client)

Apollo Client는 GraphQL을 사용하는 웹 애플리케이션을 위한 상태 관리 라이브러리 중 하나입니다. Apollo Client는 클라이언트 측에서 GraphQL 데이터를 효율적으로 관리하고 가져오는 데 도움이 되는 도구와 기능을 제공합니다.

Apollo Client의 주요 기능 및 목적은 다음과 같습니다:

GraphQL 데이터 쿼리 및 뮤테이션 관리: Apollo Client는 GraphQL 서버에서 데이터를 쿼리하고 뮤테이션을 수행하기 위한 기능을 제공합니다. GraphQL 쿼리를 작성하고 컴포넌트에서 필요한 데이터를 가져오는 데 사용됩니다.

상태 관리: Apollo Client는 클라이언트 측에서 관리해야 하는 상태를 추상화하고, 애플리케이션의 로컬 상태와 원격 데이터를 효율적으로 조화시켜줍니다.

캐싱 및 데이터 정규화: Apollo Client는 원격 서버에서 받은 데이터를 캐싱하고, 캐시된 데이터를 사용하여 성능을 향상시킵니다. 또한, 정규화를 통해 중복 데이터를 효과적으로 관리합니다.

실시간 데이터 갱신: GraphQL Subscriptions을 통해 실시간으로 데이터를 갱신할 수 있습니다. 이를 통해 서버에서 데이터가 업데이트되면 클라이언트에게 자동으로 푸시됩니다.

다양한 프레임워크 및 라이브러리와의 통합: Apollo Client는 React, Angular, Vue 등 다양한 프론트엔드 프레임워크와 라이브러리와의 통합을 지원합니다.

Apollo Client는 개발자가 GraphQL을 사용하여 데이터를 관리하고 렌더링하는 데 있어 편리한 방법을 제공하여 생산성을 향상시킵니다.


아래 예제코드로 작성 해봤습니다.

import React from 'react';
import { ApolloProvider, useQuery, gql } from '@apollo/client';

// GraphQL 쿼리 정의
const GET_USERS = gql`
  query {
    users {
      id
      name
      email
    }
  }
`;

// 컴포넌트
const UserList = () => {
  const { loading, error, data } = useQuery(GET_USERS);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return (
    <ul>
      {data.users.map(user => (
        <li key={user.id}>
          {user.name} - {user.email}
        </li>
      ))}
    </ul>
  );
};

// ApolloProvider로 감싸기
const App = () => (
  <ApolloProvider uri="http://localhost:4000/graphql">
    <UserList />
  </ApolloProvider>
);

export default App;

위의 코드 예제는 Node.js와 Express를 사용한 GraphQL 서버와 React를 사용한 클라이언트의 간단한 구조를 보여줍니다. 클라이언트에서는 Apollo Client를 사용하여 GraphQL 서버와 통신하고 데이터를 가져오는 예제입니다.






 

객체 지향 프로그래밍(OOP, Object-Oriented Programming)은 프로그래밍 패러다임 중 하나로, 코드를 객체 단위로 구성하고 객체 간의 상호작용을 중심으로 프로그래밍하는 방법론이다. OOP를 사용하는 이유와 실무에서의 중요성을 알아보겠다.

 


OOP의 주요 개념

 


1. 클래스와 객체
클래스(Class): 객체를 생성하기 위한 일종의 틀 또는 설계도이다. 클래스는 객체의 속성(attribute)과 행위(behavior)를 정의한다.

객체(Object): 클래스를 기반으로 실제로 메모리에 할당된 것으로, 속성과 메소드를 포함한 것이다.

2. 캡슐화 (Encapsulation)
관련된 데이터와 메소드를 하나의 단위로 묶고, 외부에서의 직접적인 접근을 제한하는 것을 의미한다.

데이터 은닉(data hiding)을 통해 객체 내부의 상태를 보호하고, 객체 간 인터페이스를 통한 상호작용을 간소화한다.

3. 상속 (Inheritance)
이미 존재하는 클래스의 속성과 메소드를 새로운 클래스에서 재사용할 수 있게 하는 개념이다.

코드의 재사용성을 높이고, 계층 구조를 통해 유지보수 및 확장이 용이하다.

4. 다형성 (Polymorphism)
여러 객체가 동일한 인터페이스를 사용하거나 동일한 작업을 수행할 수 있는 능력을 의미한다.
코드의 유연성을 높이고, 한 가지 인터페이스를 통해 여러 객체를 다룰 수 있다.

 

OOP 사용 이유

1. 코드 재사용성
OOP는 상속을 통해 코드를 재사용할 수 있도록 지원합니다. 이미 작성된 클래스를 확장하여 새로운 클래스를 만들 수 있고, 이는 중복 코드의 최소화로 인해 유지보수성을 향상시킨다.

2. 유지보수성 증가
객체 지향 프로그래밍은 코드의 구조화와 모듈화를 촉진하여 유지보수성을 높다. 수정이나 추가가 필요한 부분을 해당 클래스나 모듈에서만 수행할 수 있어, 예상치 못한 부작용이 줄어든다.

3. 코드의 가독성 및 이해도 향상
객체, 클래스, 메소드 등의 개념을 사용하면 현실 세계의 개념과 유사하게 코드를 작성할 수 있다. 이는 코드의 가독성을 향상시키고 다른 개발자들이 코드를 이해하기 쉽게 만든다.

4. 유연성과 확장성
캡슐화와 다형성을 통해 객체 지향적인 코드는 유연하고 확장 가능하다. 새로운 기능을 추가하거나 수정할 때 기존 코드에 영향을 미치지 않으면서 새로운 클래스나 모듈을 추가할 수 있다.

5. 프로그램의 모델링에 용이
현실 세계의 개념을 클래스와 객체로 모델링할 수 있어 프로그램을 개발하거나 이해하기 쉽다. 이는 개발자들 간의 의사소통을 강화하고 프로젝트를 효과적으로 관리할 수 있게 한다.

+ Recent posts