웹 통신(HTTP)의 가장 큰 특징은 '무상태(Stateless)'입니다. 서버는 요청을 보낸 사용자가 이전에 어떤 요청을 했는지 기억하지 못합니다.

이런 '무상태' 환경에서는 다음과 같은 문제가 발생할 수 있습니다.

  • 로그인: 페이지를 이동할 때마다 다시 로그인해야 합니다.
  • 장바구니: 상품을 담고 다른 페이지로 가면 장바구니에 담은 물품이 사라집니다.

이러한 문제를 해결하기 위해 세션(Session)을 사용합니다.

 

세션(Session)은 웹 사이트와 사용자(브라우저) 간의 지속적인 대화 상태를 유지하는 창구와 같은 역할을 합니다.

 

서버는 각 사용자를 위한 '전용 창구'를 만들어두고, 사이트를 이용하는 동안 특정 사용자를 기억할 수 있게 됩니다. 따라서 서버는 사용자의 로그인 상태, 장바구니 내용 등을 유지할 수 있습니다.

세션의 동작 방식 : 개인 사물함과 열쇠

세션은 보통 세션 ID쿠키를 이용해 동작합니다. 이 과정을 '개인 사물함과 열쇠'에 비유하면 쉽게 이해할 수 있습니다.

  1. 최초 접속 (손님의 첫 방문)
    사용자가 웹사이트에 처음 접속합니다.
  2. 세션 생성 및 세션 ID 발급 (개인 사물함과 열쇠 제공)
    서버는 이 사용자를 위한 고유한 저장 공간(세션)을 서버 메모리나 데이터베이스에 만듭니다. 이것이 바로 '개인 사물함'입니다.
    그리고 서버는 이 '개인 사물함'을 열 수 있는 유일한 '열쇠'인 세션 ID를 생성합니다.
  3. 세션 ID 전달 (열쇠를 사용자에게 전달)
    서버는 생성된 세션 ID를 HTTP 응답 헤더에 담아 사용자 브라우저에게 전달합니다.
  4. 쿠키에 저장 (열쇠를 주머니에 보관)
    사용자 브라우저는 서버로부터 받은 세션 ID를 쿠키에 저장합니다. 이제 사용자는 사이트를 이용하는 동안 이 '열쇠'를 자신의 주머니에 가지고 다니는 셈입니다.
  5. 재접속 및 인증 (열쇠 확인)
    사용자가 같은 웹사이트 내에서 다른 페이지로 이동하거나 다시 요청을 보낼 때, 브라우저는 요청 헤더의 쿠키에 저장된 세션 ID(열쇠)를 자동으로 꺼내어 서버에 보여줍니다.
  6. 상태 유지 (개인 사물함 정보 확인)
    서버는 사용자에게 받은 '열쇠'를 보고, 서버에 있는 수많은 개인 사물함 중에서 그 열쇠에 맞는 사물함을 찾아냅니다.
    사물함과 열쇠가 일치한다면, 그 안에 저장된 정보(로그인 상태, 장바구니 내용 등)를 바탕으로 응답합니다.
  7. 세션 종료 (개인 사물함 비우기)
    사용자가 로그아웃하거나, 브라우저를 닫거나, 서버에서 설정한 일정 시간 동안 아무런 활동이 없으면(세션 만료), 서버는 해당 세션 정보('개인 사물함')를 삭제합니다.

세션과 쿠키의 차이점

구분 쿠키 (Cookie) 세션 (Session)
저장 위치 사용자 브라우저 (클라이언트 측) 웹 서버
저장 내용 간단한 텍스트 데이터 (Key-Value)
세션 ID 같은 열쇠를 저장
객체를 포함한 모든 유형의 데이터<br>로그인 정보, 장바구니 등
중요한 내용물
보안 상대적으로 낮음 (클라이언트에서 수정 가능) 상대적으로 높음 (서버에 저장되어 안전)
생명 주기 설정한 만료 시간까지 유지 (브라우저를 닫아도 유지 가능) 브라우저 종료 시 또는 서버 만료 시 삭제됨
속도/부하 서버에 부담을 주지 않음 사용자가 많아지면 서버에 부하를 줄 수 있음

