Next.js와 데이터베이스

"use client" 지시어: 컴포넌트 파일 최상단에 "use client"를 선언하면, 해당 컴포넌트는 클라이언트(브라우저)에서 렌더링되고 실행됩니다. 이를 통해 useState, useEffect 같은 React Hook이나 브라우저 API를 사용할 수 있으며, 기존의 CSR 방식으로 개발 가능합니다. 이러한 CSR 방식을 사용할 경우, react-query와 같은 데이터 페칭 라이브러리를 적용하여 클라이언트 측에서 데이터를 관리할 수 있습니다.

서버 컴포넌트: "use client"가 없는 컴포넌트는 기본적으로 서버(Node.js 환경)에서 실행됩니다. 이는 데이터베이스 조회나 파일 시스템 접근 등 서버에서만 가능한 작업을 안전하게 처리하는 데 유리합니다.


실행 환경 구분: Next.js는 하나의 프로젝트 안에서 서버(Node.js 환경)와 클라이언트(웹 브라우저 환경) 코드를 모두 다룹니다.

 

이러한 Next.js는 핵심적인 렌더링 환경을 서버에서 사용할 것인지 웹에서 사용할 것인지 구분해야 하며, 이는 노드에서 사용할 것인지 브라우저에서 사용할 것인지 결정하는 것과 같습니다.

Link 컴포넌트와 Prefetch 기능

LinkPrefetch 기능은 Next.js의 사용자 경험을 극대화하는 요소입니다.

 
  • Link 컴포넌트: 페이지 간 이동을 위해 <a> 태그 대신 사용하는 Next.js의 기본 컴포넌트입니다. <a> 태그와 달리, Link 컴포넌트는 페이지 전체를 새로고침하지 않고 변경된 부분만 다시 그리는 클라이언트 사이드 네비게이션을 구현하여 매우 빠른 페이지 전환을 제공합니다.

  • Prefetch 기능: Link 컴포넌트의 핵심 기능 중 하나로, 사용자가 링크를 클릭하기 전에 해당 페이지에 필요한 데이터를 미리 불러오는 기술입니다. 화면에 Link 컴포넌트가 보이면 Next.js는 백그라운드에서 연결된 페이지의 코드와 데이터를 조용히 가져옵니다. 덕분에 사용자가 링크를 클릭했을 때, 거의 지연 시간 없이 즉시 페이지가 로드되는 것처럼 느껴집니다.

이미지 최적화 (<Image> 컴포넌트)

import Image from 'next/image'를 통해 사용하는 Image 컴포넌트는 웹 성능을 향상시킵니다.

 
  • 레이아웃 시프트(Layout Shift) 방지: 이미지가 로드될 공간을 미리 확보하여 이미지가 뒤늦게 로딩되면서 다른 요소들을 밀어내는 '레이아웃 시프트' 현상을 방지합니다.
     
  • 자동 최적화: 사용자의 기기(PC, 모바일 등)에 맞는 최적의 이미지 크기를 제공하고 WebP와 같은 최신 이미지 포맷으로 자동 변환하여 데이터 사용량을 줄이고 로딩 속도를 높입니다.

데이터베이스와 시스템 분석

시스템과 데이터의 본질

  • 시스템이란? 여러 구성 요소가 각자의 역할을 수행하며 유기적으로 결합된 집합체입니다. 만약 요소가 증거(데이터)를 남기지 않는 등 역할을 제대로 하지 않으면 시스템은 붕괴될 수 있습니다.
     
  • 데이터베이스: 정규화된 데이터의 베이스(기반)입니다.
     
  • 데이터의 의미: 시스템 안에서 발생하는 모든 행위의 '증거' 또는 '기록'입니다. 따라서 무엇을 데이터로 관리할지 결정하는 것은 "무엇을, 언제, 왜 저장하는가?"에 대한 답을 찾는 과정입니다.
     
  • 시스템 설계의 기준: 시스템을 만드는 기준은 결국 업무를 수행하는 사용자(액터)들의 행위, 즉 업무 로직(Business Logic) 입니다.
     

데이터 모델링 과정

