>

상세 컨텐츠

본문 제목

[부트캠프] 1일차

0. 창업

by 마켓플레이어, 마케터 봉 2025. 3. 3. 21:03

본문

---
# 내용

## 변수 종류

- **String : 문자열 ex) String name = "봉드로이드";**
- String? : 문자 또는 비어있는(null)상태일 수 있습니다.
- **int : 정수 ex) int age = 20;**
- **double : 실수 ex) double height = 168.9;**
- **bool : 참/거짓 ex) bool isStudent = false;**
- **List : 데이터를 여러개 가진 배열**
- **Map : {key:value}형태를 가진 딕셔너리 형태.**
- **dynamic : 모든 자료형을 담을 수 있음. 문자, 숫자 등**
- Set
- const : 처음에 변수를 선언하며 담은 값을 변경할 수 없습니다.
- final : 선언하고 나중에 값을 담을 수 있으나, 한번 담으면 변경할 수 없습니다.

```dart title:"변수 학습"
main() {
  /// var : 처음 담은 값으로 자료형이 결정 됨
  var name = '철수';
  print(name); // 철수
  print(name.runtimeType); // string (문자)
  
  var age = 20;
  print(age); // 20
  print(age.runtimeType); // int (정수)
  
  
  print("="*20); // 구분선 ====================
  
  
  /// String : 문자만 넣을 수 있음
  String address = '우리집';
  print(address); // 우리집
  
  // address = 1; // ⬅️ String 만 담을 수 있기 때문에 이 코드는 에러 발생
  
  address = '모두의 집';
  print(address); // 모두의 집
  // '우리집' 이란 값을 address에 넣었다가, '모두의 집'이란 값으로 변경해 봄.
  
  
  print("="*20); // 구분선 ====================
  
  
  /// String? : 문자 또는 비어있을 수 있음
  String? email; // ⬅️ 아무것도 안넣었으므로 비어있음
  print(email); // null ⬅️ 비어있음을 의미
  
  email = "a@a.com"; // 문자열 할당
  print(email); // a@a.com
  
  email = null; // 다시 비우기
  print(email); // null
  
  
  print("="*20); // 구분선 ====================
    
  
  /// final : 값을 재할당 할 수 없음
  final String phone = "010-0000-0000";
  print(phone); // 010-0000-0000
  // phone = "010-1111-1111"; // final 때문에 이 코드는 실행 불가능
}
```

#### String
```dart title:"기본 - String"
void main() {
  String name = "철수"; // 쌍따옴표 가능
  String email = 'hello@world.com'; // 단따옴표 가능
  
  // 문자열 연산
  print(name + email); // 철수hello@world.com
  print(name + " " + email); // 철수 hello@world.com
  
  // 문자열 속에 변수값 할당
  print("name email"); // 변수가 아닌 name과 email 문자열 출력
  print("$name $email"); // 문자열 안에 변수의 값 넣기 : "$변수명"
  print("${name + email}"); // 문자열 안에 식 넣기 : "${변수명 이외의 것}" 
  
  // 내장함수
  print(email.split('@')); // 문자열 뒤에 .을 찍어서 문자열 내장된 기능을 쓸 수 있어요.
}
```

#### int, double
```dart title:"기본 - int, double"
void main() {
  // int
  int age = 20; // 정수 입력 가능
  print(age);
  
  // double
  double longitude = 127.634324; // 실수 입력 가능
  print(longitude);
  
  // int를 double로 변경
  print(age.toDouble());
  
  // double을 int로 변경 (소수점 버림)
  print(longitude.toInt());
  
  // 연산
  print(1 + 2); // 덧셈 = 3
  print(2 * 4); // 곱셈 = 8
  print(4 / 3); // 나누기 = 1.333...
  print(5 % 3); // 5를 3으로 나눈 나머지 = 2
  print(5 ~/ 3); // 5를 3으로 나눈 몫 = 1
}
```