정리

쿠키는 사용자의 컴퓨터에 남겨진 '열쇠'와 같고, 세션은 그 열쇠를 보고 서버가 관리하는 '개인 사물함'과 같습니다.
중요한 정보는 안전한 사물함(세션)에 보관하고, 그 사물함을 열 수 있는 열쇠(세션 ID)만 사용자(쿠키)에게 맡기는 방식입니다.

이러한 세션 메커니즘을 이용하여 '상태 없는' 웹 환경에서도 편리하게 로그인 상태를 유지합니다.

728x90

'CS' 카테고리의 다른 글

Prisma ORM에 대하여  (0) 2025.08.02
클린 아키텍쳐(Clean Architecture)란?  (0) 2025.07.12
객체 지향이란?  (0) 2025.06.29
데이터 정규화(Normalization)란?  (0) 2025.06.26
동기화와 비동기화  (0) 2025.06.20

Prisma ORM이란?

Prisma는 Node.js와 TypeScript를 위한 ORM(Object-Relational Mapper)입니다.

ORM이란, 프로그래밍 코드의 객체(Object)와 관계형 데이터베이스(Relational DB)의 테이블을 서로 연결(Mapping)해주는 '번역기'와 같은 역할을 하고 있습니다.

복잡한 SQL 쿼리문(SELECT * FROM users WHERE ... 등)으로 작성하는 대신 익숙한 JavaScript/TypeScript 코드(prisma.user.findMany() 등)로 데이터베이스를 조작할 수 있게 해줍니다.


Prisma ORM의 차별점

  1. 타입 안정성 (Type-Safe) : Prisma의 가장 큰 장점이며, 데이터베이스 스키마를 기반으로 완벽한 타입이 적용된 클라이언트를 생성합니다. 코드 작성 시 자동 완성이 지원되고 존재하지 않는 컬럼에 접근하는 등의 실수를 컴파일 단계에서 막아줍니다.
  2. 직관적인 스키마 파일 (schema.prisma) : 데이터베이스의 구조를 하나의 파일에서 명확하고 읽기 쉽게 관리합니다. 이 파일만 보면 DB 전체 구조를 파악할 수 있습니다.
  3. 안전한 데이터베이스 마이그레이션 : 'prisma migrate' 명령어로 데이터베이스 구조 변경 이력을 자동으로 관리하고 안전하게 적용할 수 있습니다.

Prisma는 3가지 핵심 요소로 구성됩니다. 

요소 역할 비유
Prisma Schema 데이터베이스 구조를 정의하는 설계도 건물의 청사진
Prisma Migrate 설계도를 보고 실제 DB를 변경하는 시공사 청사진대로 건물을 짓는 일
Prisma Client 완성된 DB를 코드에서 조작하는 리모컨 완성된 건물 시설을 사용하는 리모컨

Prisma ORM 사용법

간단한 블로그의 UserPost 테이블을 만든다는 가정으로 진행합니다.

설치 및 초기 설정

  1. 필요한 패키지 설치Generated bash
    // Prisma CLI(명령어 도구) 설치
    npm install prisma --save-dev
    
    // Prisma Client(코드에서 사용할 라이브러리) 설치
    npm install @prisma/client

     

  2. Prisma 프로젝트 초기화Generated bash
          npx prisma init
    위의 명령어을 실행하면 prisma 폴더와 그 안에 schema.prisma 파일, .env 파일이 생성됩니다.

  3. .env 파일에 데이터베이스 연결 정보 입력
    .env 파일을 열어 자신의 데이터베이스 주소를 입력합니다. (예: PostgreSQL)Generated env
          DATABASE_URL="postgresql://사용자이름:비밀번호@호스트:포트/데이터베이스이름"

2단계: 데이터 모델링 (schema.prisma 작성)

prisma/schema.prisma 파일이 데이터베이스의 설계도입니다. 여기에 UserPost 모델을 정의합니다.

Generated prisma

// prisma/schema.prisma

