반응형


Flutter의 createElement 함수란?

Flutter에서 UI는 위젯(Widget)을 기반으로 구성됩니다. 위젯은 화면의 시각적 요소를 정의하지만, 자체적으로 렌더링되거나 상태를 유지하지는 않습니다. 이 역할은 Element라는 객체가 담당합니다. createElement 함수는 위젯이 Element를 생성하는 데 사용되는 중요한 메서드입니다. 이 글에서는 createElement의 역할과 사용 방법을 초보자도 쉽게 이해할 수 있도록 설명하겠습니다.


Element와 Widget의 차이

Flutter에서 WidgetElement는 밀접하게 연결되어 있지만 역할이 다릅니다.

  • Widget: UI의 정적인 설명서(blueprint)로, 화면에 표시할 구조와 스타일을 정의합니다.
  • Element: Widget의 구체적인 구현체로, 렌더링 트리에서 위젯을 관리하고 상태를 유지합니다.

createElement 함수는 Widget에서 Element를 생성하는 데 사용됩니다.


createElement의 역할

Flutter의 모든 위젯은 createElement 메서드를 가지고 있습니다. 이 메서드는 위젯을 기반으로 올바른 타입의 Element를 생성합니다.

  • StatelessWidget: StatelessElement를 생성합니다.
  • StatefulWidget: StatefulElement를 생성합니다.
  • RenderObjectWidget: RenderObjectElement를 생성합니다.

이렇게 생성된 Element는 위젯 트리와 렌더링 트리에서 중요한 역할을 합니다.


createElement 함수의 기본 구조

Flutter에서는 createElement가 위젯 클래스 내에서 오버라이드(Override)될 수 있습니다. 아래는 기본적인 사용 예입니다.

기본 예제:

@override
Element createElement() {
  return MyCustomElement(this);
}

이 코드는 현재 위젯에서 새로운 Element를 생성하며, 이 Element는 UI 트리에서 위젯을 관리하는 역할을 합니다.

 


실제 예제: 커스텀 위젯과 createElement

아래는 createElement를 사용하여 커스텀 위젯과 Element를 정의하는 간단한 예제입니다.

1. 커스텀 위젯 정의

import 'package:flutter/widgets.dart';

// 커스텀 위젯
class MyCustomWidget extends Widget {
  final String message;

  MyCustomWidget(this.message);

  @override
  Element createElement() {
    return MyCustomElement(this);
  }
}

 

2. 커스텀 Element 정의

class MyCustomElement extends Element {
  MyCustomElement(MyCustomWidget widget) : super(widget);

  @override
  void mount(Element? parent, dynamic newSlot) {
    super.mount(parent, newSlot);
    print('Element Mounted: ${(widget as MyCustomWidget).message}');
  }

  @override
  void update(Widget newWidget) {
    super.update(newWidget);
    print('Element Updated: ${(widget as MyCustomWidget).message}');
  }
}

 

3. 사용 예제

void main() {
  final widget = MyCustomWidget('Hello, Flutter!');
  final element = widget.createElement();

  element.mount(null, null); // Element가 트리에 추가됨
}

 


createElement가 중요한 이유

  1. 위젯 트리와 렌더링 트리 연결:
    • createElement는 위젯 트리와 렌더링 트리 간의 연결을 담당합니다. 이를 통해 Flutter는 효율적으로 UI를 업데이트하고 다시 그립니다.
  2. 커스텀 위젯 개발:
    • 특별한 요구 사항이 있을 때, createElement를 오버라이드하여 커스텀 위젯과 Element를 정의할 수 있습니다.
  3. 성능 최적화:
    • Element는 상태를 유지하므로 Flutter는 위젯 트리를 완전히 다시 그리지 않고도 UI를 효율적으로 업데이트할 수 있습니다.

 

createElement와 Flutter 생명주기

createElement는 Flutter 위젯의 생명주기에서 초기 단계에 호출됩니다. 아래는 주요 생명주기 단계를 요약한 것입니다:

  1. Widget 생성: 위젯 트리에서 새 위젯이 생성됩니다.
  2. Element 생성: 위젯의 createElement 메서드가 호출되어 Element가 생성됩니다.
  3. mount: Element가 부모 트리에 연결되고 초기화됩니다.
  4. build: Element가 위젯의 UI를 렌더링합니다.

 

반응형
반응형

Dart의 Constructor(생성자)

생성자(Constructor)는 클래스의 인스턴스를 생성하고 초기화하는 데 사용되는 특별한 메서드입니다. Dart에서 생성자는 클래스와 동일한 이름을 가지며, 객체를 생성할 때 호출됩니다. 생성자는 객체의 초기 상태를 설정하거나, 특정 작업을 수행하면서 객체를 초기화할 때 주로 사용됩니다.


생성자의 주요 특징

  1. 클래스와 동일한 이름을 가집니다.
  2. 객체가 생성될 때 자동으로 호출됩니다.
  3. 반환 타입이 없습니다.
  4. 기본 생성자가 없을 경우, Dart는 자동으로 기본 생성자(매개변수 없는 생성자)를 제공합니다.

생성자의 종류

1. 기본 생성자

Dart에서 생성자는 클래스와 동일한 이름을 가지며, 매개변수를 통해 필드 값을 초기화할 수 있습니다.

예시:

class Person {
  String name;
  int age;

  // 기본 생성자
  Person(String name, int age) {
    this.name = name; // this를 사용하여 클래스 필드를 초기화
    this.age = age;
  }

  void introduce() {
    print('안녕하세요! 저는 $name이고, 나이는 $age입니다.');
  }
}

void main() {
  Person person = Person('홍길동', 25);
  person.introduce();
}

출력:

안녕하세요! 저는 홍길동이고, 나이는 25입니다.

2. 간략화된 생성자 (축약 생성자)

Dart에서는 축약 문법을 사용하여 필드를 간단하게 초기화할 수 있습니다. this 키워드를 사용하여 클래스의 필드를 직접 초기화합니다.

예시:

class Person {
  String name;
  int age;

  // 축약 생성자
  Person(this.name, this.age);

  void introduce() {
    print('안녕하세요! 저는 $name이고, 나이는 $age입니다.');
  }
}

void main() {
  Person person = Person('홍길동', 25);
  person.introduce();
}

출력:

안녕하세요! 저는 홍길동이고, 나이는 25입니다.

3. 이름이 지정된 생성자 (Named Constructor)

여러 생성자를 사용할 경우, 이름을 지정하여 다양한 방식으로 객체를 초기화할 수 있습니다.

예시:

class Person {
  String name;
  int age;

  // 기본 생성자
  Person(this.name, this.age);

  // 이름이 지정된 생성자
  Person.namedConstructor(String name) {
    this.name = name;
    this.age = 0; // 나이는 기본값으로 설정
  }

  void introduce() {
    print('안녕하세요! 저는 $name이고, 나이는 $age입니다.');
  }
}

void main() {
  Person person1 = Person('홍길동', 25);
  person1.introduce();

  Person person2 = Person.namedConstructor('이순신');
  person2.introduce();
}

출력:

안녕하세요! 저는 홍길동이고, 나이는 25입니다.
안녕하세요! 저는 이순신이고, 나이는 0입니다.

4. 초기화 리스트 (Initializer List)

초기화 리스트는 생성자가 본문을 실행하기 전에 필드 값을 초기화하는 데 사용됩니다. 주로 final 필드와 같이 한 번만 초기화 가능한 필드를 설정할 때 유용합니다.

예시:

class Circle {
  final double radius;
  final double area;

  // 초기화 리스트를 사용한 생성자
  Circle(this.radius) : area = 3.14 * radius * radius;

  void showArea() {
    print('반지름: $radius, 면적: $area');
  }
}

void main() {
  Circle circle = Circle(5);
  circle.showArea();
}

출력:

반지름: 5.0, 면적: 78.5

5. 팩토리 생성자 (Factory Constructor)

