춘기IT/춘기개발

Dart 기본 문법(1) - 변수와 데이터 타입 / 연산자(Operators)

화춘기 2025. 6. 24. 18:03

Today I Learned (250624) 1-2.

 

1. 변수와 데이터 타입

변수

- 데이터를 저장하기 위한 공간 (데이터를 담는 상자)

- 데이터를 담는 상자인 변수에 데이터를 담고, 필요할 때 데이터를 꺼내서 사용

   ㄴ 나이라는 이름 상자를 만들고, 그 상자에 30 이라는 데이터를 담는 느낌

- 변수에 데이터를 저장하면 컴퓨터 메모리 어딘가에 그 데이터가 저장됨

   ㄴ 컴퓨터는 그 데이터를 저장하고 있다가 필요하다고 하면 변수 이름을 가지고 그 데이터를 찾아서 줌

- 상자에는 이름을 붙일 수 있음 (같은 이름의 데이터 상자 허용하지 않음)

변수의 종류: 프로그램 실행 중(런타임)에 값 변경 가능 여부에 따라 크게 2가지로 나뉨

1. 프로그램 실행 중에 값을 변경할 수 있는 변수
  * [타입] [변수이름] = [값];
int age = 30;
String name = 'Bob';
bool isStudent = true;​


  * var [변수이름] = [값];

var name = 'Bob';

 


  ㄴ 타입 추론 (Type Inference)을 해서, 타입을 쓰지 않는 경우도 있음
      * 타입 추론 (Type Inference): 타입을 명시하지 않았을 때 변수에 넣은 값을 보고, 타입을 추론해주는 것
         ㄴ 위와 같이 코드를 쓰면 name에 'Bob'이 할당된 것을 보고 name이 String 타입인 것을 추론함

2. 프로그램 실행 중에 값을 변경할 수 없는 변수: 상수(Constant)
  * final [타입] [변수이름] = [값];
final firstCurrentTime = DateTime.now(); // 타입 명시하지 않은 경우
final DateTime secondCurrentTime = DateTime.now(); // 타입 명시한 경우​

  ㄴ 타입 추론이 가능하기 때문에 [타입] 생략 가능
  ㄴ DateTime.now() 실행 시점의 현재 시간을 가져오는 코드

  * const [변수이름] = [값];
const pi = 3.14159; // 타입 명시하지 않은 경우
const int age = 30; // 타입 명시한 경우​


  ㄴ 마찬가지로 타입 추론이 가능하기 때문에 [타입] 생략 가능

* final / const 1) 초기화 시점 2) 용도에 차이가 있음
1) 초기화 시점
- final 변수: 프로그램 실행(런타임) 시점
- const 변수: 컴파일 시점 / 그래서 const 변수를 컴파일 타임 상수라고 부르기도 함

2) 용도
- final 변수: 프로그램 실행 중에 값이 결정되는 경우 ex. 현재 시간
- const 변수: 프로그램 실행 전이든 실행 후든 상관없이 항상 값이 고정인 경우 ex. 원주율 (3.14xxx...) 


* 변수의 값을 바꾸면 오류 발생 !!
final String name = 'Bob';
name = 'Alice'; // Error: Can't assign to the final variable 'name'.

const int age = 25;
age = 30; // Error: Can't assign to the const variable 'age'.​

3. late 변수
- 선언 후에 초기화되는 NonNullable한 변수
- 변수가 사용되는 시점에 초기화(지연 초기화)되는 변수
  * late [타입] [변수이름];
late String name;​

  ㄴ late 변수는 [타입] 생략 불가능

* late 변수 사용 시기
1) 변수를 선언할 당시에 넣어줄 값을 아직 특정하기 어려운 경우
late String description;

void main() {
  description = '설명입니다.';
  print(description); // 설명입니다.
}​

  ㄴ 선언할 때 넣어줄 값을 특정하기 어려울 때는 null을 쓰면 되지 않을까?
      - 컴퓨터는 null을 싫어하기 때문에 최대한 null 사용 자제
      - late 변수는 null을 허용하지 않으면서도 변수에 null을 넣어준 것과 비슷한 역할을 함