// 데이터베이스 종류와 주소를 지정합니다.
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

// Prisma Client를 생성하기 위한 설정입니다.
generator client {
  provider = "prisma-client-js"
}

// User 모델 (users 테이블)
model User {
  id    Int     @id @default(autoincrement()) // 고유 ID (기본 키), 자동 증가
  email String  @unique // 이메일 (중복 불가)
  name  String? // 이름 (선택 사항)
  posts Post[]  // 한 명의 유저는 여러 개의 Post를 가짐 (1:N 관계)
}

// Post 모델 (posts 테이블)
model Post {
  id        Int      @id @default(autoincrement())
  title     String
  published Boolean  @default(false)
  author    User     @relation(fields: [authorId], references: [id]) // User 모델과 관계 설정
  authorId  Int      // 외래 키
}

설계도를 실제 데이터베이스에 적용합니다. 터미널에 다음 명령어를 입력하세요.

      npx prisma migrate dev --name "init"
  • migrate dev: 개발 환경에서 마이그레이션을 실행합니다.
  • --name "init": 이 변경 사항에 "init"이라는 이름을 붙여 히스토리를 관리합니다.

위 명령 성공시, DB에 UserPost 테이블이 생성되고 동시에 최신 스키마에 맞는 Prisma Client가 자동으로 생성(업데이트)됩니다.

4단계: Prisma Client의 데이터 조작 (CRUD)

이제 코드에서 데이터를 자유자재로 다룰 수 있습니다.

  1. Prisma Client 인스턴스 생성
    애플리케이션에서 한 번만 생성하여 재사용하는 것이 좋습니다.
    // lib/prisma.ts
    import { PrismaClient } from '@prisma/client'
    
    export const prisma = new PrismaClient()
  2. CRUD 작업 수행
    • 데이터 생성 (Create)
      const newUser = await prisma.user.create({
        data: {
          email: "test@example.com",
          name: "김강현",
        },
      });
    • 데이터 조회 (Read)
      // 모든 사용자 조회
      const users = await prisma.user.findMany();
      
      // 특정 게시물을 작성자 정보와 함께 조회
      const post = await prisma.post.findUnique({
        where: { id: 1 },
        include: {
          author: true, // author 관계를 포함해서 가져옴
        },
      });
    • 데이터 수정 (Update)
      const updatedPost = await prisma.post.update({
        where: { id: 1 },
        data: {
          published: true,
        },
      });
    • 데이터 삭제 (Delete)
      const deletedUser = await prisma.user.delete({
        where: { email: "test@example.com" },
      });

       


정리

Prisma의 핵심 사용법을 정리했습니다.
위의 단계를 통해서 SQL 쿼리 없이 타입스크립트 코드만으로 안전하고 직관적으로 데이터베이스를 관리할 수 있습니다.

728x90

'CS' 카테고리의 다른 글

세션(Session)이란?  (1) 2025.08.03
클린 아키텍쳐(Clean Architecture)란?  (0) 2025.07.12
객체 지향이란?  (0) 2025.06.29
데이터 정규화(Normalization)란?  (0) 2025.06.26
동기화와 비동기화  (0) 2025.06.20

클린 아키텍쳐에 대하여 깊게 고민하고 생각해보며 공부하였습니다.
이해하기에는 쉽지 않았으나, 공부한 내용을 글로 작성합니다.
글의 내용이 길다고 생각하여 마지막 부분에 쉬운 이해를 위해  내용을 간단하게 정리하였습니다.

 

클린 아키텍쳐란 무엇인가?

소프트웨어 프로젝트를 진행하다 보면 프로젝트의 크기가 커져 코드가 점점 복잡해집니다. 처음에는 깔끔했던 코드가 기능이 추가될수록 서로 얽혀 나중에는 작은 기능 하나를 수정해도 예상치 못한 곳에서 버그가 터져 나올 수 있습니다. 이런 상태를 '소프트웨어가 부패했다' 또는 '아키텍처가 무너졌다'고 표현합니다.