#### bool
```dart title:"기본 - bool"
void main() {
  print(true); // 참 = true
  print(false); // 거짓 = false
  print(!true); // !는 not의 의미 = false
  
  // 비교 연산의 결과는 bool
  print(1 == 1); // == : 두 값이 같은지 비교. 1과 1은 같음 = true
  print(1 != 2); // != : 두 값이 다른지 비교. 1과 2는 서로 다름 = true
  print(1 > 2); // 1은 2보다 작음 = false
  print("hello" == 'hello'); // 같은 문자열이므로 true
    
  var myNumber = 1;
  var answerNumber = 1;
  
  // 참거짓을 판단하여 흐름을 변경하는 조건문과 함께 사용합니다.
  if(myNumber == answerNumber) {
    print("당첨"); // true인 경우 실행
  } else {
    print("꽝"); // false인 경우 실행
  }
}

```

#### List
```dart title:"기본 - List<T>"
void main() {
  // 배열 생성
  List<String> fruits = ["바나나"]; // 문자열만 담을 수 있는 배열을 생성합니다.
  print(fruits);
  print("fruits 개수 : ${fruits.length}"); // 개수 조회
  
  // 추가
  print('--------- 추가 -----------');
  fruits.add('딸기'); // 딸기 추가
  print(fruits);
  
  fruits.add('배'); // 배 추가
  print(fruits);
  
  // fruits.add(1); // fruits 타입이 List<String>이므로 문자열만 추가 가능
  
  // 조회
  print('--------- 조회 -----------');
  print(fruits[0]); // 배열에 0번째 아이템 꺼내기
  print(fruits[1]); // 배열에 1번째 아이템 꺼내기
  
  
  // 수정
  print('--------- 수정 -----------');
  print(fruits);
  fruits[0] = "키위"; // 0번째 바나나를 키위로 수정
  print(fruits);
  
  
  // 삭제
  print('--------- 삭제 -----------');
  fruits.remove('딸기'); // 딸기와 일치하는 값이 제거됩니다.
  print(fruits);
  fruits.removeAt(0); // 0번째 아이템 삭제
  print(fruits);
  
  
  // 뭐든지 담을 수 있는 배열 생성
  print('-------- dynamic --------');
  List<dynamic> buckets = [1, "문자", [1, 2]]; // dynamic은 모든 타입을 포괄합니다.
  print(buckets);
  buckets.add(true); // 아무거나 담을 수 있음
  print(buckets);
  print(buckets[2]); // 2번째 배열 조회
  print(buckets[2][0]); // 2번째 배열의 0번째 값 조회
}

```

#### Map
```dart title:"기본 - Map<K, V>"
void main() {
  // Map은 중괄호 {} 로 Key와 Value를 감싼 있는 형태입니다.
  // Map<Key 타입, Value 타입>과 같이 타입을 명시할 수 있습니다.
  Map<String, dynamic> person = {
    "name": "철수",
    "age": 20
  };
  print(person);
  
  // 조회 : map[key]를 입력하여 value를 가져옵니다.
  print(person['name']);
  print(person['age']);
  
  // 추가 : 새로운 key로 값을 넣는 경우, 추가가 됩니다.
  person['email'] = 'hi@mail.com';
  print(person);
  
  // 수정 : 기존에 존재하는 key로 값을 넣는 경우, 수정이 됩니다.
  person['age'] = 10;
  print(person);
  
  // 삭제 : key를 지정하여 삭제할 수 있습니다.
  person.remove('name');
  print(person);
}
```
- Map뒤에 꺽쇠 괄호가 붙은 것은 키/밸류 값의 변수 형태를 의미함.
- 즉, key 값인 name, age, email 은 다 문자지만, value 값은 문자나 숫자 등 다양한 형태가 올 수 있기에 dynamic으로 표현함.

#### dynamic
```dart title:"기본 - String"
void main() {
  // dynamic은 모든 자료형을 품을 수 있습니다.
  dynamic name = "철수"; // String 담기
  name = 20; // int 담기
  print(name);
  
  
  // var는 처음 담긴 값의 자료형만 넣을 수 있습니다.
  var age = 20; // int 20을 담았으므로 int만 넣을 수 있습니다.
  // age = "철수"; // int만 넣을 수 있어서 주석 해제시 에러가 납니다.
  print(age);
}
```




## 연산자, 사칙연산