데이터베이스를 설계하는 과정은 크게 3단계로 구성됩니다.

 
  1. 개념적 설계 (Concept Design): 업무적인 흐름을 분석하여 데이터베이스에 저장할 데이터를 선별하고, 각 요소(엔티티)와 그들 간의 관계를 정의하는 단계입니다.
    • 엔티티(Entity): 저장할 데이터의 대상. 다이어그램에서 사각형으로 표현됩니다. (예: 손님, 요리사, 메뉴)
    • 관계(Relation): 엔티티 간의 행위. 마름모로 표현됩니다. (예: 주문, 결제)
  2. 논리적 설계 (Logical Design): 개념적 설계의 결과를 관계형 데이터베이스(R-DB)의 테이블 구조로 변환하는 과정입니다. 이 단계에서 데이터 정규화가 이루어집니다.
     
  3. 물리적 설계 (Physical Design): 논리적 설계를 특정 DBMS(MySQL, PostgreSQL 등)의 실제 테이블 형태로 만드는 최종 단계입니다. 데이터 타입, 길이, 제약조건 등을 구체적으로 설정합니다.

데이터 정규화(Normalization)

  • 정규화란? 데이터베이스 테이블의 '표준화' 과정입니다. 데이터의 결함을 제거하고, 특히 중복을 제거하여 데이터의 일관성과 무결성을 확보하는 것을 목표로 합니다.
     
  • 목표: 중복이 제거된 파일(테이블) 형태가 표준이며, 그 표준에 맞추는 것이 정규화입니다.
728x90

 Next.js란 무엇인가?

  • 정의: React 라이브러리를 기반으로 구축된 오픈소스 풀스택(Full-stack) 웹 프레임워크입니다.

  • 핵심 개념: 프레임워크는 정해진 골격(구조)과 규칙을 제공하며, 개발자는 그 틀 안에서 코드를 작성합니다. 이는 라이브러리와의 가장 큰 차이점으로, 프레임워크가 코드의 흐름을 제어하는 '제어의 역전(IoC)' 개념이 적용됩니다.

제어의 역전 (IoC, Inversion of Control)

'제어의 역전'은 소프트웨어 공학의 중요한 원칙으로, 프레임워크를 이해하기 위해 도움이 됩니다.

전통적인 프로그래밍에서는 개발자가 작성한 코드가 프로그램의 전체 흐름을 직접 제어합니다. 그러나, 제어의 역전(IoC)에서는 프레임워크가 프로그램의 흐름을 주도하고, 개발자의 코드는 프레임워크에 의해 '호출'되어 사용됩니다. 이는 제어의 주체가 개발자에서 프레임워크로 넘어간(역전된) 것입니다.

  • 개발자의 집중도 향상: 개발자는 웹 서버를 만들고, URL을 분석하고, HTTP 요청을 처리하는 등 반복적이고 복잡한 기반 작업에 신경 쓸 필요가 없습니다. 프레임워크가 모두 처리해주므로, 오직 비즈니스 로직(실제 기능 구현)에만 집중할 수 있습니다.
  • 결합도 감소 (Decoupling): 컴포넌트나 모듈들이 서로에게 깊게 의존하지 않게 되어 코드를 더 모듈화하고 유지보수하기 쉬워집니다.
  • 재사용성 및 확장성 증가: 프레임워크라는 잘 짜인 구조 안에서 부품(컴포넌트)을 갈아 끼우기 쉽습니다. 새로운 기능을 추가하거나 기존 기능을 수정하기가 매우 용이해집니다.

 

 

Next.js를 사용하는 이유

  • 서버사이드 렌더링(SSR): 서버에서 페이지를 미리 그려 사용자에게 전달하므로, 초기 로딩 속도가 빠르고 검색 엔진 최적화(SEO)에 매우 유리합니다. (React는 전체 파일을 한 번에 보내지만, Next.js는 필요한 부분만 먼저 보냅니다.)

  • 파일 시스템 기반 라우팅: app 폴더 안에 폴더를 생성하면, 그 폴더명이 바로 URL 경로가 됩니다. React처럼 별도의 라우팅 설정이 필요 없어 직관적이고 편리합니다.

  • 최적화 기능: 코드 분할, 이미지 최적화 등 성능 향상을 위한 다양한 기능이 내장되어 있습니다.

프로젝트 구조와 컴포넌트 관리

  • app 폴더: 사용자가 요청하는 페이지(동적 문서)를 제공하는 핵심 공간입니다.

  • 컴포넌트 관리
    공용 컴포넌트: 여러 페이지에서 재사용되는 컴포넌트나 외부 라이브러리는 최상단에 components 폴더를 만들어 공동으로 관리하는 것이 효율적입니다.

    지역(특정 페이지) 컴포넌트: 해당 페이지에서만 사용되는 컴포넌트는 그 페이지 폴더 근처에 두어 관리하는 것이 좋습니다.