클린 아키텍처는 이러한 문제에 대한 해결책으로 로버트 C. 마틴(Uncle Bob)이 제안한 설계 사상입니다. 아래의 내용은 클린 아키텍쳐의 핵심 철학입니다.

 "좋은 아키텍처는 시스템을 유연하고, 테스트하기 쉽고, 유지보수하기 좋게 만든다. 이를 위해 시스템의 핵심 비즈니스 로직과 외부 기술(세부 사항)을 철저히 분리해야 한다."

여기서 '세부 사항(Details)'이란 프레임워크(Next.js), 데이터베이스(PostgreSQL), UI, 외부 라이브러리 등을 의미합니다. 이것들은 언젠가 바뀔 수 있는 부차적인 요소입니다. 반면, '핵심 비즈니스 로직'은 이 서비스가 존재하는 이유(서비스의 규칙)이며 쉽게 변하지 않습니다.

클린 아키텍처는 이 변하지 않는 핵심을 변하기 쉬운 세부 사항들로부터 보호하는 '방어벽'을 만드는 설계 방법론입니다.


클린 아키텍쳐의 시스템

클린 아키텍처는 시스템을 크게 네 개의 계층으로 나누어 설명합니다. 가장 안쪽부터 바깥쪽으로 이동합니다. 

 

아래는 각 계층의 역할과 특징입니다.

Entities (엔티티)

  • 역할 : 시스템의 가장 핵심적인 비즈니스 규칙을 담는 영역입니다. 이 규칙은 특정 애플리케이션에 종속되지 않습니다.

  • 예시 : 쇼핑몰 시스템의 Product(상품)나 Order(주문) 객체. 이 객체들은 상품의 가격 계산 로직이나 주문의 상태 변경 규칙 같은 고유한 비즈니스 로직을 포함할 수 있습니다.

  • 특징
    엔티티는 변하지 않고 안정적입니다. 외부의 어떤 계층이 바뀌더라도 엔티티는 영향을 받지 않습니다. 예를 들어, 애플리케이션이 웹에서 모바일로 바뀌거나 데이터베이스 종류가 바뀌어도 엔티티는 그대로 유지되어야 합니다.
// 예시 코드

// /src/core/entities/reservation.entity.ts
export class Reservation {
  public readonly rsv_id: string;
  public rsv_user: string;
  public rsv_room: string;
  public rsv_start: Date;
  public rsv_end: Date;

  constructor(props: Omit<Reservation, 'isWithinBusinessHours'>) {
    Object.assign(this, props);
  }

  // 엔티티 스스로가 가질 수 있는 핵심 비즈니스 규칙
  public isWithinBusinessHours(): boolean {
    const startHour = this.rsv_start.getHours();
    const endHour = this.rsv_end.getHours();
    return startHour >= 9 && endHour <= 18;
  }
}

 Use Cases (유즈케이스)

  • 역할 : 애플리케이션에 특화된 비즈니스 규칙을 구현합니다. 이 계층은 엔티티를 사용하여 시스템이 사용자에게 제공하는 특정 기능(유스케이스)을 완성시킵니다.

  • 예시: RegisterUserUseCase는 사용자 등록에 필요한 모든 단계를 조율하지만, 실제 데이터베이스에 사용자 정보를 저장하는 코드는 직접 작성하지 않고, 저장소 인터페이스를 호출할 뿐입니다.

  • 특징
    "사용자를 등록한다", "상품을 장바구니에 담는다"와 같은 구체적인 기능를 코드로 표현합니다.
    이 계층은 데이터가 어떻게, 어디에 저장되는지 전혀 알지 못합니다. 대신 "사용자를 등록해줘" 또는 "상품 데이터를 가져와줘"라는 추상적인 규칙(인터페이스)에만 의존합니다.
// 예시 코드
// /src/core/repositories/reservation.repository.ts (인터페이스 정의)
export interface IReservationRepository {
  save(reservation: Reservation): Promise<void>;
  findById(id: string): Promise<Reservation | null>;
}

// /src/core/use-cases/create-reservation.use-case.ts
import { Reservation } from '../entities/reservation.entity';
import { IReservationRepository } from '../repositories/reservation.repository';