late String name;
print(name); // Error: Late variable 'name' without initializer is definitely unassigned.​

  ㄴ 값을 넣지 않은 상태로 변수를 쓰면 오류 발생 ! - 그렇기 때문에 사용 전 무조건 값을 넣어야 함

2) 초기화 비용이 높은 변수가 지금 당장 필요하지는 않은 경우
int getTemperature(int temperature) {
  return temperature;
}

void main() {
  late int temperature = getTemperature(35);
}​

  ㄴ main에 있는 temperature 변수가 사용되지 않았기 때문에 getTemperature(35)는 실행되지 않음

 

데이터 타입

- 타입은 프로그래밍 할 때 다루는 데이터의 형태

- 어떤 형태의 값을 다룰 것인지(데이터 타입을) 컴퓨터에게 알려줘야 함.

- 변수에 할당할 수 있는 값의 유형 (변수가 데이터를 담는 상자라면, 데이터 타입은 상자가 담을 수 있는 데이터의 형태)

* 데이터 타입 종류
1. 숫자형 (Numbers)
int : 정수(소수점이 없는 숫자) 유형
int [변수이름] = [값];

int a = 1;
int b = -5;​
double : 소수(소수점이 있는 숫자) 유형
double [변수 이름] = [값];

double a = 1.5;
double b = 0.1234;

* 값을 정수로 할당하면 자동으로 소수점 부여
double z = 1; // double z = 1.0 와 같아요.
z += 2.5;
print(z); // 3.5​

 

num : 정수, 소수 등의 모든 숫자 유형으로 int와 double의 상위 클래스
Object > num > int / double

num [변수 이름] = [값];

num a = 1;
num b = 1.5;

* int, double 모두를 포함하기 때문에, int, double 모두(정수/소수) 가능
num a = 1;
a += 2.5;
print(a); // 3.5​

2. 문자형 (Strings)
String : 문자 유형
String [변수이름] = '문자'; / String [변수이름] = "문자"; (작은 따옴표, 큰 따옴표 모두 가능)

String a = 'hello';
String b = "bye";

* 식별자는 $식별자 형태로, 표현식은 ${표현식} 형태로 만들면 문자열에 넣을 수 있음
String name = 'Bob';
print('Hello, my name is $name.'); // Hello, my name is Bob.
print('Hello, my name is ${name.toUpperCase()}.'); // Hello, my name is BOB.
* toUpperCase()는 문자열에 있는 모든 문자를 대문자로 변경함

* == 연산자를 통해 두 값이 같은지 판별 가능
String word = 'HELLO';
print('hello' == word.toLowerCase()); // true
* toLowerCase()는 문자열에 있는 모든 문자를 소문자로 변경함

* + 연산자를 통해 2개 이상의 문자열을 합칠 수 있음
String prefix = 'Hello, ';
String suffix = 'my name is Bob.';
print(prefix + suffix); // Hello, my name is Bob.