#### AND, OR 연산자
```dart
void main() {
  // && : AND 연산자로 좌우 값이 모두 true일 때 전체를 true로 반환
  if (false && true) {
    print('&&는 하나라도 true가 아니면 실행이 안됩니다.');
  } else if (true && true) {
    print('&&는 양쪽 모두 true면 실행이 됩니다.'); // 이게 실행됨
  }
  
  // || : OR 연산자로 둘 중 하나만 true이면 전체를 true로 반환
  if (false || false) {
    print("||는 둘다 false면 실행이 안됩니다.");
  } else if (false || true) {
    print("||는 둘 중 하나라도 true면 실행이 됩니다."); // 이게 실행됨
  }
  
  
  int temp = 15;
  bool isSummer = true;

  if (isSummer && temp < 10) { // 여름이면서 10도 미만입니까?
    print("여름 and 10도 미만");
  } else if (isSummer || temp < 10) { // 여름이거나 10도 미만입니까?
    print("여름 or 10도 미만");
  }
}
```




## 조건문(if/else문, switch문)

### if/else문

```example
if( 조건 비교 ){
참인 경우 실행될 로직
} else {
위 조건이 거짓일 경우 실행될 로직 
}
```

```dart title:"if/else 예시"
void main() {
  int number = 3;

  if (number > 5) {
    print('number는 5보다 큽니다.');
  } else {
    print('number는 5보다 크지 않습니다.');
  }
}
```

### switch문

```example
switch( 확인할 변수 ) { 
case [환인할 변수에 해당되는 값] : 
실행로직; 
break;
case [환인할 변수에 해당되는 값2] : 
실행로직; 
break; 
case [환인할 변수에 해당되는 값3] : 
실행로직; 
break;
default: 
모든 case에 해당되지 않는 경우 실행 로직 ; 
}
```

```dart title:"switch 예시"
void main() {
  int number = 2;

  switch (number) {
    case 1:
      print('number는 1입니다.');
      break;
    case 2:
      print('number는 2입니다.');
      break;
    case 3:
      print('number는 3입니다.');
      break;
    default:
      print('number는 1, 2, 3 중 하나가 아닙니다.');
  }
}
```

#### switch문 참고
- enum 타입인 경우에는 switch문이 훨씬 낫다. enum이란 enumerated type의 줄임말로, 열거형이라 부른다. 예를 들어, 행동을 정의할 때, walk, run, jump, sit, sleep 이란 타입이 있다고 치자.

```dart title:"enum 참고 : 1단계"
enum Action {
  walk,
  run,
  jump,
  sit,
  sleep,
}

void main() {
  var action = Action.jump;
  switch (action) {

  }
}
```
1. 위와 같이 쓰면 switch 구문에 에러창이 뜸
2. 그 때 [command+.(쩜)] 누르면 "Add missing switch cases"라는 문장이 뜸
3. 그걸 누르면 아래와 같이 자동 완성됨.
```dart title:"enum 참고 : 2단계"
enum Action {
  walk,
  run,
  jump,
  sit,
  sleep,
}

void main2() {
  var action = Action.jump;
  switch (action) {

    case Action.walk:
      // TODO: Handle this case.
      throw UnimplementedError();
    case Action.run:
      // TODO: Handle this case.
      throw UnimplementedError();
    case Action.jump:
      // TODO: Handle this case.
      throw UnimplementedError();
    case Action.sit:
      // TODO: Handle this case.
      throw UnimplementedError();
    case Action.sleep:
      // TODO: Handle this case.
      throw UnimplementedError();
  }
}
```




## 반복문(for문)

```example
for( [반복 시작 시점] ; [반복 종료 시점] ; [증감값] ){
로직
}
```

```dart
void main() {
var sum =0;
for(var i = 0; i < 1000; i++){
 sum+=i;
}
print(sum); // 499500 
}

```

```dart title:"출력 시 $로 표현 가능"
void main() {
for(var i = 0; i < 5; i++){
 print('${i} 더하기 1은? ${i + 1}이다.');
}
}

```