export class CreateReservationUseCase {
  // 실제 구현이 아닌, 인터페이스에 의존함
  constructor(private reservationRepo: IReservationRepository) {}

  async execute(input: { userId: string, roomId: string, start: Date, end: Date }) {
    const newReservation = new Reservation({ ... });

    if (!newReservation.isWithinBusinessHours()) {
      throw new Error("예약은 업무 시간 내에만 가능합니다.");
    }
    // ... 다른 비즈니스 규칙 검사

    await this.reservationRepo.save(newReservation);
  }
}

Interface Adapters (인터페이스 어댑터)

  • 역할 : 안쪽의 유스케이스/엔티티 계층과 바깥쪽의 프레임워크/드라이버 계층 사이에서 데이터를 변환하고 전달하는 '번역가' 역할을 합니다.

  • 예시
    Controller : 웹 요청(HTTP Request)을 받아 유스케이스가 이해할 수 있는 데이터 형식으로 변환한 뒤, 해당 유스케이스를 호출합니다.
    Repository 구현체 : 유스케이스 계층에 정의된 "데이터 저장 규칙(인터페이스)"을 실제 데이터베이스 기술(예: SQL)을 사용하여 구현합니다.

  • 특징
    이 계층의 코드는 안쪽의 핵심 로직과 바깥쪽의 외부 기술 모두를 알고 있습니다.
    Controllers, Presenters, Gateways(Repositories) 등이 여기에 속합니다.
// 예시 코드
// /src/infra/repositories/supabase-reservation.repository.ts
import { IReservationRepository } from '@/core/repositories/reservation.repository';
import { Reservation } from '@/core/entities/reservation.entity';
import { supabase } from '@/infra/db/supabase'; // Supabase 클라이언트

export class SupabaseReservationRepository implements IReservationRepository {
  async save(reservation: Reservation): Promise<void> {
    const { error } = await supabase.from('reservations').insert([
      { ...reservation } // 엔티티를 DB 스키마에 맞게 변환
    ]);
    if (error) throw new Error(error.message);
  }
  //... findById 등 구현
}

Frameworks & Drivers (프레임워크 & 드라이버)

  • 역할 : 시스템의 가장 바깥쪽 경계로, 우리가 사용하는 모든 외부 도구와 기술이 이 계층에 해당합니다.

  • 특징
    웹 프레임워크, 데이터베이스, UI 프레임워크, 외부 라이브러리 등 구체적인 기술들입니다.
    이 계층의 코드는 주로 다른 계층들을 연결하고 초기화하는 '접착제' 역할을 합니다.

  • 예시 : Next.js 프레임워크, PostgreSQL 데이터베이스, React UI 라이브러리, 웹 서버 등.

위와 같은 구조로 가장 중요한 엔티티유스케이스는 가장 불안정한 프레임워크데이터베이스 기술로부터 완벽하게 보호받게 됩니다.

중요한 것 (핵심 비즈니스 로직)
이 서비스가 존재하는 이유 그 자체입니다. 예를 들어, 프로젝트에서는 "회의실을 특정 규칙에 따라 예약한다"는 것이 핵심 로직입니다. 이 로직은 웹사이트로 만들든, 모바일 앱으로 만들든 변하지 않습니다.

중요하지 않은 것 (세부 사항)
 핵심 로직을 구현하기 위해 사용하는 외부 도구들입니다.

  • 웹 프레임워크: Next.js, Express 등
  • 데이터베이스: PostgreSQL, MySQL, Supabase 등
  • UI: React, Angular 등

 


의존성 규칙 (The Dependency Rule)

클린 아키텍쳐를 이해할 때, 가장 중요한 규칙입니다.

"소스 코드의 의존성(참조 관계)은 오직 안쪽을 향해야 한다."


시스템을 여러 개의 구조로 생각했을 때, 안쪽 원은 바깥쪽 원에 대해 아무것도 모릅니다.

  • 안쪽 원 (핵심 로직): 데이터베이스가 무엇인지, 웹 프레임워크가 무엇인지 알 필요가 없습니다.
  • 바깥쪽 원 (세부 사항): 안쪽 원의 규칙을 알고 있으며, 그 규칙에 따라 움직입니다.