스타일링 (CSS)

  • global.css: app 폴더 내에 위치하며, 이름 그대로 프로젝트 전역에 적용될 공통 스타일을 정의합니다. 프레임워크의 규칙에 따라 이 파일명을 사용하는 것이 권장됩니다.

  • 저장 위치
    app 폴더: 컴포넌트와 함께 번들링되어 사용자에게 전달될 CSS 파일을 저장합니다. 애플리케이션 소스 코드를 저장하며,  폴더 안의 파일들은 컴포넌트와 함께 처리되고 번들링되어 최적화됩니다. 또한, Next.js가 빌드 시점에 코드를 분석하고 최적화하고 CSS 파일은 압축되어 이미지는 기기에 맞게 크기가 조절됩니다.

    public 폴더:
    서버에 저장해두고 직접 참조하는 이미지, 폰트 등 정적(Static) 파일을 보관하는 곳이며 파일 그대로 서버에 저장되고 제공됩니다. 특징으로는 Next.js가 코드를 압축하거나 최적화하지 않으며, 폴더 안의 경로가 그대로 URL 주소가 됩니다. (예: public/logo.png → 내사이트.com/logo.png)

 

 

728x90

타입스크립트의 필요성 및 개요

  • 타입스크립트란? 자바스크립트에 '타입(Type)'이라는 개념을 추가하여 더 안전하고 예측 가능한 코드를 작성할 수 있게 해주는 언어입니다. 결국 자바스크립트로 변환되어 실행됩니다.
  • 타입스크립트의 필요성 (쓰는 이유): 자바스크립트가 데이터를 확정 짓는 능력(동적 타입)이 부족하여 런타임 오류가 발생하기 쉽기 때문에, 타입스크립트는 : (콜론)이라는 한정사(타입 어노테이션)를 사용하여 변수나 함수의 데이터 형식을 미리 선언(확정)함으로써, 코드 실행 전에 오류를 찾아내고 안정성을 높입니다. 이를 통해 대규모 프로젝트의 유지보수성과 협업 효율성을 크게 향상시킵니다.

type과 interface의 차이점

  • interface (인터페이스):
    접점(Interface): 이름 그대로 '접점'의 역할을 합니다. 주로 객체의 구조를 정의하고, 다른 클래스가 특정 인터페이스의 형태를 따르도록 implements 키워드를 통해 강제할 수 있습니다 (객체 지향적 관점).

    확장 가능: 다른 인터페이스를 extends 키워드를 통해 상속받아 확장할 수 있습니다.

    선언적 병합(Declaration Merging) 가능: 같은 이름으로 여러 번 선언하면 타입스크립트가 이를 하나로 합쳐줍니다. 라이브러리 타입 확장에 유리합니다.
  • type (타입 별칭 / Type Aliases):

    타입의 형식 지정: 기존 타입에 새로운 이름을 부여하여 복잡한 타입을 간결하게 표현하거나, 유니언 타입, 인터섹션 타입 등 복합적인 타입들을 정의할 때 주로 사용됩니다.

    확장 불가능 (결합): extends를 통한 상속은 불가능하지만, & (인터섹션 타입)을 사용해 여러 타입을 '결합'하는 방식으로 유사한 효과를 낼 수 있습니다.

    선언적 병합 불가능: 같은 이름으로 여러 번 선언하면 오류가 발생합니다.

    객체의 구조를 타입으로 정의하는 예시:위 코드는 직접 객체 리터럴의 타입을 정의하는 방식으로, 매번 동일한 구조의 객체 타입을 반복해서 정의해야 하는 비효율성이 있습니다. 이럴 때 type이나 interface를 사용하면 코드 재사용성과 가독성을 높일 수 있습니다:
    type UserType = { name: string; age: number; }; // type을 사용하여 객체 구조를 타입으로 정의
    const user1: UserType = { name: "John", age: 30 };
    const user2: UserType = { name: "Jane", age: 20 };
    
    const user: { name: string; age: number; } = { name: "Alice", age: 30 };
    