팩토리 생성자는 새로운 인스턴스를 생성하는 대신 기존의 인스턴스를 반환하거나 특정 조건에 따라 객체를 생성해야 할 때 사용됩니다.

예시:

class Singleton {
  static final Singleton _instance = Singleton._internal();

  // private 생성자
  Singleton._internal();

  // 팩토리 생성자
  factory Singleton() {
    return _instance;
  }
}

void main() {
  var obj1 = Singleton();
  var obj2 = Singleton();

  print(obj1 == obj2); // true (같은 객체를 반환)
}

출력:

true

생성자를 사용할 때 주의할 점

  1. 매개변수 순서와 이름에 주의: 필드 이름과 매개변수 이름이 같을 때는 this를 사용하여 혼동을 피합니다.
  2. final 또는 const 필드 초기화: final 필드는 반드시 생성자를 통해 초기화해야 하며, const 필드는 컴파일 시점에 값이 결정되어야 합니다.
  3. 생성자와 메서드 구분: 생성자는 반환 타입이 없으며, 클래스와 동일한 이름을 가집니다.
반응형
반응형


Flutter에서 위젯(Widget)은 UI 구성 요소의 기본 단위입니다. Flutter는 모든 것을 위젯으로 구성하며, 화면에 표시되는 텍스트, 이미지, 버튼, 레이아웃까지 모두 위젯으로 처리됩니다. Flutter에서 위젯을 잘 이해하는 것은 효과적인 UI 설계와 앱 개발에 중요한 요소입니다. 이 글에서는 Flutter 위젯의 개념과 종류를 쉽게 설명하겠습니다.



Flutter 위젯이란?

위젯(Widget)은 Flutter에서 화면을 구성하는 기본적인 요소입니다. 위젯은 UI를 표현하는 데 필요한 모든 것들을 정의합니다. 예를 들어, 텍스트를 표시하거나 버튼을 만들거나, 레이아웃을 설정하는 것 모두 위젯을 통해 이루어집니다.

위젯의 특성

구성 요소: Flutter 앱에서 모든 것은 위젯입니다. 화면에 보이는 텍스트, 버튼, 이미지, 리스트 등 모든 것이 위젯으로 구현됩니다.

구성 가능성: 위젯은 다른 위젯을 포함할 수 있으며, 이를 통해 복잡한 UI를 구성할 수 있습니다.

불변성: 위젯은 불변(immutable) 객체입니다. 한 번 생성된 위젯은 상태를 변경할 수 없고, 상태 변경은 StatefulWidget을 사용하여 처리합니다.

 


위젯의 종류

Flutter에서 위젯은 크게 StatelessWidgetStatefulWidget으로 나뉩니다.

1. StatelessWidget (상태 없는 위젯)

StatelessWidget상태를 변경하지 않는 위젯입니다. UI가 한 번 설정되면 변경되지 않으며, 생성 시 주어진 데이터만을 사용하여 화면을 구성합니다. 예를 들어, 텍스트를 표시하거나 단순한 아이콘을 화면에 표시할 때 사용됩니다.

import 'package:flutter/material.dart';

class MyTextWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Hello, Flutter!', style: TextStyle(fontSize: 24)),
    );
  }
}

특징:

  • 상태를 갖지 않음: 위젯 자체는 상태를 가지지 않으며, 생성 시 주어진 데이터를 기반으로 화면을 그립니다.
  • 빠르고 효율적: 상태 변경이 없으므로 성능이 뛰어납니다.
  • UI가 변경되지 않는 부분에 사용합니다.

2. StatefulWidget (상태 있는 위젯)

StatefulWidget상태를 변경할 수 있는 위젯입니다. 예를 들어, 버튼 클릭, 텍스트 입력, 슬라이더 조정 등 사용자의 입력에 따라 UI가 변경되는 경우에 사용됩니다. StatefulWidget은 두 부분으로 나뉩니다: 위젯 자체와 상태를 관리하는 State 클래스입니다.

예시:

import 'package:flutter/material.dart';

class CounterWidget extends StatefulWidget {
  @override
  _CounterWidgetState createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('Counter: $_counter', style: TextStyle(fontSize: 24)),
          ElevatedButton(
            onPressed: _incrementCounter,
            child: Text('Increment'),
          ),
        ],
      ),
    );
  }
}

특징:

  • 상태를 유지: StatefulWidget은 상태를 유지하며, UI가 변경될 때마다 setState() 메서드를 호출하여 상태를 업데이트합니다.
  • 상태 관리: 상태를 관리하는 State 클래스를 사용하여 UI 변경을 처리합니다.
  • 사용자 인터랙션: 버튼 클릭, 입력 필드 등 사용자의 입력에 따라 UI가 동적으로 변경되어야 할 때 사용됩니다.

Flutter에서 자주 사용되는 기본 위젯

Flutter에서 제공하는 많은 기본 위젯들은 UI를 빠르게 구성하는 데 유용합니다. 여기에는 레이아웃을 구성하는 위젯, 텍스트를 표시하는 위젯, 상호작용하는 위젯들이 포함됩니다.

1. Text 위젯

텍스트를 화면에 표시하는 위젯입니다.

Text('Hello, Flutter!', style: TextStyle(fontSize: 20))

2. Container 위젯

모든 종류의 UI 요소를 배치하고 스타일을 적용할 수 있는 가장 기본적인 레이아웃 위젯입니다. 크기, 색상, 마진 등을 설정할 수 있습니다.

예시:

Container(
  width: 200,
  height: 100,
  color: Colors.blue,
  child: Center(child: Text('Hello, World!')),
)

3. ColumnRow 위젯

Column은 세로로, Row는 가로로 위젯을 배치하는 레이아웃 위젯입니다.

예시 (Column):

Column(
  children: <Widget>[
    Text('Item 1'),
    Text('Item 2'),
    Text('Item 3'),
  ],
)

4. ElevatedButton 위젯

버튼을 만들 때 사용하는 위젯입니다. 클릭 이벤트를 처리할 수 있습니다.

예시:

ElevatedButton(
  onPressed: () {
    print('Button clicked!');
  },
  child: Text('Click Me'),
)

5. Image 위젯

이미지를 화면에 표시하는 위젯입니다.

예시:

Image.asset('assets/image.png')  // 로컬 이미지

 

 

반응형
반응형


Dart는 Flutter 앱 개발에 사용되는 언어로, 다양한 변수 타입을 제공합니다. 프로그래밍을 배우는 데 있어, 변수 타입을 이해하는 것은 매우 중요합니다. 변수는 데이터를 저장하고 조작하는 기본적인 단위이기 때문입니다. 이번 글에서는 Dart에서 제공하는 주요 내장 변수 타입에 대해 초보자들도 쉽게 이해할 수 있도록 설명하겠습니다.


1. 숫자 타입 (int, double)

Dart에서 숫자는 두 가지 주요 타입으로 나눠집니다: 정수실수입니다.

  • int: 정수형 변수로, 소수점이 없는 숫자를 저장합니다.
  • double: 실수형 변수로, 소수점을 포함하는 숫자를 저장합니다.

예시:

void main() {
  int age = 25;        // 정수형 변수
  double price = 10.99; // 실수형 변수
  
  print(age);   // 출력: 25
  print(price); // 출력: 10.99
}

주요 특징:

  • int는 소수점 없이 정수만 저장할 수 있습니다.
  • double은 소수점이 포함된 숫자, 예를 들어 10.99 같은 값을 저장할 수 있습니다.

2. 문자열 타입 (String)

**String**은 문자나 단어, 문장 등을 저장하는 변수 타입입니다. 즉, 텍스트 데이터를 다룰 때 사용됩니다.

예시:

void main() {
  String greeting = "Hello, Flutter!";
  
  print(greeting); // 출력: Hello, Flutter!
}