이 규칙으로 인해 데이터베이스를 바꾸거나 웹 프레임워크를 교체하는 큰 변화에도 핵심 비즈니스 로직 코드는 단 한 줄도 수정할 필요가 없게 됩니다. 이것이 클린 아키텍처가 추구하는 유연성입니다.


클린 아키텍쳐를 사용하는 이유

  • 유연성 : 데이터베이스나 웹 프레임워크를 바꿔야 할 때, 핵심 비즈니스 로직은 건드리지 않고 해당 부분만 교체하면 됩니다.
  • 테스트 용이성 : 핵심 로직을 외부 기술과 분리하여 독립적으로 쉽게 테스트할 수 있습니다.
  • 유지보수성 : 코드가 역할별로 명확히 분리되어 있어 이해하고 수정하기 쉽습니다.

정리

 

클린 아키텍쳐를 공부하며 많은 시간을 쓰고, 깊은 고민을 했습니다. 이후, 이해하게 된 내용은 상당히 간단하게 요약할 수 있었습니다.

시스템의 중요한 부분은 (핵심 비즈니스 로직)과 중요하지 않은 부분(외부 기술, 세부사항)을 분리하는 것입니다.

시스템은 안쪽으로 갈수록 중요해지며 안쪽은 Entity, Use Case 등이 위치하며 바깥쪽에는 Framework, Data Base 등이 있습니다.

이 계층의 사이에는 내부의 핵심 로직과 외부 세계(웹, DB 등) 사이에서 데이터를 변환하고 전달하는 중간 계층인 Adapter가 존재합니다.

 

Entity는 비즈니스 규칙과 데이터 구조 등이 위치합니다.

Use Case는 애플리케이션 고유의 로직이며 엔티티를 조율하여 실제 기능을 완성합니다.
Adapter는 Controller, Repository 구현체 등이 속합니다.
Frameworks & Drivers는 웹 프레임워크(Next.js), 데이터베이스(PostgreSQL), UI 등 우리가 사용하는 모든 외부 기술입니다. 이들은 '세부사항'이며, 언제든 교체될 수 있습니다.

 

 

 

출처 : https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

728x90

'CS' 카테고리의 다른 글

세션(Session)이란?  (1) 2025.08.03
Prisma ORM에 대하여  (0) 2025.08.02
객체 지향이란?  (0) 2025.06.29
데이터 정규화(Normalization)란?  (0) 2025.06.26
동기화와 비동기화  (0) 2025.06.20

객체 지향 프로그래밍 (Object-Orinted Programming, OOP)

객체 지향 프로그래밍은 단순이 코드를 짜는 것을 넘어, 소프트웨어를 만들고 생각하는 방식입니다.

 

프로그램과 코드가 커지고 복잡해질수록 코드의 길이는 길어집니다. 이러한 코드가 한 덩어리로 구성된다면 문제가 발생했을 경우, 문제점을 찾기 어려우며 기능을 추가하고 수정하는 등 유지, 관리에 어려움이 생기며 가독성 또한 떨어집니다.

 

이러한 문제를 해결하기 위해 '객체 지향'이라는 패러다임이 제시되었으며, 객체 지향의 중요한 개념은 객체 입니다.

객체는 현실 세계의 사물처럼 특징(속성)행동(메서드)을 하나로 묶어놓은 독립적인 단위입니다.

 

예를 들어, 자동차를 객체로 생각할 경우

  • 속성(데이터) : 자동차의 특징들 (색상, 최대 속도, 모델명, 현재 속도, 연료량)
  • 행동(기능/메서드) : 자동차가 할 수 있는 동작들 (예: 출발, 정지, 엑셀, 브레이크)

위와 같이 속성과 행동의 결합이 객체입니다.


객체 지향 프로그래밍의 중요 원칙

캡슐화 (Encapsulation)