타입스크립트의 다양한 타입들

  • 유니언 타입 (Union Types): | (파이프) 기호를 사용하여 둘 이상의 타입 중 하나를 가질 수 있음을 나타냅니다. 예: let value: string | undefined = "Hello"; (값은 문자열이거나 undefined일 수 있음)
  • 리터럴 타입 (Literal Types): 변수가 특정 고정된 값만 가질 수 있도록 형식(타입)을 제한하는 것입니다. 문자열, 숫자, 불리언 리터럴을 타입으로 사용할 수 있습니다. 예: let direction: "up" | "down" = "up"; (변수는 "up" 또는 "down" 값만 가질 수 있음)
  • 열거형 (Enum Types): enum 키워드를 사용하여 숫자 값 집합에 이름을 부여하는 타입입니다. "리터럴과 80% 비슷하며 둘 중 하나를 선택하여 사용할 수 있다."는 설명은 리터럴 타입처럼 특정 값들을 제한한다는 점에서 유사하지만, 숫자에 이름을 부여하여 가독성을 높이고 특정 값들의 집합을 '미리 정의된 코드'로 사용할 때 더 유용하다는 의미입니다.
    • 목적: 숫자 형태를 이해하기 쉬운 문자로 만들어 코드 가독성을 높입니다.
    • 예시: enum Direction { Up, Down, Left, Right }
    • 특징: Up은 자동으로 0, Down은 1 등으로 숫자가 할당되며, 필요하면 직접 숫자를 지정할 수도 있습니다 (예: enum HttpStatus { OK = 200, NotFound = 404 }).
    • 정적이고 엄격한 사용: 상수로 선언하여 리터럴 타입을 사용하는 것보다 더 엄격하게, 더 정적으로 사용될 수 있습니다.

4. 객체 지향 프로그래밍 (OOP)과 클래스

  • 객체 지향 프로그래밍(OOP) (방법론): 프로그래밍 방법론 중 하나로, 프로그램을 객체 위주, 객체 중심으로 구성하여 현실 세계의 사물처럼 데이터(속성)와 기능을 묶어 관리합니다. 재사용성, 유지보수성, 확장성 등을 높이는 데 목적이 있습니다.
  • class (클래스): 자바스크립트의 객체 지향에서 class는 객체를 생성하기 위한 '설계도' 또는 '템플릿' 역할을 합니다. 클래스 안에는 속성(property)과 메서드(method)를 정의할 수 있습니다.
    • constructor: 클래스의 객체(인스턴스)가 생성될 때 호출되는 특별한 메서드입니다. 속성들을 초기화하는 역할을 합니다.
    • private: 클래스 내부에서만 접근할 수 있는 속성(예: private speed)을 정의할 때 사용합니다.
    • has A inheritance (포함 관계): GamePanel 클래스에서 private car: SUVCar;와 같이 선언하는 것은 "GamePanel이 SUVCar를 가지고 있다"는 의미의 포함 관계(Composition)를 나타냅니다. 이는 상속(Inheritance)과는 다른 개념으로, 한 클래스가 다른 클래스의 객체를 자신의 속성으로 가지는 것입니다.
    • 실체화(Instantiation) 및 객체 생성: this.car = new SUVCar()와 같이 new 키워드를 사용하여 클래스의 실체(객체, 인스턴스)를 만들어야만, 해당 객체의 속성과 메서드를 사용할 수 있습니다. "실체화하여야 사용이 가능, 객체가 있어야 사용 가능." 이 바로 이 부분을 설명합니다.

제네릭 (Generic)

제네릭선언할 때(함수나 클래스를 정의할 때) 타입을 마치 함수의 파라미터처럼 사용하는 것을 의미합니다. 코드를 작성할 때는 타입을 확정하지 않고, 실제로 사용할 때(호출할 때) 타입을 지정할 수 있게 해주는 기능이에요.

  • 목적: 한 번 작성한 코드를 여러 타입에서 재사용할 수 있도록 하여 코드 중복을 줄이고 유연성을 높입니다.
  • 기본 문법: <T>와 같이 꺾쇠 괄호 안에 타입 파라미터(관례적으로 T, U, K 등을 사용)를 넣어 사용합니다.
  • 예시: function print<T>(value: T): void { ... }
    • print<string>("Hello, World!"); // T는 string으로 지정
    • print<number>(42); // T는 number로 지정
    • getText<string>('hi');
    • getText<number>(10);
    • getText<boolean>(true);
728x90