```dart title:"for문과 for in 문"
void main() {
  // 과일 5개가 들어있는 배열의 내용을 모두 출력하려면 5번 print를 사용해야 합니다.
  List<String> fruits = ["딸기", "감", "배", "사과", "바나나"];
  print(fruits[0]);
  print(fruits[1]);
  print(fruits[2]);
  print(fruits[3]);
  print(fruits[4]);
  

  print("---- 반복문 ----");
  print("fruits.length : ${fruits.length}"); // 전체 배열의 개수

  // 반복문을 사용하면 과일의 개수에 상관없이 3줄만 입력하면 됩니다.
  for (int i = 0; i < fruits.length; i++) {
    print("$i : ${fruits[i]}"); // i가 0부터 fruits.length - 1까지로 변합니다.
  }
  
  
  print("---- for in 문 ----");
  
  // 참고로 for in문이라 불리는 다른 형태의 반복문도 있습니다.
  for (String name in fruits) {
    print(name); // fruits 배열의 원소를 차례대로 꺼냅니다.
  }
}
```



## 함수

```example
반환타입 함수명(매개변수1, 매개변수2, ...) {
// 비즈니스 로직 구현부
return 반환값;
}
```
- 반환타입 : 함수가 반환하는 값의 타입을 명시함. 반환값이 없는 경우 void 사용.
- [[부트캠프_Flutter 앱개발 1 - 반복문, 함수, 조건문, 동기-비동기, 클래스#변수 종류]]

```example hl:2,6 point1:4,9-12 title:"함수 작동 순서"
void main() {
  print("1. 시작");
  
  say();
  
  print("4. 종료!");
}

void say() {
  print("2. 안녕");
  print("3. Hello");
}
```
- 함수명(함수이름) : main(), say()
- main()함수 내에 say()함수를 호출하여 진행. → 즉, 1(main)>2(say)>3(say)>4(main) 순으로 print 됨.
![작동 순서](https://teamsparta.notion.site/image/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2Fa0a227d7-997b-4430-ad32-60c994a906a5%2FUntitled.png?table=block&id=8848fd09-494a-4923-9193-027ec82dfae7&spaceId=83c75a39-3aba-4ba4-a792-7aefe4b07895&width=1250&userId=&cache=v2)

```dart title:"함수에 값 전달"
void main() {
 say("영희", "철수야 안녕?");
}

void say(String from, String message) {
  print("$from : $message"); // 영희 : 철수야 안녕?
}
```
- 함수에 값을 전달할 때, 1개만 넣을 수도 있고, 2개 이상 넣을 수도 있다. 입력값이 여러개인 경우, 콤마를 이용해 추가할 수 있다.
- "영희", "철수야 안녕?"와 같은 입력값을 받는 from, message를 매개변수/파라미터/인자 등 다양하게 부른다.

```dart title:"함수에 null값 전달 - 옵셔널한 파라미터"
void main() {
 say(from:"철수",message:"안녕");
 say(from:"영희");

}

// 소괄호 안쪽이 중괄호로 감싸진 경우 = named parameter
// 네임드 파라미터 안에 ? 다음 파라미터가 오는 경우 = 옵셔널한 파라미너
void say({required String from, String? message}) {
  print("$from : $message"); // 철수 : 안녕 && 영희 : null
}
```
- 네임드 파라미터(필수값인 required)가 요구된 상태에서 옵셔널한 파라미터값이 들어갈 수 있음.


```example hl:1-3 point1:5 title:"화살표 함수"
say(){
return "hello";
}

say2() => "hello";
```
- say()함수와 say2()함수는 같은 결과물을 출력함

#### 예시

```dart title:"두 수의 뺄셈 예제 (포지셔널 파라미터 - 기본 형태)"
int substract(int a, int b) {
  int sum = a - b;
  return sum;
}

void main() {
  int result = substract(3, 5);
  int result2 = substract(5, 3);
  print('결과: $result');  // 출력: 결과: -2
  print('결과: $result2');  // 출력: 결과: 2
}
```
- 포지셔널 파라미터 (positional parameters) : 파라미터의 순서를 의미한다. 위 substract 라는 함수의 int a, int b라는 파라미터의 고정된 순서를 의미한다. 

```dart hl:7-8 title:"네임드 파라미터의 두 수의 뺄셈 예제"
int substract({required int frontValue,required int endValue}) {
  int sum = frontValue - endValue;
  return sum;
}

void main() {
  int result = substract(frontValue : 3 , endValue : 5);
  int result2 = substract(endValue : 5 , frontValue : 3);
  print('결과: $result');  // 출력: 결과: -2
  print('결과: $result2');  // 출력: 결과: -2
}
```
- 네임드 파라미터(named parameters) : 파라미터 전달 시 이름을 지정해서 전달하는 것. 그렇기에 위치가 변해도 상관없다. 위 예제처럼 frontValut, endValut를 네임드 파라미터라 하며, 위치가 변해도 해당 파라미터로 값이 지정되어 들어간다.

```dart hl:7-8 title:"네임드 파라미터의 옵셔널한 예제"
int add({required int frontValue,required int endValue, int? expansionValue}) {
  int sum = frontValue + endValue + (expansionValue??0);
  return sum;
}

void main() {
  int result = add(frontValue : 3, endValue : 5);
  int result2 = add(frontValue : 3, endValue : 5, expansionValue : 3);
  print('결과: $result');  // 출력: 결과: 8
  print('결과: $result2');  // 출력: 결과: 11
}
```
- 옵셔널한 파라미터(optional parameters) : 말 그대로 옵션 값이라는 의미다. 전달해도 되고, 전달하지 않아도 되는 파라미터다. 그렇기에 필수인 네임드 파라미터는 required 라는 '필수' 표시가 되어있지만, 옵셔널 파라미터는 물음표를 붙여넣은 것이다.
1. 옵셔널한 파라미터값은 변수타입에 물음표를 붙이면 된다.
2. 옵셔널한 파라미터값은 값이 없어도 함수가 작동된다. 즉, 유동적으로 값이 있는 경우와 없는 경우 작동하도록 할 수 있다. 조금 더 가변적이다라고 볼 수 있다. 확장성이 좋다고도 볼 수 있다.




## 클래스(객체)

```example
class 클래스명 {
생성자() //클래스명과 동일한 함수

    변수 //특성(클래스 내의 속성)

    메소드(){
//기능(클래스 내의 함수)
    }
}
```
- 클래스의 구성요소
- 속성(property) : 클래스 내의 ==변수==
- 메소드(method) : 클래스 내의 ==함수==
- 생성자(constructor) : 클래스 명과 동일한 ==함수==



```dart title:"클래스 예시"
class Human {
  // 특성특성
  final String id;
  final String name;
  int age;
  final Gender gender;

  // 생성자
  Human({
    required this.id,
    required this.name,
    required this.age,
    required this.gender,
  });

  // 기능 addAge라는 함수(메서드) 넣은 것.
  void addAge(){
    age++;
  }
}

enum Gender { M, W} // Gender의 경우 남자인지 여자인지 표시해줘야해서 따로 넣음.
```
- final 은 한번 값을 넣으면 바꿀 수 없음을 선언함. 즉, 나이는 매년 변경되기 때문에 final로 설정하지 않은 것임.

```dart title:"클래스 활용 예시"
void main() async {
  var totalYears = 10;
  print('프로그램 시작');
  var man = Human(
    id: '860319-xxxxxxx',
    name: '김성덕',
    age: 39,
    gender: Gender.M,
  );
  
  for (var currentYear = 1; currentYear < totalYears; currentYear++) {
    await Future.delayed(Duration(seconds: 1));
    print('$currentYear년이 흘렀습니다.');
    man.addAge();
    print('${man.name}은 ${man.age} 나이입니다.');
  }
  
  print('프로그램 종료');
}
```


#### 인스턴스(instance)

```example title:"인스턴스 예시" hl:9 point1:2
void main() {
Bread bread = Bread(); // Bread 생성자를 호출하여 인스턴스를 반환
print(bread); // Instance of 'Bread'
}

class Bread {

// 생성자
Bread();
}
```
- 라인9 : 생성자 Bread를 호출하여 인스턴스를 라인2에 반환함.
- 클래스 Bread 안에, 동일한 이름으로 함수가 있는 것을 생성자라 함. 즉, 이 생성자를 불러와서 미리 정의해둔 속성과 메소드를 가진 데이터 객체를 만들 수 있는데, 이를 인스턴스(instance)라 함.
```dart title:"인스턴스 예시" hl:11-12,22-24 point1:7-8,18-20,3-4
void main() {
  // 인스턴스(instance) 만들기
  Bread bread1 = Bread('팥'); // 클래스의 생성자를 호출하여 인스턴스(instance)를 만듭니다.
  Bread bread2 = Bread('크림');
  
  // 속성 호출
  print(bread1.content); // 팥
  print(bread2.content); // 크림
  
  // 메소드 호출
  print(bread1.getDescription()); // 맛있는 팥빵입니다.
  print(bread2.getDescription()); // 맛있는 크림빵입니다.
}

class Bread {
  String? content; // 클래스 속 변수를 속성(property)라고 부릅니다.
  
  Bread(String core) { // 클래스명과 동일한 이 함수를 생성자(constructor)라고 부릅니다.
    content = core;
  }
  
  String getDescription() { // 클래스 속 함수를 메소드(method)라고 부릅니다.
    return "맛있는 $content빵입니다.";
  }
}
```


#### 상속(extends)
```example title:"상속 extends 예시" hl:10,13 point1:15-17, point2:2-3,5-6
void main() {
  Bread bread = Bread();
  Cookie cookie = Cookie();

  print(bread.madeBy); //TouLesJours3 출력
  print(cookie.madeBy); //TouLesJours3 출력
}

//클래스 TouLesJOurs를 상속받음(변수와 함수를 그대로 전달받음)
class Bread extends TouLesJours {}

//클래스 TouLesJOurs를 상속받음(변수와 함수를 그대로 전달받음)
class Cookie extends TouLesJours {}

class TouLesJours {
  String madeBy = "TouLesJours3";
}
```
- class 클래스1 extends 클래스2 이라고 입력하면, 클래스2의 변수와 함수를 클래스1에서 그대로 사용할 수 있음.(예를 들어, 라인10,13이 라인15-17의 변수와 함수를 사용할 수 있다는 의미임.) 이를 클래스1이 클래스2의 기능을 그대로 물려받았다고 해서 상속(extends)받았다고 함.
- 또 다른 표현으로, 변수와 함수를 물려받은 클래스1을 자식(child), 기능을 물려준 클래스2를 부모(super)라고 부르기도 함.



## 동기/비동기(async, await)

```dart title:"동기 방식 소스코드"
void main() {
  print('print1');
  performTask();
  print('print3');
}

void performTask() {
  print('print2');
}
```
- void main 함수 내에 있는 순서대로 작업 수행. print1 > print2>print3

```dart title:"비동기 방식 소스코드"
void main() {
  print('print1');
  performTask();
  print('print3');
}

Future<void> performTask() async {
  await Future.delayed(Duration(seconds: 2));
  print('print2');
}
```
- void main 함수 내에 완료되는 순서대로 작업 수행. print1 > print3 > print2
- print2은 2초 딜레이를 걸어놨기 때문에 print3보다 먼저 시작되었지만, 출력은 나중에 된다.

```dart hl:3 title:"비동기를 동기 방식으로 처리하는 코드"
void main() async{
  print('print1');
  await performTask();
  print('print3');
}

Future<void> performTask() async {
  await Future.delayed(Duration(seconds: 2));
  print('print2');
}
```
- void main 함수 내 순서대로 실행된다. print1 > print2 > print3
- 단, print2 실행 되기 전 2초 딜레이 후 실행된다.
- 3번째 줄에 await을 붙여야만 동기방식으로 순서대로 처리된다. 그렇지 않으면(await을 지우면) print1 > print3 > print2 순서대로 실행된다.

'0. 창업' 카테고리의 다른 글

[부트캠프] 4일차 - 북클럽 정리  (0) 2025.03.06
[부트캠프] 3일차  (0) 2025.03.05
[부트캠프] 사업계획서 목차  (0) 2025.02.21
[부트캠프] 관련 용어 정리  (0) 2025.02.20
[부트캠프] 2주차 강의  (0) 2025.02.19

관련글 더보기