객체의 데이터(속성)와 그 데이터를 다루는 기능(메서드)을 하나로 묶고, 외부에서는 객체 내부의 세부 구현을 직접 건드리지 못하도록 보호하는 것 입니다. 알약 캡슐안에는 약 성분이 담겨 있으나, 우리는 겉의 캡슐만 보고 그 안의 성분의 제조방법까지 알 필요가 없는 것과 같습니다.

  • 보안 및 데이터 보호: 중요한 데이터가 외부에서 함부로 변경되는 것을 막습니다.
  • 유지보수 용이: 객체 내부의 구현이 바뀌어도, 외부에서 객체를 사용하는 방식(인터페이스)만 유지된다면 외부 코드를 수정할 필요가 없습니다.
  • 정보 은닉: 객체를 사용하는 사람은 객체가 '무엇을 하는지'만 알면 되고, '어떻게 하는지'는 알 필요 없게 만듭니다.

상속 (Inheritance)

어떤 객체(부모/상위 클래스)가 가진 속성과 행동을 다른 객체(자식/하위 클래스)가 물려받아 재사용할 수 있게 해주는 기능입니다. 자식 객체는 부모의 것을 물려받고, 자신만의 고유한 속성이나 행동을 추가할 수 있습니다.

  • 코드 재사용: 이미 만들어진 코드를 또 만들 필요 없이 물려받아 쓸 수 있어 개발 시간을 줄입니다.
  • 확장성: 기존 코드를 변경하지 않고 새로운 기능을 추가할 수 있게 합니다.
  • 계층 구조: 객체들 간의 관계를 명확한 계층으로 표현할 수 있습니다.

추상화 (Abstraction)

복잡한 시스템에서 핵심적인 특징이나 기능만을 뽑아내어 표현하고, 불필요하거나 복잡한 세부사항은 표현하지 않습니다. 운전자가 자동차를 운전할 때, 엔진 등의 복잡한 내부 원리를 다 알 필요 없이 핸들, 액셀, 브레이크만 조작만으로 자동차를 이용하는 것과 같습니다.

  • 복잡성 감소: 복잡한 부분을 숨겨서 개발자가 더 중요한 부분에 집중할 수 있게 합니다.
  • 사용 편의성: 필요한 정보만 제공하여 시스템을 더 쉽게 이해하고 사용할 수 있게 합니다.
  • 설계 명확성: 시스템의 핵심 기능과 책임을 명확히 정의할 수 있습니다.

다형성 (Polymorphism)

하나의 기능(메서드)다양한 형태(객체의 타입)에 따라 다르게 동작하는 것을 의미합니다. 예를 들어, '짖다'라는 행동이 '강아지' 객체에서는 "멍멍"으로, '고양이' 객체에서는 "야옹"으로, '오리' 객체에서는 "꽥꽥"으로 다르게 구현되는 것과 같습니다. 같은 '짖기'라도 어떤 객체인지에 따라 결과가 달라집니다.

  • 유연성 증가: 같은 이름의 메서드를 통해 다양한 객체를 처리할 수 있어 코드가 유연해집니다.
  • 확장성: 새로운 타입의 객체가 추가되어도 기존 코드를 크게 수정하지 않고 새로운 동작을 추가할 수 있습니다.
  • 코드 가독성: 비슷한 작업을 수행하는 코드를 더 깔끔하게 작성할 수 있습니다.
728x90

'CS' 카테고리의 다른 글

세션(Session)이란?  (1) 2025.08.03
Prisma ORM에 대하여  (0) 2025.08.02
클린 아키텍쳐(Clean Architecture)란?  (0) 2025.07.12
데이터 정규화(Normalization)란?  (0) 2025.06.26
동기화와 비동기화  (0) 2025.06.20

데이터 정규화(Normalization)


데이터 정규화는 데이터베이스의 테이블을 가장 표준화된 방식으로 만드는 과정을 의미합니다. 이 과정의 핵심 목표는 데이터의 결함을 없애고 데이터의 중복을 제거하는 것입니다. 중복이 제거된 테이블 형태를 표준으로 보며 이 표준에 맞추기 위한 과정을 표준화, 정규화라고 합니다.