* 작은 따옴표 3개 이어 붙인 형태(''')나 큰 따옴표를 3개 이어 붙인 형태(""")를 통해 여러 줄의 문자열도 만들 수 있음
String s1 = '''
이렇게 하면
여러 줄의 문자열을
만들 수 있어요 !
''';
/*
이렇게 하면
여러 줄의 문자열을
만들 수 있어요 !
*/

String s2 = """이것도 여러 줄의
문자열이랍니다 !""";
/*
이것도 여러 줄의
문자열이랍니다 !
*/​

3. 불리언형 (Booleans)
bool : 참(true) 또는 거짓(false)으로 판별할 수 있는 유형
bool [변수이름] = [값];

bool isTrue = true;
bool isFalse = false;​

 

null

- 값이 없다는 것을 컴퓨터에 알려주기 위해 사용

- null을 허용하는 변수 (Nullable한 변수)는 타입 뒤에 ?를 붙임

int a = 3;
int? b = null;

a는 int 뒤에 ?가 없기 때문에 NonNullable한 변수이고,
b는 int 뒤에 ?가 있기 때문에 Nullable한 변수이다.

 

- null을 허용하는 변수는 초기값이 설정되지 않으면 기본적으로 null을 가짐

int? nullableInt;
print(nullableInt); // null

nullableInt = 1;
print(nullableInt); // 1

nullableInt = null;
print(nullableInt); // null

int nonNullableInt;
print(nonNullableInt); // Error: Non-nullable variable 'nonNullableInt' must be assigned before it can be used.

 

- null을 허용하는 변수를 사용할 때는 항상 주의해야하고, 최대한 덜 쓰려고 노력해야함

  ㄴ 컴퓨터가 null을 싫어하기 때문에 프로그램 실행중에 오류가 발생하기도 함.

  ㄴ 상관 없이 null을 오류 없이 안전하게 쓰고 싶다면?

      ㄴ ?. 연산자 사용

어떤 변수가 null이면 ?.이 포함한 표현식 전체가 null이 됨

String? name;
print(name?.length); // null

name = 'Bob';
print(name?.length); // 3

String? name; 까지만 있을 때는 name에 기본값으로 null이 들어가기 때문에
name?.length 가 null로 반환됨
하지만, name에 'Bob'을 넣어주면 더이상 name은 null이 아니기 때문에
name?. length가 null이 아닌 값이 반환됨

 

2. 연산자(Operators)

- 프로그램 내에서 데이터를 조작하거나 처리하기 위해 사용하는 기호 또는 키워드

- 수학적인 계산 뿐 아닌, 논리적인 비교, 데이터 조합 등 다양한 작업에 사용

* 연산자 종류

1. 산술 연산자 (Arithmetic Operators)
- 기본 연산 (덧셈, 뺄셈, 곱셈, 나눗셈, 나머지) 수행 시 사용
- 종류
+ : 두 개의 값을 더할 때 사용
int two = 2;
int three = 3;
print(two + three); // 5​

- : 하나의 값에서 다른 하나의 값을 뺄 때 사용
int two = 2;
int three = 3;
print(three - two); // 1
print(two - three); // -1​

* : 두 개의 값을 곱할 때 사용
int two = 2;
int three = 3;
print(two * three); // 6​

/ : 하나의 값에서 다른 하나의 값을 나눌 때 사용 > 그 값을 반환함
int five = 5;
int two = 2;
print(five / two); // 2.5​

~/ : 하나의 값에서 다른 하나의 값을 나눌 때 사용 > 정수 부분만 반환함
int five = 5;
int two = 2;
print(five ~/ two); // 2​

% : 하나의 값에서 다른 하나의 값을 나누었을 때 나오는 나머지를 구할 때 사용
int six = 6;
int four = 4;
print(six % four); // 2​

2. 비교 연산자 (Comparison Operators)
- 2개의 값을 비교할 때 사용
- 종류
== : 2개의 값이 같으면 true, 다르면 false를 반환
int a = 4;
int b = 4;
print(a == b); // true

int c = 2;
int d = 4;
print(c == d); // false

int? e = null;
int? f = null;
print(e == f); // true

int? g = null;
int? h = 2;
print(g == h); // false​

!= : 2개의 값이 다르면 true, 같으면 false 반환
int a = 2;
int b = 4;
print(a != b); // true

int c = 4;
int d = 4;
print(c != d); // false

int? e = null;
int? f = 2;
print(e != f); // true

int? g = null;
int? h = null;
print(g != h); // false​

> : > 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 크면 true, 작거나 같으면 false 반환
int a = 4;
int b = 2;
print(a > b); // true

int c = 2;
int d = 4;
print(c > d); // false​

< : < 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 작으면 true, 크거나 같으면 false 반환
int a = 2;
int b = 4;
print(a < b); // true

int c = 4;
int d = 2;
print(c < d); // false​

>= : >= 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 크거나 같으면 true, 작으면 false 반환
int a = 4;
int b = 2;
print(a >= b); // true

int c = 3;
int d = 3;
print(c >= d); // true

int e = 2;
int f = 4;
print(e >= f); // false​

<= : <= 기준으로 왼쪽에 있는 값이 오른쪽에 있는 값보다 작거나 같으면 true, 크면 false 반환
int a = 2;
int b = 4;
print(a <= b); // true

int c = 3;
int d = 3;
print(c <= d); // true

int e = 4;
int f = 2;
print(e <= f); // false​

3. 타입 체크 연산자 (Type Test Operators)
- 프로그램 실행 중 (런타임)에 타입을 검사할 때 사용

* 타입 체크 연산자의 종류
1) as : 타입을 변환(Type Casting)할 때 사용
- 형변환(Type Casting): 하나의 특정 타입으로 지정되어 있는 값을 다른 타입으로 바꾸는 것
int a = 2;
print(a as double); // 2

String b = '2';
print(b as double); // TypeError 발생​

 ㄴ 확실하게 형변환이 가능할 때만 사용 가능
     형변환이 불가능한 경우에 as를 사용하면 TypeError 발생

  2) is : 특정 타입을 가지고 있는지 판별할 때 사용
int? a = 2;
print(a is int); // true

int? b = null;
print(b is int); // false​

  3) is! : 특정 타입을 가지고 있지 않은지 판별할 때 사용 (is와 반대 개념)
int? a = null;
print(a is! int); // true

int? b = 2;
print(b is! int); // false​

4. 대입 연산자 (Assignment Operators)
- 값을 변수에 대입할 때 사용
* 대입 연산자 종류
= : = 기준으로 오른쪽 값을 왼쪽에 대입
int a = 2;
print(a); // 2​

??= : ??= 기준으로 왼쪽에 있는 것이 null 일 때 오른쪽 값을 대입
int? a = null;
a ??= 2;
print(a); // 2

int b = 3;
b ??= 2;
print(b); // 3​

+= : += 기준으로 왼쪽에 있는 것과 오른쪽에 있는 것을 더해서 왼쪽에 대입
        a += b 와 a = a + b 는 같은 의미
int a = 2;
int b = 3;
a += b;
print(a); // 5​

-= : -= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 빼서 왼쪽에 대입
       a -= b 와 a = a - b 는 같은 의미
int a = 3;
int b = 2;
a -= b;
print(a); // 1​

*= : *= 기준으로 왼쪽에 있는 것과 오른쪽에 있는 것을 곱해서 왼쪽에 대입
       a *= b 와 a = a * b 는 같은 의미
int a = 2;
int b = 3;
a *= b;
print(a); // 6​

/= : /= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 나눠서 왼쪽에 대입
     a /= b 와 a = a / b 는 같은 의미
double a = 6;
int b = 3;
a /= b;
print(a); // 2​

 

 

~/= : ~/= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 나누었을 때 나온 값의 정수 부분을 왼쪽에 대입
int a = 5;
int b = 3;
a ~/= b;
print(a); // 1​

%= : %= 기준으로 왼쪽에 있는 것에서 오른쪽에 있는 것을 나누었을 때 나온 나머지를 왼쪽에 대입
int a = 5;
int b = 3;
a %/= b;
print(a); // 2​

5. 논리 연산자 (Logical Operators)
- 참 또는 거짓으로 판별할 수 있는 표현식을 반전하거나 결합할 때 사용

* 논리 연산자 종류

1) ! : ! 기준으로 오른쪽에 있는 판별식을 반전
bool a = true;
print(!a); // 판별식을 반전해서 true가 false로 출력

 

2) || : || 기준으로 왼쪽 판별식과 오른쪽 판별식 중 하나라도 참이면 참을 반환하고, 모두 거짓이면 거짓을 반환
          또는(or)과 같은 의미라고 생각
bool a = true;
bool b = true;
print(a || b); // true

bool c = true;
bool d = false;
print(c || d); // true

bool e = false;
bool f = false;
print(e || f); // false​

3) && : && 기준으로 왼쪽 판별식과 오른쪽 판별식 모두 참이면 참을 반환하고, 하나라도 거짓이면 거짓을 반환해요.
             그리고(and)와 같은 의미라고 생각
bool a = true;
bool b = true;
print(a && b); // true

bool c = true;
bool d = false;
print(c && d); // false

bool e = false;
bool f = false;
print(e && f); // false​