주요 특징:

  • 문자열은 큰따옴표(")나 작은따옴표(')로 감쌀 수 있습니다.
  • 여러 줄에 걸친 문자열을 사용할 때는 ''' 또는 **"""**를 사용할 수 있습니다.

3. 불리언 타입 (bool)

**bool**은 참(true) 또는 거짓(false) 값을 저장하는 변수 타입입니다. 주로 조건문(if, else)이나 논리 연산에서 사용됩니다.

예시:

void main() {
  bool isFlutterFun = true;
  bool isCold = false;
  
  print(isFlutterFun); // 출력: true
  print(isCold);       // 출력: false
}

주요 특징:

  • bool 타입은 true 또는 false 두 값만 가질 수 있습니다.
  • 주로 조건문에서 사용되어 프로그램 흐름을 제어합니다.

4. 리스트 타입 (List)

**List**는 여러 개의 값을 순서대로 저장하는 배열 같은 역할을 합니다. 리스트는 다양한 데이터 타입의 값을 하나의 변수에 저장할 수 있는 유용한 타입입니다.

예시:

void main() {
  List<String> fruits = ["Apple", "Banana", "Orange"];
  
  print(fruits); // 출력: [Apple, Banana, Orange]
  print(fruits[0]); // 출력: Apple
}

주요 특징:

  • 리스트는 **대괄호([])**로 묶어서 여러 값을 저장합니다.
  • 인덱스를 사용해 리스트의 특정 항목에 접근할 수 있습니다. 인덱스는 0부터 시작합니다.

5. 맵 타입 (Map)

**Map**은 **키(key)**와 **값(value)**을 쌍으로 저장하는 데이터 타입입니다. 리스트가 순서대로 저장되는 반면, 맵은 키를 통해 값을 검색하는 방식입니다.

예시:

void main() {
  Map<String, String> capitals = {
    'Korea': 'Seoul',
    'Japan': 'Tokyo',
    'USA': 'Washington, D.C.'
  };
  
  print(capitals); // 출력: {Korea: Seoul, Japan: Tokyo, USA: Washington, D.C.}
  print(capitals['Korea']); // 출력: Seoul
}

주요 특징:

  • 맵은 **중괄호({})**로 묶어서 키-값 쌍을 저장합니다.
  • 를 사용해 에 접근할 수 있습니다. 예를 들어, capitals['Korea']는 Seoul을 반환합니다.

6. 동적 타입 (dynamic)

**dynamic**은 어떤 타입이든 저장할 수 있는 타입입니다. 변수의 타입을 고정하지 않고, 실행 중에 변경할 수 있기 때문에 유연하게 사용할 수 있지만, 타입 안전성이 떨어질 수 있어 주의해서 사용해야 합니다.

예시:

void main() {
  dynamic something = 42;  // 정수 저장
  print(something);        // 출력: 42
  
  something = "Flutter";   // 문자열로 변경
  print(something);        // 출력: Flutter
}

주요 특징:

  • dynamic은 타입을 동적으로 결정하기 때문에 변수에 어떤 값이든 저장할 수 있습니다.
  • 타입을 명확히 정의하지 않기 때문에 타입 오류를 쉽게 발견할 수 없습니다. 이를 신중하게 사용해야 합니다.

7. Set 타입

**Set**은 중복되지 않는 값을 저장하는 집합을 나타내는 자료형입니다. 리스트와 유사하지만, 값의 순서는 보장하지 않으며, 중복된 값을 허용하지 않습니다. 주로 유일한 값들을 다뤄야 할 때 유용합니다.

void main() {
  Set<String> fruits = {"Apple", "Banana", "Orange", "Apple"};
  
  print(fruits); // 출력: {Apple, Banana, Orange}
  
  fruits.add("Grapes");  // 새로운 요소 추가
  print(fruits); // 출력: {Apple, Banana, Orange, Grapes}
}

주요 특징:

  • 중복되지 않는 값을 저장합니다. 예를 들어 "Apple"을 두 번 추가해도 한 번만 저장됩니다.
  • 순서가 보장되지 않습니다. 즉, 값이 저장되는 순서와 출력되는 순서는 다를 수 있습니다.
  • Set은 **add()**나 remove() 메서드를 사용하여 값을 추가하거나 삭제할 수 있습니다.
  • 검색 및 포함 여부 체크가 빠른 편입니다.

Set의 사용 예:

  • 고유한 값 목록을 관리해야 할 때 유용합니다.
  • 예를 들어, 사용자가 방문한 페이지 목록, 중복된 이메일을 처리하는 시스템 등에서 활용됩니다.

8. Enum 타입

Enum(열거형)은 여러 개의 관련 상수 값을 그룹화하여 하나의 타입으로 묶을 때 사용됩니다. Enum을 사용하면 값의 집합을 명확하게 정의하고, 코드에서 의미 있는 이름을 사용할 수 있어 가독성과 유지보수성이 높아집니다.

예시:

void main() {
  var status = Status.pending;
  
  switch (status) {
    case Status.pending:
      print("Processing...");
      break;
    case Status.completed:
      print("Completed!");
      break;
    case Status.failed:
      print("Failed!");
      break;
  }
}

enum Status {
  pending,   // 대기 중
  completed, // 완료됨
  failed     // 실패
}
반응형

'Flutter' 카테고리의 다른 글

다트 이해하기 - (4) Constructor(생성자)  (0) 2024.12.01
다트 이해하기 - (3) 위젯이란?  (0) 2024.12.01
다트 이해하기 - (1) 변수  (0) 2024.12.01
플러터 기본위젯  (0) 2024.03.30
typedef와 함수  (0) 2024.03.30
반응형

1. 플러터에서 변수란?

플러터(Flutter)는 Dart 언어를 기반으로 동작하며, Dart에서도 변수는 데이터를 저장하고 관리하기 위한 기본 요소입니다. Dart의 변수는 프로그램 내에서 값들을 저장하고 이를 조작하는 데 사용됩니다. Flutter를 사용한 UI 구성이나 상태 관리에서도 변수는 필수적입니다.


2. 변수 선언과 초기화

Dart에서 변수를 선언하려면 var, final, 또는 const 키워드를 주로 사용합니다. 또한, 변수의 자료형을 명시적으로 선언할 수도 있습니다.

1. var 키워드

  • Dart는 변수에 저장된 값에 따라 자료형을 자동으로 추론합니다.
  • 한 번 값이 할당되면 같은 자료형의 값만 저장 가능합니다.
void main() {
  var name = "가디사는 개발자 주녘"; // Dart가 자료형을 String으로 추론
  print(name); // 출력: 가디사는 개발자 주녘
}

 

2. 자료형 명시

  • 변수의 자료형을 명확히 정의할 수도 있습니다.
void main() {
  String name = "Dart"; // 명시적으로 자료형 선언
  int age = 25;         // 정수 자료형
  double height = 5.9;  // 실수 자료형
  bool isFlutterDev = true; // 불리언 자료형
  print("$name, $age, $height, $isFlutterDev");
}

 

3. final과 const

  • final: 런타임에 값이 결정되며, 이후 변경 불가능.
  • const: 컴파일 타임에 값이 결정되며, 상수로 사용.
void main() {
  final String appName = "MyApp"; // 실행 중 할당된 값은 변경 불가능
  const String framework = "Flutter"; // 컴파일 시점에 값이 고정
  print("$appName uses $framework.");
}

 


3.  변수 사용 시 주의점

  1. 변수의 범위(Scope) 이해하기
    • 변수가 선언된 위치에 따라 접근 가능한 범위가 달라집니다.
    • 예를 들어, 함수 내에서 선언된 변수는 함수 외부에서 접근할 수 없습니다.
  2. 변수 이름은 명확하게
    • 변수 이름은 역할을 명확히 나타내야 가독성이 높아집니다.
    • 예: counter는 "카운트" 용도로 사용되는 변수임을 바로 알 수 있습니다.
  3. 불필요한 변수 선언 피하기
    • 너무 많은 변수를 선언하면 코드가 복잡해질 수 있으니 꼭 필요한 변수만 선언해야합니다.

4. 플러터에서 변수의 중요성

플러터에서 변수는 다음과 같은 다양한 곳에서 사용됩니다:

  1. UI 상태 관리 (Stateful Widget과 State 클래스)
  2. 사용자 입력값 저장
  3. API 호출 결과 데이터 저장
  4. 애니메이션 상태 추적

5. Dart의 Null Safety란?

Null Safety는 Dart 언어의 중요한 기능으로, 개발자가 **null 값으로 인해 발생할 수 있는 오류(null reference errors)**를 방지할 수 있도록 돕는 메커니즘입니다. Null Safety는 Dart 2.12 버전부터 기본적으로 활성화되었으며, 플러터 앱 개발에서도 핵심적인 역할을 합니다.


6. 왜 Null Safety가 필요한가?

null 값은 변수에 아무 값도 저장되지 않은 상태를 나타냅니다. 하지만 null 값에 접근하거나 조작하려 하면 프로그램이 오류를 일으킵니다. 이를 Null Pointer Exception이라고 부르며, 많은 프로그래밍 언어에서 흔히 발생하는 문제입니다.

예를 들어:

String? name; // name은 null일 수 있음
print(name.length); // NullPointerException 발생

Dart의 Null Safety는 null이 될 수 있는 변수와 null이 될 수 없는 변수를 명확히 구분함으로써 이런 문제를 방지합니다.

 


7. Null Safety의 주요 개념

1. null이 될 수 없는 변수

기본적으로 Dart에서 선언된 변수는 null 값을 가질 수 없습니다. 이를 non-nullable 변수라고 합니다.

void main() {
  String name = "Flutter"; // null이 될 수 없음
  print(name); // 정상 출력: Flutter

  name = null; // 컴파일 오류 발생
}

 

2. null이 될 수 있는 변수

변수 뒤에 ?를 붙이면 해당 변수는 nullable이 되어 null 값을 가질 수 있습니다.

void main() {
  String? name; // null이 될 수 있음
  print(name); // 출력: null

  name = "Dart";
  print(name); // 출력: Dart
}

8. Null Safety를 사용하는 방법

1. null 값 확인

null이 될 수 있는 변수에 접근할 때는 반드시 null 여부를 확인해야 합니다.

예: null 체크

void main() {
  String? name;
  if (name != null) {
    print(name.length); // name이 null이 아닐 때만 length 접근
  }
}

 

예: null 병합 연산자 ??

?? 연산자는 null일 경우 대체 값을 반환합니다.

void main() {
  String? name;
  print(name ?? "No Name"); // 출력: No Name
}

2. null 값 사용 강제

! 연산자를 사용하면 null 값을 사용할 수 있다고 Dart에 강제로 알릴 수 있습니다. 이는 개발자가 null이 아님을 확신할 때만 사용해야 합니다.

⚠️ 잘못 사용하면 런타임 오류를 발생시킬 수 있으니 주의가 필요합니다.
void main() {
  String? name;
  name = "Flutter";
  print(name!.length); // name이 null이 아님을 보장
}

3. late 키워드

late 키워드는 변수를 나중에 초기화하겠다는 것을 Dart에 명시적으로 알립니다. null이 아닌 값을 보장해야 할 때 유용합니다.

void main() {
  late String name; // 초기값 없이 선언
  name = "Dart"; // 나중에 초기화
  print(name); // 출력: Dart
}

 


4. nullable 리스트

리스트에도 null safety가 적용됩니다. 예를 들어:

  • List<String>: null 값을 포함하지 않는 문자열 리스트
  • List<String?>: null 값을 포함할 수 있는 문자열 리스트
void main() {
  List<String> names = ["Alice", "Bob"];
  List<String?> nullableNames = ["Alice", null, "Bob"];

  print(names); // 출력: [Alice, Bob]
  print(nullableNames); // 출력: [Alice, null, Bob]
}

Null Safety가 Flutter에서 중요한 이유

플러터 앱 개발에서는 상태 관리, 사용자 입력 처리, 비동기 작업 등에서 null이 자주 발생할 수 있습니다. Null Safety는 다음과 같은 문제를 예방합니다:

  1. Widget 초기화 오류 방지
    위젯이나 상태(State)를 초기화할 때 null 값이 의도치 않게 사용되는 경우를 방지합니다.
  2. 비동기 작업에서 null 값 처리
    API 호출이나 데이터베이스에서 데이터를 가져올 때 null 값이 반환될 가능성을 처리할 수 있습니다.
  3. 안정성과 유지보수성 향상
    null로 인해 발생하는 오류를 컴파일 시점에서 잡아주므로 앱의 안정성이 향상됩니다.

 

요약: Null Safety의 장점

  • 컴파일 시점에서 null 관련 오류 탐지
    앱 실행 전에 null로 인해 발생할 수 있는 문제를 예방합니다.
  • 코드 안정성과 신뢰성 향상
    명확한 nullable 및 non-nullable 구분으로 오류를 줄입니다.
  • 가독성과 유지보수성 향상
    변수의 null 가능성을 코드에서 쉽게 확인할 수 있습니다.
반응형

'Flutter' 카테고리의 다른 글

다트 이해하기 - (3) 위젯이란?  (0) 2024.12.01
다트 이해하기 - (2) 내장 변수타입  (0) 2024.12.01
플러터 기본위젯  (0) 2024.03.30
typedef와 함수  (0) 2024.03.30
dart 이론  (1) 2024.03.30
반응형
💻 프로젝트 미리보기

 

 

서울로 이사하고 회사에 입사한 지 4개월이 지나서 OJT를 하면서 업무를 배우고 시간을 보내다가 여유가 생겼다. 주말에 사이드 프로젝트를 만들어보자고 마음먹고, 웹소켓을 이용한 채팅 프로그램을 개발했다.

스프링 부트를 취업 전에 사용하여 여러 프로젝트를 진행했었는데, 회사에 입사한 이후로는 잘 사용하지 않아서 잊어버린 부분이 많았다.

우선 회사를 다니면서 혼자서 사이드 프로젝트를 진행하는 일이 보통 힘든일이 아니였다...
회사에서도 프로젝트를 진행하는데 퇴근하고 집에 오면 바로 침대행이기 때문.....

 

실시간 채팅 애플리케이션
 
 
우선, 프로젝트 구성은 대충 이런식으로 구성하였다.
프로젝트 루트
│
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           └── chatapp
│   │   │               ├── config
│   │   │               │   └── WebSocketConfig.java
│   │   │               │   └── WebConfig.java
│   │   │               ├── controller
│   │   │               │   └── ChatController.java
│   │   │               └── service
│   │   │                   └── UserService.java
│   │   └── resources
│   │       └── application.properties
│   │
│   └── webapp
│       └── WEB-INF
│           └── jsp
│               └── chat.jsp
│               └── username.jsp

먼저 사용자가 닉네임을 입력하는 부분인 username.jsp를 만들고 채팅방을 입장하게 되면 chat.jsp가 실행된다.

 

WebSocket은 취업 준비를 하면서 팀 프로젝트에서 사용해본 경험이 있었지만, 그때는 웹소켓에 대한 이해가 부족한 상태에서 사용한 느낌이었다. 이번에는 웹소켓에 대해 깊이 공부하고 구현해보았다.

 


기술 스택

  • 백엔드: Spring Boot, WebSocket
  • 프론트엔드: JSP, JavaScript, CSS
 

주요 기능

  • 실시간 채팅: 사용자는 메시지를 실시간으로 주고받을 수 있다.
  • 사용자 목록: 현재 접속 중인 사용자 목록을 표시한다.
  • 이모지 선택기: 사용자가 메시지 입력 시 이모지를 쉽게 선택할 수 있는 기능을 제공한다. 이모지는 카테고리로 구분되어 있어 사용자가 원하는 이모지를 쉽게 찾을 수 있다.
  • 사용자 입장/퇴장 알림: 사용자가 채팅방에 입장하거나 퇴장할 때 시스템 메시지를 통해 알림을 제공한다.
 

주요 파일 및 구성

  • ChatController.java: 사용자 목록 관리 및 메시지 전송 로직을 처리한다.
  • chat.jsp: 사용자 인터페이스를 구성하며, 이모지 선택기와 사용자 목록을 포함한다.

UI/UX 개선

 

이모지 선택기의 디자인을 개선하여 사용자 경험을 향상시켰다. 이모지를 카테고리별로 구분하고, 마우스 오버 시 확대되는 효과를 추가하여 시각적으로 더 매력적으로 만들었다.

 

의존성 설정

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.3.4'
    id 'io.spring.dependency-management' version '1.1.6'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-websocket'
    implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-web'

    // JSP Support Dependencies
    implementation group: 'org.glassfish.web', name: 'jakarta.servlet.jsp.jstl', version: '2.0.0'
    implementation 'jakarta.servlet.jsp:jakarta.servlet.jsp-api:3.0.0'
    implementation 'jakarta.servlet:jakarta.servlet-api:6.0.0'
    implementation 'org.apache.tomcat.embed:tomcat-embed-jasper'
    implementation 'org.apache.taglibs.taglib-standard-impl:1.2.5'
    implementation 'org.apache.taglibs.taglib-standard-spec:1.2.5'

    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    runtimeOnly 'mysql:mysql-connector-java:8.0.33'  // MySQL Connector
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
    useJUnitPlatform()
}

 

WebConfig.java 파일만들기

/**
 * WebConfig 클래스는 Spring MVC의 CORS(Cross-Origin Resource Sharing) 설정을 구성합니다.
 * CORS는 다른 출처의 웹 페이지가 현재 출처의 리소스에 접근할 수 있도록 허용하는 메커니즘입니다.
 * 이 설정을 통해 특정 출처에서 오는 요청을 허용하고, 허용할 HTTP 메서드 및 자격 증명 사용 여부를 지정합니다.
 */
package com.example.chatproject.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // CORS 설정 추가
        registry.addMapping("/chat/**") // "/chat/**" 경로에 대한 CORS 설정
                .allowedOrigins("http://localhost:8080", "http://localhost:3000") // 허용할 출처
                .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // 허용할 HTTP 메서드
                .allowCredentials(true); // 자격 증명(쿠키, 인증 헤더 등) 허용
    }
}

 

 

WebSocketConfig.java 파일만들기

/**
 * WebSocketConfig 클래스는 Spring WebSocket 메시지 브로커를 설정하는 클래스이다.
 * 이 클래스에서는 STOMP 프로토콜을 사용하여 웹소켓 엔드포인트를 등록하고,
 * 메시지 브로커를 구성하여 클라이언트와 서버 간의 실시간 메시지 전송을 가능하게 한다.
 */
package com.example.chatproject.config;

import com.example.chatproject.listener.CustomHttpSessionInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;


@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // STOMP 엔드포인트 등록
        registry.addEndpoint("/ws") // 웹소켓 엔드포인트를 "/ws"로 설정
                .setAllowedOriginPatterns("http://localhost:8080") // 허용할 출처를 설정
                .withSockJS() // SockJS를 사용하여 브라우저 호환성 제공
                .setInterceptors(new CustomHttpSessionInterceptor()); // 커스텀 HTTP 세션 인터셉터 사용
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // 메시지 브로커 설정
        config.enableSimpleBroker("/topic"); // 메시지 브로커가 "/topic" 경로를 구독하도록 설정
        config.setApplicationDestinationPrefixes("/app"); // 애플리케이션 목적지의 접두사를 "/app"으로 설정
    }
}

 

이 파일들은 각각 CORS 설정과 WebSocket 메시지 브로커 설정을 담당한다.

이 두 설정 파일은 Spring Boot 기반의 웹 애플리케이션에서 중요한 역할을 한다. 

WebConfig.java는 CORS 설정을 통해 외부 출처의 요청을 허용하고, WebSocketConfig.java는 실시간 메시지 전송을 위한 웹소켓 설정을 담당한다. 이러한 설정을 통해 사용자에게 더 나은 경험을 제공할 수 있다.

 

 

 

반응형
반응형

SQL문의 실행순서를 요약하면 아래와 같습니다.

  • 개발자가 작성한 SQL문(DDL, DML, DCL 등)은 3단계를 걸쳐서 실행된다. SQL문의 문법을 검사하고 구문 분석을 한다.
  • 구문 분석 이후에 SQL을 실행한다. SQL이 실행되면 데이터를 인출하게 된다.

▶ SQL 실행 순서

SQL 실행 순서 설명
파싱(Parsing) - SQL 문의 문법을 확인하고 구문 분석한다.
- 구문 분석한 SQL문은 Library Cache에 저장된다.
실행(Execution) 옵티마이저(Optimizer)가 수립한 실행 계획에 따라 SQL을 실행한다.
인출(Fetch) 데이터를 읽어서 전송한다.

 

  1. 파싱(Parsing)
    • SQL 문이 데이터베이스로 들어오면, 파싱 단계에서 문법이 올바른지 먼저 확인합니다. 이 과정에서 데이터베이스는 SQL 문을 구문 분석(파싱)해서 명령어가 무엇을 의미하는지 이해하고, 최종적으로 문법 오류가 있는지 체크합니다. 만약 문법적으로 문제가 없다면, 그 SQL 문을 Library Cache라는 메모리 공간에 저장해두죠. 이 작업은 이후 동일한 SQL 문이 또 실행될 때, 이미 분석된 SQL 문을 재사용해서 속도를 빠르게 하기 위해서예요.
  2. 실행(Execution)
    • 파싱이 끝나고 나면, 실행 단계로 넘어가요. 이 단계에서 데이터베이스는 **옵티마이저(Optimizer)**라는 내부 알고리즘을 사용해, SQL을 어떻게 효율적으로 실행할지 '실행 계획'을 세워요. 옵티마이저는 여러 가지 방법 중에서 가장 빠르고 적합한 방법을 선택해 실행하게 돼요. 예를 들어, 특정 테이블에서 데이터를 조회할 때, 인덱스를 사용할지, 전체 테이블을 스캔할지를 결정하는 게 바로 이 과정이에요.
  3. 인출(Fetch)
    • SQL 문이 실행되면, 그 결과를 가져오는 인출 단계가 진행돼요. 데이터를 데이터베이스에서 읽어온 후, 요청한 사용자에게 전송해주는 단계예요. 예를 들어, "나이가 18세 이상인 사람들의 이름을 조회"하라는 명령어를 실행했다면, 그 결과를 가져와서 화면에 보여주는 게 이 단계죠.

요약하자면, 파싱은 SQL 문을 분석하고 준비하는 단계, 실행은 실제로 SQL을 처리하는 단계, 인출은 실행 결과를 가져오는 단계예요. 이 세 단계를 통해 데이터베이스가 우리가 요청한 데이터를 안전하고 빠르게 처리해주는 것입니다.

반응형

'SQL > SQL_이론' 카테고리의 다른 글

SQL에서 자주보이는 오류들  (1) 2025.05.25
트랜잭션(Transaction)  (0) 2024.09.19
SQL의 종류  (1) 2024.09.19
관계형 데이터베이스와 테이블  (0) 2024.09.19
SELECT 문  (0) 2024.06.25
반응형

 

트랜잭션은 데이터베이스의 작업을 처리하는 단위이다.

▶ 트랜잭션의 특성

트랜잭션 특성 설명
원자성(Atomicity) - 트랜잭션은 데이터베이스 연산의 전부가 실행되거나 전혀 실행되지 않아야 한다 (ALL OR NOTHING)
- 즉, 트랜잭션의 처리가 완전히 끝나지 않았을 경우는 실행되지 않은 상태와 같아야 한다.
일관성(Consistency) - 트랜잭션 실행결과로 데이터베이스의 상태가 모순되지 않아야 한다.
- 트랜잭션 실행 후에도 일관성이 유지되어야 한다.
고립성(Isolation) - 트랜잭션 실행 중에 생성하는 연산의 중간결과는 다른 트랜잭션이 접근할 수 없다.
- 즉, 부분적인 실행 결과를 다른 트랜잭션이 볼 수 없다.
영속성(Durability) 트랜잭션이 그 실행을 성공적으로 완료하면 그 결관느 영구적 보장이 되어야 한다.

 

좀 더 쉽게 설명하면 다음과 같다.

 

  1. 원자성(Atomicity)
    • 내가 책을 한 권 샀다고 상상해보자. 책을 사는 과정에는 "돈을 내기"와 "책을 받기"라는 두 가지 행동이 있다. 이 두 가지는 한꺼번에 이루어져야 한다. 만약 책을 샀는데 돈만 내고 책을 못 받으면 안 될 것이다. 반대로 책만 받고 돈을 안 냈다면 그것도 문제가 된다. 그래서 원자성이란, 둘 다 동시에 성공해야 하고, 하나라도 실패하면 둘 다 취소돼서 처음 상태로 돌아가야 한다는 것이다.
  2. 일관성(Consistency)
    • 엄마가 장난감 가게에서 장난감을 사려고 할 때, 엄마는 돈을 줄 테니까 장난감 가게는 장난감을 준다. 그런데 만약 가게에서 장난감이 없으면 엄마가 돈을 줘도 장난감을 못 받게된다. 일관성은 이런 상황을 막는 것이다. 돈을 줬으면 반드시 장난감을 받아야 하고, 반대로 장난감이 없으면 돈을 내는 일이 생기지 않도록 해야 한다.
  3. 고립성(Isolation)
    • 친구가 나에게 초콜릿을 하나 주는 중이라고 상상해보자. 그 순간에 다른 친구가 와서 "초콜릿 너 다 먹었어?"라고 물으면, 너는 아직 초콜릿을 받고 있는 중이라 뭐라고 대답해야 할지 헷갈릴 것이다. 고립성이란, 너가 초콜릿을 다 받을 때까지 다른 친구가 그 일에 끼어들지 못하게 막는 것이다. 너가 초콜릿을 다 받으면 그제야 "응, 다 먹었어!"라고 말할 수 있는 것이다.
  4. 영속성(Durability)
    • 내가 그림을 그렸을 때, 그 그림이 물에 젖어서 없어지면 속상할 것이다. 영속성은 한 번 성공적으로 그린 그림이 절대로 없어지지 않도록 보관해주는 것이다. 데이터베이스도 마찬가지로, 트랜잭션이 성공적으로 끝나면 그 결과가 절대로 사라지지 않도록 안전하게 보관하는 것이다.

이렇게 트랜잭션은 중요한 일을 할 때, 확실하게 처리하고 중간에 문제가 생기지 않도록 여러 규칙들을 지키는 것이다.

반응형

'SQL > SQL_이론' 카테고리의 다른 글

SQL에서 자주보이는 오류들  (1) 2025.05.25
SQL문의 실행순서  (0) 2024.09.19
SQL의 종류  (1) 2024.09.19
관계형 데이터베이스와 테이블  (0) 2024.09.19
SELECT 문  (0) 2024.06.25
반응형
SQL은 컴퓨터에서 데이터를 다루는 특별한 언어입니다. 마치 우리가 국어나 영어를 사용해 이야기를 나누는 것처럼, SQL은 컴퓨터와 데이터를 주고받는 방법입니다. 데이터를 쉽게 정리하고, 저장하고, 바꾸는 일을 할 수 있도록 도와주는 중요한 도구라고 할 수 있습니다.

 

SQL이 하는 일

SQL은 데이터베이스라는 곳에서 일을 합니다. 데이터베이스는 정보를 모아둔 큰 상자 같은 곳이라고 생각하면 됩니다. 예를 들어, 학교에서 학생들의 이름, 나이, 성적을 기록해두는 곳이 데이터베이스 입니다. SQL을 사용하면 이 상자 속에서 정보를 쉽게 찾고, 더하고, 바꾸고, 없앨 수 있습니다.

 

SQL의 종류

SQL에는 크게 네 가지 종류가 있습니다. 각 종류마다 하는 일이 조금씩 다릅니다.

  1. DDL (데이터 정의 언어)
    이건 데이터를 넣을 그릇, 즉 테이블을 만드는 일을 합니다.
    예를 들어, 학교에서 학생 정보를 저장할 테이블을 만들려면, DDL을 사용합니다.
    • CREATE: 테이블을 새로 만듭니다.
    • ALTER: 테이블에 더 넣을 공간이 필요하면 수정합니다.
    • DROP: 더 이상 필요 없는 테이블을 삭제합니다.
    예시:이 코드는 "학생"이라는 테이블을 만들고, 그 테이블에 이름, 나이, 성적을 기록할 수 있도록 해줍니다.
CREATE TABLE 학생 (이름 VARCHAR(20), 나이 INT, 성적 INT);
  1. DML (데이터 조작 언어)
    이건 테이블 안의 데이터를 직접 다루는 언어입니다.
    • INSERT: 새 데이터를 테이블에 넣습니다.
    • UPDATE: 이미 있는 데이터를 수정합니다.
    • DELETE: 데이터를 삭제합니다.
    • SELECT: 테이블에서 데이터를 찾아서 보여줍니다.
    예시:이 코드는 "홍길동"이라는 학생 정보를 테이블에 넣습니다.
INSERT INTO 학생 (이름, 나이, 성적) VALUES ('홍길동', 12, 90);
  1. DCL (데이터 제어 언어)
    이건 데이터를 누가 사용할 수 있는지 권한을 주는 역할을 합니다.
    • GRANT: 다른 사람이 데이터를 사용할 수 있도록 허락합니다.
    • REVOKE: 데이터를 사용할 수 없도록 권한을 회수합니다.
  2. TCL (트랜잭션 제어 언어)
    여러 개의 일을 한 번에 묶어서 실행하고, 실수했을 때 다시 원래 상태로 되돌리는 것을 도와줍니다.
    • COMMIT: 여러 작업을 다 끝내고 저장합니다.
    • ROLLBACK: 실수하면 다시 이전 상태로 복원합니다.
    예시:이 코드를 사용하면 실수한 일을 모두 취소하고 처음 상태로 되돌려줍니다.
ROLLBACK;

 

이렇게 SQL은 데이터를 다루는 여러 가지 방법을 제공해서, 마치 우리가 장난감을 정리하듯이 데이터를 정리하고 다룰 수 있습니다.

반응형

'SQL > SQL_이론' 카테고리의 다른 글

SQL문의 실행순서  (0) 2024.09.19
트랜잭션(Transaction)  (0) 2024.09.19
관계형 데이터베이스와 테이블  (0) 2024.09.19
SELECT 문  (0) 2024.06.25
WHERE 절  (0) 2024.06.25
반응형

1. 관계형 데이터베이스

(1) 데이터베이스와 데이터베이스 관리 시스템의 차이점

  • 데이터베이스는 데이터를 어떠한 형태의 자료구조로 사용하느냐에 따라서 나누어진다.
  • 데이터베이스의 종류는 계층형, 네트워크형 데이터베이스, 관계형 데이터베이스 등이 있다.
  • 계층형 데이터베이스는 트리 형태의 자료구조에 데이터를 저장하고 관리하며, 네트워크는 오너와 멤버 형태로 데이터를 저장한다.
  • 계층형 데이터베이스는 1대 N 관계를 표현한다.
  • 네트워크 데이터베이스는 1대N과 함께 M대 N 표현도 가능하다.
  • 관계형 데이터베이스는 릴레이션에 데이터를 저장하고 관리한다.
  • 관계형 데이터베이스는 릴레이션을 사용해서 집합 연산과 관계 연산을 할 수 있다.
  • 데이터베이스 관리 시스템은 계층형 데이터베이스, 네트워크 데이터베이스, 관계형 데이터베이스 등을 관리하기 위한 소프트웨어를 의미하며, 일명 DBMS라고 한다.
  • DBMS의 종류에는 Oracle, MS-SQL, MySQL, Sybase 등이 있으며 모두 관계형 데이터베이스를 지원한다.

(2) 관계형 데이터베이스 집합 연산과 관계 연산

  • 관계형 데이터베이스의 특징은 릴레이션을 사용해서 집합 연산과 관계 연산을 할 수 있다.

▶ 집합 연산

집합 연산 설명
합집합(Union) - 두 개의 릴레이션을 하나로 합하는 것이다.
- 중복된 행(튜플)은 한 번만 조회된다.
차집합(Difference) 본래 릴레이션에는 존재하고 다른 릴레이션에는 존재하지 않는 것을 조회한다.
교집합(Intersection) 두 개의 릴레이션 간에 공통된 것을 조회한다.
곱집합(Cartesian product) 각 릴레이션에 존재하는 모든 데이터를 조합하여 연산한다.

 

▶ 관계 연산

관계 연산 설명
선택 연산(Selection) 릴레이션에서 조건에 맞는 행(튜플)만을 조회한다.
투영 연산(Projection) 릴레이션에서 조건에 맞는 속성만을 조회한다.
결합 연산(Join) 여러 릴레이션의 공통된 속성을 사용해서 새로운 릴레이션을 만들어 낸다.
나누기 연산(Division) 기준 릴레이션에서 나누는 릴레이션이 가지고 있는 속성과 동일한 값을 가지는 행(튜플)을 추출하고 나누는 릴레이션의 속성을 삭제한 후 중복된 행을 제거하는 연산이다.

 

2. 테이블의 구조

  • 관계형 데이터베이스는 릴레이션에 데이터를 저장하고 릴레이션을 사용해서 집합 연산 및 관계 연산을 지원하여 다양한 형태로 데이터를 조회할 수 있다.
  • 릴레이션은 최종적으로 데이터베이스 관리 시스템에서 테이블로 만들어진다.
  • 기본키(Primary Key)는 하나의 테이블에서 유일성(Unique)과 최소성, Not Null을 만족하면서 해당 테이블을 대표하는 것이다. EMP 테이블에서는 사원번호가 기본키가 된다.
  • 테이블은 행과 칼럼으로 구성된다. 그중에서 행(ROW)은 하나의 테이블에 저장되는 값으로 튜플(Tuple)이라고도 한다.
  • 칼럼(Column)은 어떤 데이터를 저장하기 위한 필드(Field)로 속성(Attribute)이라고도 한다.
  • 외래키(Foreign Key)는 다른 테이블의 기본키를 참조(조인)하는 칼럼이다. 예를 들어 EMP 테이블의 부서코드는 DEPT 테이블의 기본키인 부서코드를 참조한다.
  • 외래키는 관계 연산 중에서 결합 연산(Join)을 하기 위해서 사용한다.

 

[정리]

**데이터베이스 개요**

- 데이터베이스는 계층형, 네트워크형, 관계형 등 다양한 종류가 있으며, 각각 다른 자료구조를 사용한다
- 관계형 데이터베이스는 릴레이션을 사용하여 데이터를 저장하고 관리한다
- DBMS(데이터베이스 관리 시스템)는 이러한 데이터베이스를 관리하기 위한 소프트웨어이다

**관계형 데이터베이스 연산**

- 관계형 데이터베이스는 집합 연산(합집합, 차집합, 교집합, 곱집합)과 관계 연산(선택, 투영, 결합, 나누기)을 지원한다
- 이러한 연산들을 통해 다양한 형태로 데이터를 조회할 수 있다

**테이블 구조**

- 테이블은 행(튜플)과 열(속성)로 구성되며, 기본키는 유일성과 최소성, Not Null을 만족하는 대표 속성이다
- 외래키는 다른 테이블의 기본키를 참조하는 칼럼으로, 주로 결합 연산에 사용된다

반응형

'SQL > SQL_이론' 카테고리의 다른 글

트랜잭션(Transaction)  (0) 2024.09.19
SQL의 종류  (1) 2024.09.19
SELECT 문  (0) 2024.06.25
WHERE 절  (0) 2024.06.25
프로시저  (0) 2023.09.15
반응형
JSP 주석은 JSP 페이지 내에서 주석을 작성할 때 사용됩니다. 주석은 JSP 페이지를 해석할 때 무시되며, 최종 HTML 페이지에 포함되지 않습니다. JSP에는 HTML 주석, JSP 주석, 그리고 Java 주석이 있습니다.

 

HTML 주석

HTML 주석은 최종 HTML 페이지에 포함되며, 브라우저에서 볼 수 있습니다.

 

<!-- 이것은 HTML 주석입니다. 최종 HTML 페이지에 포함됩니다. -->

 

JSP 주석

JSP 주석은 JSP 페이지를 해석할 때 무시되며, 최종 HTML 페이지에 포함되지 않습니다.
<%-- 이것은 JSP 주석입니다. 최종 HTML 페이지에 포함되지 않습니다. --%>

 

Java 주석

Java 주석은 스크립트릿, 선언, 표현식 등 Java 코드 내부에서 사용됩니다.
<% 
    // 이것은 한 줄짜리 Java 주석입니다.
    /* 이것은 여러 줄짜리 
       Java 주석입니다. */
%>

 

JSP 지시자

페이지 지시자는 JSP 페이지의 전체 설정을 지정합니다. 예를 들어, 페이지의 인코딩, import 문, 에러 페이지 등을 설정할 수 있습니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.*" %>
<%@ page errorPage="error.jsp" %>

 

include 지시자

include 지시자는 다른 JSP 파일을 현재 JSP 파일에 포함시킵니다. 이는 정적 포함 방식으로, 컴파일 시 포함됩니다.
<%@ include file="header.jsp" %>

 

코드 실습 1 - 주석을 사용해 보자
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <title>JSP 주석 예제</title>
</head>
<body>
    <!-- HTML 주석: 이것은 최종 HTML 페이지에 포함됩니다. -->
    <%-- JSP 주석: 이것은 최종 HTML 페이지에 포함되지 않습니다. --%>
    <%
        // Java 주석: 한 줄짜리 주석
        /* Java 주석: 
           여러 줄짜리 주석 */
    %>
    <h1>JSP 주석 예제</h1>
</body>
</html>

 

코드 실습 2 - JSP 지시자와 include 의 사용

header.jsp

header.jsp 파일에는 페이지의 헤더 부분을 포함합니다. 이 파일에는 <html>, <head>, <body> 태그를 열고, 공통으로 사용되는 스타일시트나 스크립트를 포함할 수 있습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>공통 헤서 만들어보기</title>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
	<header>
		<h1>사이트 이름</h1>
		<nav>
			<ul>
				<li><a href="home.jsp">홈</a></li>
				<li><a href="about.jsp">소개</a></li>
				<li><a href="contact.jsp">연락처</a></li>
			</ul>
		</nav>
	</header>

home.jsp

home.jsp 파일에서는 header.jsp와 footer.jsp 파일을 포함하여 페이지의 본문 내용을 작성합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file="header.jsp" %>
<%@ page import="java.util.Date" %>

<h1>JSP 지시자 예제</h1>
<p> 현재 시간 <%= new Date() %> </p>

<%@ include file="footer.jsp" %>

 

footer.jsp

footer.jsp 파일에는 페이지의 푸터 부분을 포함합니다. 이 파일에서는 열린 <body>와 <html> 태그를 닫습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

		<footer>
			<p>공통 푸터 &copy; 2024</p>
		</footer>    

	</body>
</html>
반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] JSP 기초 문법  (0) 2024.07.03
[JSP] JSP 라이프사이클  (0) 2024.07.03
[JSP] Java Server Pages 란?  (0) 2024.07.03
스레드(Thread)  (0) 2023.10.04
중첩 클래스  (0) 2023.10.02
반응형

JSP는 기본적으로 HTML 문서 안에 자바 언어를 삽입해 사용할 수 있도록 설계 되어 있습니다.

그래서 실제로 대부분의 변수 선언, 메서드 선언, 로직 등은 자바 언어로 작성할 수 있습니다.

하지만 HTML 사이에 자바 코드를 끼워 넣을 때 필요한 문법이 몇 가지 있습니다.

💡 JSP 기초 문법의 종류
- JSP 지시어, Directive
- 스크립트릿(Scriptlet)
- 선언부(Declaration)
- 표현부(Expession)
- JSP 액션 태그

 

JSP 지시어, Directive
<%@ xxxx…. %>
JSP 디렉티브는 JSP 페이지의 전반적인 속성을 설정합니다. 주로 페이지 속성, import 등을 지정합니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" %>
<%@ page import="java.lang.Math" %>

 

스크립트릿(Scriptlet)
Java 코드를 HTML 중간에 삽입할 때 사용한다.
<% ... %> 태그 사이에 Java 코드를 작성한다 (코드 실행 영역에 해당)

 

<% 
    String greeting = "Hello, JSP!";
    out.println(greeting);
%>

 

선언부(Declaration)
JSP 페이지에서 변수를 선언하거나 메서드를 정의할 때 사용한다.
<%! ... %> 태그를 사용한다.

 

<%! 
    private String greeting = "Hello, JSP!";
    
    public String getGreeting() {
        return greeting;
    }
%>

 

표현식(Expression)
값을 출력할 때 사용하며, Java 표현식을 평가한 결과를 HTML로 출력한다.
<%= ... %> 태그를 사용한다.
<%
    String greeting = "Hello, 길동!";
%>
<p>Greeting: <%= greeting %></p>

 

JSP 액션 태그(Action Tags)
JSP 페이지에서 자바빈즈(Beans)를 사용하거나 다른 JSP 페이지를 포함시키는 등의 작업을 수행할 때 사용됩니다.

 

// 자바빈즈를 생성하거나 찾을 때 사용합니다.
<jsp:useBean id="myBean" class="com.example.MyBean" scope="session" />

// 자바빈즈의 속성 값을 설정할 때 사용합니다.
<jsp:setProperty name="myBean" property="username" value="JohnDoe" />

// 자바빈즈의 속성 값을 가져올 때 사용합니다.
<p>Username: <jsp:getProperty name="myBean" property="username" /></p>

// 다른 JSP 페이지를 포함시킬 때 사용합니다. 
<jsp:include page="header.jsp" />

// 다른 JSP 페이지로 요청을 포워드할 때 사용합니다.
<jsp:forward page="nextPage.jsp" />

... 등

 

💡 자바빈즈(JavaBeans)란?

재사용 가능한 객체: 자바빈즈는 재사용 가능하도록 설계된 Java 객체입니다.
특정 규약이 적용된 객체: 자바빈즈는 캡슐화, 기본 생성자, 직렬화 등의 규약을 따릅니다.
캡슐화(Encapsulation): 필드는 private으로 선언하고, 접근자 메서드(getter)와 설정자 메서드(setter)를 통해 접근합니다.
기본 생성자(Default Constructor): 자바빈즈 클래스는 기본 생성자를 반드시 가져야 합니다.
직렬화(Serialization): 자바빈즈는 Serializable 인터페이스를 구현하여 직렬화할 수 있습니다.
데이터 저장, 연산 및 전송: 자바빈즈는 애플리케이션에서 데이터를 저장하고, 연산을 수행하며, 다른 컴포넌트나 시스템으로 데이터를 전송하는 데 도움을 줍니다.

정리 - 동일한 클래스를 여러 곳에서 인스턴스화 해서 사용가능하며 스코프(scope) 내에서 재사용될 수 있습니다. 세션 스코프(scope)에서 생성된 자바빈즈 객체는 세션 내내 동일한 객체로 유지될 수 있습니다.

자바빈즈와 스코프

page: 현재 페이지에서만 사용 가능 (기본값)
request: 하나의 요청 동안 사용 가능
session: 세션 동안 사용 가능
application: 애플리케이션 전체에서 사용 가능

 

코드 실습 1 - 인사말 생성기
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	
	<h1>인사말 생성기</h1>
	<!-- 절대 경로 -->
	<!-- 상대 경로 -->
	<form action="greet.jsp" method="POST">
		<label for="name">당신에 이름을 입력하세요: </label>
		<input type="text" id="name" name="name" >
		<button type="submit">서버로 제출</button>
	</form>
	
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!-- JSP 페이지의 설정을 정의하는 지시자   -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>인사말을 완성 하였습니다.</h1>
	
	<%
		// 자바 실행 코드 
		// request 객체에서 값 추출 
		String name = request.getParameter("name");
		if(name == null || name.trim().isEmpty()) {
			out.println("<p> 앗! 당신에 이름을 먼저 입력해주세요 </p>");
		} else {
			out.print("<p>반가워, " + name + "! 나의 JSP Site 잘 왔어 환영~~");
		}
	%>
	
	<!-- 다시 이전 페이지로( 특정 페이지로 이동)   -->
	<a href="greet_from_page.html">Back</a>
	

</body>
</html>

 

코드 실습 2 - 간단한 계산기
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            display: flex;
            height: 100vh;
            justify-content: center;
            align-items: center;
            margin: 0;
            background-color: #f0f0f0;
        }
        .container{
            width: 300px;
            background-color: #fff;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        form{
            display: flex;
            flex-direction: column;
        }
        label{
            margin-bottom: 10px;
        }

        input[type="number"] {
            height: 30px;
            border: 1px solid #bababa;
            border-radius: 5px;
            margin-bottom: 20px;
        }
        input[type="submit"] {
                height: 40px;
                border-radius: 5px;
                border: 0;
                background-color: #45a049;
                color: #fff;
        }
        input[type="submit"]:hover{
            background-color: #1c5a1f;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>간단한 계산기</h1>
        <form action="calculator.jsp" method="post">
            <label for = "num1">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num1" name="num1" required="required">

            <label for = "num2">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num2" name="num2" required="required">

            <input type="submit" value="계산 요청하기">
        </form>
    </div>
</body>
</html>

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body{
            display: flex;
            height: 100vh;
            justify-content: center;
            align-items: center;
            margin: 0;
            background-color: #f0f0f0;
        }
        .container{
            width: 300px;
            background-color: #fff;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
        }
        form{
            display: flex;
            flex-direction: column;
        }
        label{
            margin-bottom: 10px;
        }

        input[type="number"] {
            height: 30px;
            border: 1px solid #bababa;
            border-radius: 5px;
            margin-bottom: 20px;
        }
        input[type="submit"] {
                height: 40px;
                border-radius: 5px;
                border: 0;
                background-color: #45a049;
                color: #fff;
        }
        input[type="submit"]:hover{
            background-color: #1c5a1f;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>간단한 계산기</h1>
        <form action="calculate.jsp" method="post">
            <label for = "num1">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num1" name="num1" required="required" value="10">
            
            <label for = "num2">첫번째 숫자를 입력하세요</label>
            <input type="number" id="num2" name="num2" required="required" value="20">
            <input type="submit" value="계산 요청하기">
        </form>
    </div>
</body>
</html>
반응형

'Java > Java 이론' 카테고리의 다른 글

[JSP] 주석과 지시자  (0) 2024.07.03
[JSP] JSP 라이프사이클  (0) 2024.07.03
[JSP] Java Server Pages 란?  (0) 2024.07.03
스레드(Thread)  (0) 2023.10.04
중첩 클래스  (0) 2023.10.02

+ Recent posts