정규화가 필요한 이유

정규화의 가장 큰 목적은 데이터의 중복을 제거하여 나타날 수 있는 이상 현상을 방지하기 위함입니다. 이상 현상은 데이터를 삽입, 수정, 삭제할 때 예기치 않은 문제가 생기는 것을 말하며, 이상 현상의 내용은 아래와 같습니다.

  • 삽입 이상 (Insertion Anomaly): 불필요한 데이터가 없으면 새로운 데이터를 추가할 수 없는 문제입니다.
  • 갱신 이상 (Update Anomaly): 중복된 데이터 중 일부만 수정되어 데이터의 일관성이 깨지는 문제입니다.
  • 삭제 이상 (Deletion Anomaly): 특정 데이터를 삭제했을 뿐인데, 유지되어야 할 다른 정보까지 함께 사라지는 문제입니다.

정규화의 장점 

  • 데이터 중복 최소화: 중복되는 데이터를 제거하여 저장 공간을 효율적으로 사용합니다.
  • 데이터 무결성 보장: 정규회된 데이터는 중복이 없고 데이터의 정확성과 일관성이 향상됩니다.
  • 이상 현상(Anomaly) 방지: 데이터 정규화를 통하여 데이터 손실이나 불일치 위험을 줄입니다.
  • 구조의 유연성: 데이터베이스 구조를 변경하거나 확장하기 쉬워집니다.

데이터 정규화 과정 (1NF, 2NF, 3NF)

데이터 정규화는 여러 단계로 나뉘어 있으며, 일반적으로 제3정규형(3NF)까지 만족된다면 관계형 데이터베이스 설계로서 충분합니다.

제1정규형 (1NF: First Normal Form) :  테이블의 모든 컬럼은 반드시 '원자값(Atomic Value)'을 가져야 한다.

하나의 속성에는 오직 하나의 값만 저장될 수 있도록 테이블을 분해합니다.

제2정규형 (2NF: Second Normal Form) : 1NF를 만족하고, 모든 컬럼은 '기본 키(Primary Key) 전체'에 완전하게 종속되어야 한다. (부분 함수 종속 제거)

테이블의 주제와 관련 없는 데이터를 별도의 테이블로 분리하는 과정입니다.

제3정규형 (3NF: Third Normal Form) : 2NF를 만족하고, 기본 키가 아닌 모든 컬럼 간에는 서로 종속 관계가 없어야 한다. (이행적 함수 종속 제거)

일반 컬럼이 다른 일반 컬럼에 의해 결정되는 관계를 제거하는 과정입니다.


BCNF (Boyce-Codd Normal Form) : 테이블의 모든 결정자가 후보 키(Candidate Key)여야 한다.

3NF를 보완하는 강화된 정규형이며, 더욱 엄격한 기준을 가집니다.

  • 결정자(Determinant): 어떤 속성(컬럼)의 값을 결정하는 다른 속성. 즉, X → Y 라는 관계에서 X를 결정자라고 합니다. (X를 알면 Y를 알 수 있다)
  • 후보 키(Candidate Key): 테이블의 각 행을 유일하게 식별할 수 있는 속성의 최소 집합입니다. 기본 키(Primary Key)가 될 수 있는 후보들을 의미합니다.

어떤 값을 결정하는 키(결정자)는 그 자체로 기본 키가 될 자격이 있어야 한다는 강한 원칙입니다. 3NF는 이 규칙에 약간의 예외를 두지만 BCNF는 그 예외도 허용하지 않습니다.

 

 대부분의 경우 3NF를 만족하면 BCNF도 만족하므로, 일반적으로 3NF까지의 정규화를 목표로 합니다.

728x90

'CS' 카테고리의 다른 글

세션(Session)이란?  (1) 2025.08.03
Prisma ORM에 대하여  (0) 2025.08.02
클린 아키텍쳐(Clean Architecture)란?  (0) 2025.07.12
객체 지향이란?  (0) 2025.06.29
동기화와 비동기화  (0) 2025.06.20