Skip to main content

콘솔 RPG 게임 필수 기능 만들기

· 2 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

  • 콘솔 RPG 게임 만들기

✍️ 주요 학습 내용

배운 내용

  • 랜덤으로 값을 뽑아내는 기능
  • 파일 입출력을 처리하는 기능

새로 알게된 개념

콘솔 입력

  • stdin.readLineSync()

콘솔 입력 받기 전에 안내문구 입력

  • stdout.write()

파일 관련

final file = File(’./gameStats/characters.text’);
final contents = file.readAsStringSync();
final stats = contents.split(',');

랜덤값 구하기

import 'dart:math';
int attackingPower = Random().nextInt(100) + 10

nextInt(100)

→ 0부터 99까지의 랜덤값을 출력

→ +를 사용해 최소값을 정할 수 있음

실습한 내용

  • 필수기능 구현

🚨 발생한 문제/에러

  • 아직까진 없음

📝 코드 스니펫

// 오늘 배운 주요 코드
int randomInt = Random().nextInt(100) + 10;

📚 내일 학습할 내용

  • 개인과제 도전 기능 구현

💭 오늘의 회고

잘한 점 👍

  • 음 .. 최선을 다한 것?

개선할 점 🔨

  • 시간관리

배운 점 💡

  • 파일 입출력

✏️ 참고 자료

비동기 프로그래밍

· 6 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

아침에 코딩

주어진 문자열 haystack과 needle이 있을 때, needle이 haystack 내에서 처음 나타나는 위치를 반환합니다. needle이 존재하지 않으면 -1을 반환합니다.

int strStr(String haystack, String needle) {
return haystack.indexOf(needle);
}

알게 된 점

  • String 에서 indexOf로 특정 String 이 들어가는 시작 인덱스를 알 수 있다는 것을 배웠다.
  • 그리고 해당 문자열이 없으면 -1 로 반환된다는 것을 배워서 간단한 문제였음.

✍️ 주요 학습 내용

배운 내용

  • 동기 프로그래밍
  • 비동기 프로그래밍

새로 알게된 개념

비동기 프로그래밍
  • 작업이 완료될 때까지 기다리지 않고, 미래의 특정 시점에 값을 반환해요.
  • 결과값이 나올 때까지 멈춰 있지 않고, 수행할 수 있는 다른 작업을 찾아서 수행해요
  • dart:async
    • Future , Stream 클래스를 통해 비동기 프로그래밍 지원
Future 클래스
  • 작업이 성공적으로 완료되었을 때 해당 결과값을 반환하고 실행을 종료

  • 하나의 작업에 대해 값이나 이벤트가 한번 발생하는 단일 비동기 작업에 사용

  • Future 에 있는 delayed() 라는 메서드에 대해 알아보고 갑시다 👀

    • Future.delayed(Duration(seconds: [지연 시간]));

      void main() {
      int seconds = 2;
      print('실행 시작 !');
      Future.delayed(Duration(seconds: seconds));
      print('실행 끝 !');
      }

      /*
      실행 시작 !
      실행 끝 !
      */
    • Future.delayed(Duration(seconds: [지연 시간]), () {[지연 시간 후의 동작]});

      void main() {
      int seconds = 2;
      print('실행 시작 !');
      Future.delayed(Duration(seconds: seconds), () {
      print('$seconds초 다 기다림 !');
      });
      print('실행 끝 !');
      }

      /*
      실행 시작 !
      실행 끝 !
      2초 다 기다림 !
      */

async ~ await

→ 비동기 프로그래밍을 동기 프로그래밍으로!

await 을 사용하려면 Future<void> 를 반환타입에 명시해 줘야 함

한계점

  • 하나의 작업당 결과값을 1번만 받을 수 있음
  • 하나의 작업에 결과값이 여러 번 나오는 경우가 있을 수 있기 때문에 Stream 이 등장
Stream 클래스
  • 실행을 종료해 주지 않으면 계속 실행됨

  • 비동기 연산의 결과값이 여러 번 반환되는 경우 그 값을 순차적으로 받기 위해 사용됨

  • 코드를 본격적으로 써보기 전에 몇 가지에 대해 알아보고 갑시다 👀

    • yield

      • 값을 방출하도록 하는 키워드
        Stream<String> emitNames() async* {
        yield '강미래';
        yield '강현재';
        yield '강과거';
        }
        Stream<String> emitNames(List<String> names) async* {
        for (var i = 0; i < names.length; i++) {
        yield '${i + 1}번째는 ${names[i]} ~';
        }
        }
      • 함수메서드 에서 사용하는 return 과 같은 개념이라고 보시면 돼요 🙂
    • listen()

      • 방출되는 소리를 듣고 있는다는 뜻으로 생각하면 돼요 🙂

      • yield 를 통해 방출되는 값을 받기 위해 사용하는 메서드

        Stream<String> emitNames() async* {
        yield '강미래';
        yield '강현재';
        yield '강과거';
        }

        void main() {
        int number = 1;

        emitNames().listen((name) {
        print('$number번째는 $name ~');
        number += 1;
        });
        }

        /*
        1번째는 강미래 ~
        2번째는 강현재 ~
        3번째는 강과거 ~
        */
        Stream<String> emitNames(List<String> names) async* {
        for (var i = 0; i < names.length; i++) {
        yield '${i + 1}번째는 ${names[i]} ~';
        }
        }

        void main() {
        List<String> names = ['강미래', '강현재', '강과거'];
        emitNames(names).listen((element) {
        print(element);
        });
        }

        /*
        1번째는 강미래 ~
        2번째는 강현재 ~
        3번째는 강과거 ~
        */
  • async* 이렇게 사용을 해줘야 함.

실습한 내용

  • 없음

🚨 발생한 문제/에러

  • 없음

📝 코드 스니펫

// 오늘 배운 주요 코드
Stream<int> emitNumbers(int first) async* {
for(var i = first; i >= 0 ; i--){
yield i;

await Future.delayed(Duration(seconds : 1));
}
}

📚 내일 학습할 내용

  • 개인 과제

💭 오늘의 회고

잘한 점 👍

  • 집중 공부

개선할 점 🔨

  • 나태함 이기기

배운 점 💡

  • Future 클래스
  • Stream 클래스

✏️ 참고 자료

라이브러리를 이용한 확장

· 9 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

아침에 코딩
* 문제
주어진 배열 nums에서 특정 값 val을 제거해야 합니다.
제거한 후의 배열은 배열의 처음 부분에 남겨두고, 배열의 길이를 반환해야 합니다.
배열에서 제거된 값은 결과에 포함되지 않아야 하며,
반환된 길이를 기준으로 원래 배열의 처음 부분에 남은 값이 올바른 결과로 여겨집니다.

* 조건
1. 0 <= nums.length <= 100
2. 0 <= nums[i] <= 50
3. 0 <= val <= 100
class Solution {
int removeElement(List<int> nums, int val) {
int k = 0; // val이 아닌 요소의 개수를 셀 포인터

for (int i = 0; i < nums.length; i++) {
if (nums[i] != val) {
nums[k] = nums[i]; // val이 아닌 요소를 k 위치에 배치
k++; // 다음 위치로 이동
}
}

return k; // val이 아닌 요소의 개수를 반환
}
}

void main() {
Solution solution = Solution();
print(solution.removeElement([3, 2, 2, 3], 3)); // 2
print(solution.removeElement([0, 1, 2, 2, 3, 0, 4, 2], 2)); // 5
}

알게 된 점

  • 특정 요소가 제거된 후의 배열까지 만들려고 했었는데 그게 아니라 제거된 후 배열의 길이만 구하면 되어서 간단하게 할 수 있었다.

google_fonts , image_picker 등 다양한 꿀 외부 라이브러리에 대해서 알게 됐다.

  • import '[라이브러리 이름]';
    import 'dart:html';
    import 'package:http/http.dart'
  • import '[파일 경로]';
    import 'src/my_utils.dart';

✍️ 주요 학습 내용

배운 내용

  • 라이브러리 개념
  • 라이브러리 특징
  • 라이브러리 종류

새로 알게된 개념

라이브러리 종류

Dart SDK 표준 라이브러리

  • 프로그래밍에 필요한 기능을 제공하는 핵심 라이브러리 등을 가지고 있음

  • 모든 플랫폼에서 사용 가능

    • dart:core
    • dart:async
    • dart:collection
    • dart:convert
      • Json, UTF-8
      • 인코더, 디코더 제공
    • dart:developer
    • dart:math
  • Native Platform에서 사용 가능

    • Native platform 은 타겟이 Mobile, Desktop 이라고 했던 것 기억하시죠 ~?
    • dart:ffi
      • DartC API 를 사용할 수 있도록 하는 기능을 제공해요.
    • dart:io
      • 파일, 소켓, HTTP, 기타 입출력 등의 기능을 제공해요.
  • Web platform에서 사용 가능

    • 참고로, Web platformJavaScript 로 컴파일되는 코드랍니다 !
    • package:web
      • 가벼운 브라우저 API 와 연결하는 기능을 제공해요.
    • dart:js_interop
      • JavaScript 와 브라우저 API 를 상호운용할 수 있는 기능을 제공해요.
    • dart:html
      • HTML 요소들과 Web 기반 응용 프로그램 리소스들을 제공해요.

Dart SDK에 포함되어 있지 않은 라이브러리

  • Pub.dev 에서 다양한 외부 라이브러리를 쉽게 찾아서 사용할 수 있어요 🤩
  • cupertino_icons
    • FlutterCupertino 위젯에 쓰이는 기본 아이콘 에셋을 제공해요.
  • intl
    • 번역, 날짜 포맷팅, 숫자 포맷팅 등 국제화와 현지화 기능을 제공해요.
  • shared_preferences
    • 간단한 데이터를 다루는 기능을 제공해요.
    • iOSmacOS 에서 사용하는 NSUserDefaults, Android 에서 사용하는 SharedPreferences 와 같은 역할을 해요.
  • url_launcher
    • URL 을 다루는 기능을 제공해요.
  • image_picker
    • iOSAndroid 에서 사진 다루는 기능을 제공해요.
    • 예시로 카메라로 사진 찍는 기능이랑 앨범에서 사진 선택하는 기능이 있어요 !
  • firebase_core
    • Firebase 와 연동하는 작업할 때 필요한 핵심 기능을 제공해요.
  • firebase_auth
    • Firebase 인증 API 를 사용하기 위한 기능을 제공해요.
  • google_fonts
    • fonts.google.com 에서 제공하는 폰트를 사용하기 위한 기능을 제공해요.
  • permission_handler
    • iOSAndroid 의 권한을 다루는 기능을 제공해요.
  • custom_lint
    • Lint 규칙을 쉽게 적용할 수 있도록 해주는 기능을 제공해요.
    • Lint ?
      • 어떤 친구인가요 ?
        • 오류가 발생할 수 있는 코드, 코드 스타일에 어긋난 코드, 비효율적이거나 불필요한 코드 등을 찾아내서 경고를 띄워주는 도구
      • 왜 사용하나요 ? 사용하면 뭐가 좋은가요 ?
        • 코드의 품질을 개선할 수 있어요.
        • 코드의 가독성을 향상시킬 수 있어요.
        • 유지보수성 높은 프로젝트를 만들 수 있어요.
  • flutter_svg
    • SVG 를 렌더링하기 위한 기능을 제공해요.
  • cached_network_image
    • 네트워크를 통해 사진을 받아오고, 캐싱하는 기능을 제공해요.
  • flutter_local_notifications
    • 로컬 알림을 다루는 기능 (ex. 알림 표시, 알림 예약) 을 제공해요.
  • path_provider
    • 파일 시스템을 사용하기 위한 기능을 제공해요.
  • geolocator
    • iOSAndroid 에서 위치를 다루기 위한 기능을 제공해요.
  • dio
    • HTTP 네트워크 사용을 위한 기능을 제공해요.
라이브러리 특징
  • 어떤 특징이 있나요 ?
    • as 를 통해 라이브러리에 별칭을 부여할 수 있어요.
      import 'package:http/http.dart' as http;
    • show 를 통해 라이브러리에서 필요한 부분만 선택적으로 가져올 수 있어요.
      import 'package:lib1/lib1.dart' show foo;
    • hide 를 통해 라이브러리의 특정 부분을 제외하고 가져올 수 있어요.
      import 'package:lib2/lib2.dart' hide foo;
    • deferred as 를 통해 라이브러리가 필요한 시점에 로드되도록 할 수 있어요.
      • 지연 로딩 이라고도 불러요 🙂
      • 왜 사용하나요 ? 사용하면 뭐가 좋은가요 ?
        • 필요한 시점에 라이브러리가 로드되기 때문에 초기화하는 시간이 줄어들고, 성능이 향상돼요 👍🏼
      • 어떤 특징이 있나요 ?
        • 모든 플랫폼에서 지원하는 것은 아니고, Web platform 에서만 지원해요 🥹
      • 어떻게 생겼나요 ?
        • import ‘[라이브러리 이름이나 파일 경로]’ deferred as [식별자];
          import 'package:greetings/hello.dart' deferred as hello;
      • 어떻게 동작하나요 ?
        • deferred as 뒤에 썼던 식별자를 통해 loadLibrary() 를 라이브러리가 필요한 시점에 호출하면 그 라이브러리를 불러와요 !
          import 'package:greetings/hello.dart' deferred as hello;

          Future<void> greet() async {
          await hello.loadLibrary();
          hello.printGreeting();
          }
        • 저는 loadLibrary() 를 정의한 적이 없는데, 어떻게 된건가요 ?
          • deferred as [식별자] 를 통해 식별자를 만들어 주는 순간, 그 식별자에 loadLibrary() 가 자동으로 정의된답니다 🤩

실습한 내용

  • 없음

🚨 발생한 문제/에러

  • 없음

📝 코드 스니펫

// 오늘 배운 주요 코드
import 'dart:io';

📚 내일 학습할 내용

  • 개인과제 준비

💭 오늘의 회고

잘한 점 👍

  • 음..

개선할 점 🔨

  • 계획 세우기

배운 점 💡

  • 라이브러리

✏️ 참고 자료

에러 헨들링

· 4 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

오늘의 코딩

정렬된 배열에서 중복 제거

class Solution {
int removeDuplicates(List<int> nums) {
if(nums.isEmpty){return 0;}
int k = 1;

for(int i = 1; i < nums.length ; i++){
if(nums[i] != nums[k-1]){
nums[k] = nums[i];
k++;
}
}
return k;

}
}

문제점

  • 숫자 배열에서 조건에 숫자가 뒤로 갈수록 감소하지 않는다는 것을 파악하지 못함
  • 중복되는 것을 제거해서 ‘_’로 바꿔야 한다는 것을 잘못 이해해서 헛고생을 조금 했다. 매번 문제를 잘 이해하지 못하는 부분이 있는 것 같다.

  • 예외와 오류의 차이
    • 예외는 프로그래밍 로직 문제, 오류는 주로 시스템 문제(메모리 부족)

✍️ 주요 학습 내용

배운 내용

  • 예외 클래스
  • 오류 클래스
  • 예외와 오류의 차이
  • 예외처리

새로 알게된 개념

예외

FormatException

  • 다른 형태의 데이터가 들어갔을 때 예외 발생

IOException

  • 입출력 관련 오류

OSError

  • 운영체제 관련 에러

TimoutException

  • 비동기 처리시 시간이 오버할 때 나오는 에러

throw → 의도적으로 예외를 던지는 것.


예외에 사용하는 키워드

try 의 코드 블록 중에 예외가 발생하면 try 의 코드 블록에 있는 뒷 코드들은 실행되지 않음 → catch 문으로 넘어감

catch (e)

e → 예외객체가 매개변수로 들어옴

on

  • 단독으로 쓸 수 없음
  • 특정 타입의 예외를 다룸
try{

}on FormatException catch(e){}

finally

  • 예외 발생 여부에 상관없이 실행할 코드를 넣는 부분
try{
}catch(e){
}finally{
print('예외 처리 끝!')
}
오류(Error)
  • 오류를 발생하면 프로그램이 종료됨

AssertionError

  • assert(조건문)false 면 오류 발생

RangeError

  • 리스트 길이보다 더 큰 인덱스를 사용할 때
    • RangeError 를 상속받은 IndexError 를 발생

OutOfMemoryError

  • 메모리 부족

StackOverflowError

  • 메모리 영역 중 하나인 스택 영역이 가능한 범위를 넘어가는 현상
  • 스택은 지역 변수나 매개변수를 담는 공간

StateError

  • 객체가 현재 상태로는 특정 동작이 불가능할 때
  • ex) null.first()

UnimplementedError

  • 정의되지 않은 메서드나 기능을 호출했을 때

UnsupportedError

  • 호출은 하는데 동작은 하지 않음

실습한 내용

  • 없음

🚨 발생한 문제/에러

  • 없음

📝 코드 스니펫

// 오늘 배운 주요 코드
try{
}catch(e){
}finally{
}

📚 내일 학습할 내용

  • 종합반 강의 복습

💭 오늘의 회고

잘한 점 👍

  • 목표를 끝까지 지키려고 한 점

개선할 점 🔨

  • 완벽한 상태에서 과제를 하려고 하기보다 미리 시작하고 과제를 먼저 파악하는 게 중요한 것 같음

배운 점 💡

  • 예외를 예측하는 게 쉽지 않은 것 같음

✏️ 참고 자료

쇼핑몰 콘솔 프로그램 트러블 슈팅

· 5 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

오늘은 개인 과제로 - 콘솔로 쇼핑몰 기능을 하는 프로그램을 만드는 것이었다. 간단하게 생각해서 여유부리다가 마지막에 시간에 쫓겨서 도전 기능은 거의 못하고 제출하게 되었다.

나는 사용자가 입력할 수 있는 모든 예외 상황에 대처할 수 있는 프로그램을 만들기 위해서 여러 가지 신경을 썼었는데 해설강의를 들으니까 기본적인 예외만 처리하고 나머지는 프리하게 하는 것을 보면서 내가 너무 어렵게 했나 그런 생각도 들었다. 그래도 확실히 이런 여러 가지 과제들을 하면서 복잡한 로직?을 짜보는 게 중요한 것 같다.

아무래도 코딩을 하다 보면 자기가 익숙한 문법, 코드만을 가지고 계속해서 코딩을 하게 되는데 알고리즘 문제 등을 풀면서 내가 익숙하지 않았던 문법 요소들도 사용을 하게 되고 이 문법이 이렇게 쓰이는구나 라고 깨닫게 되는 것 같다.

✍️ 주요 학습 내용

배운 내용

  • 콘솔 프로그램 제작

새로 알게된 개념

쇼핑몰 과제

tryParse()

  • 성공시 정수 변환 → 실패시 null 반환
  • ?? 연산자로 0을 반환 처리 가능
트러블 슈팅1 : 공백 제거
void addToCart(String productName, int number) {
Product addedProduct =
products.where((product) {
print('product.name: ${product.name} productName: $productName');
print('== ${product.name == productName}');
return product.name == productName;
}).first;
cart.add(addedProduct);
totalPrice += addedProduct.price * number;
print(
'----------------------------------------------------------------------------------------',
);
print('장바구니에 상품이 담겼어요!');
}

// error message
수량 : 2
Unhandled exception:
Bad state: No element
#0 Iterable.first (dart:core/iterable.dart:645:7)
#1 ShoppingMall.addToCart (file:///Users/junseokyang/Desktop/project/flutter/assignment/consoleShoppingMall/consoleShoppingMall.dart:29:66)
#2 main (file:///Users/junseokyang/Desktop/project/flutter/assignment/consoleShoppingMall/consoleShoppingMall.dart:139:24)
#3 _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:315:19)
#4 _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:194:12)
product.name: 셔츠 productName: 반바지
== false
product.name: 원피스 productName: 반바지
== false
product.name: 반팔티 productName: 반바지
== false
product.name: 반바지 productName: 반바지
== false
  • 장바구니에 상품을 담기 위해서 수량을 입력하면 에러가 나왔다.
  • 원인은 입력한 상품명과 동일한 상품명을 갖고 있는 요소들을 배열로 만들어야 되는데 동일한 상품명이 없어서 빈 배열을 where 을 통해서 반환하게 되고 거기서 first 를 사용해서 첫 번째 요소를 받으려고 하니까 오류가 생겼다.
  • 분명히 상품명을 동일하게 입력했는데도 오류가 나오니까 where 문에 print 를 추가해서 값을 비교했다.
  • 그랬더니 입력을 할 때 양말[공백] 이런 식으로 뒤나 앞에 공백이 있으면 양말과는 일치하지 않는다고 나와서 where 에서 빈 배열을 반환하게 되는 오류였다.
  • 그래서 addToCart() 매개변수로 보내기 전에 productName.trim() 이렇게 trim() 을 사용해 양 옆 공백을 제거해 줌으로써 문제가 해결이 되었다.
해설

stdin.readLineSync();String? 을 반환함

import ‘dart:io’;

  • 입출력을 담당하는 라이브러리
  • std → standard의 준말
  • in → input

stdin.readLineSync(); : 입력요청

stdout.write(’상품명 : ‘); 글자 출력

No Element → Exception 처리

try & catch

switch

default: → 옵션에 없는 값이 나왔을 때

List<Map> cart = [];
cart.add({"product" : currentProduct, "count" : count})
cartItem['product'].name

실습한 내용

  • 콘솔 프로그램 제작

🚨 발생한 문제/에러

  • 위에서 정리를 함. 공백 문제

📝 코드 스니펫

// 오늘 배운 주요 코드
string.trim()

📚 내일 학습할 내용

  • 종합반 복습

💭 오늘의 회고

잘한 점 👍

  • 과제 마무리

개선할 점 🔨

  • 미리미리 과제를 시작할걸..

배운 점 💡

  • dart의 io 입출력에 대해서 배움

✏️ 참고 자료

객체 지향 프로그래밍 배우기

· 20 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

오늘의 코딩

공통된 접두사를 찾아서 반환해라

// 강사님 풀이법
String longestCommonPrefix(List<String> strs){
if(strs.isEmpty){
return ""
}
String prefix = strs.first;

for(var i = 1; i < strs.length; i++){
String str = strs[i];
while(!str.startsWith(prefix)){
prefix = prefix.substring(0, prefix.length - 1);
if(prefix.isEmpty){
return "";
}
}
}
return prefix;

}
// 내 풀이법 str.codeUnits
class Solution {
String longestCommonPrefix(List<String> strs) {
if (strs.isEmpty) {
return solutionStr;
}

String prefix = "";
String solutionStr = "";
List<String> firstStr = strs[0].split("");
for(int i = 0; i < firstStr.length; i++){
prefix = firstStr[i];

if(strs.every((samePrefix) => samePrefix.startsWith(prefix, i))){
solutionStr += prefix;
}else{
break;
}
}
return solutionStr;
}
}

알게 된 점

  1. 빈 배열에 대한 예외 처리
    1. 빈 List가 왔을 때 에러가 나오기 때문에 처음에 isEmpty 로 예외처리해 주기
  2. subString([시작인덱스], [길이])
    1. 문자열에서 원하는 부분을 출력할 때
  • 클래스의 개념에 대해서 배웠다. 속성에서 클래스 변수, 지역 변수, 정적 변수가 있었는데 정적 변수에 대한 개념이 없었는데 정적 변수에 대해서 확실히 배울 수 있었다.
  • 지금까지 메서드와 함수를 같은 개념으로 생각해 왔는데 그렇지 않다는 것을 알게 되었다. 메서드는 클레스에 종속되어 있는 것이고 함수는 클래스와 관계없이 있는 것을 함수라고 하는데 그 차이점을 알게 되었다.
  • 또한 정적 메서드도 클래스에 종속되어 있어서 클래스를 통해서 호출가능한 메서드라는 것을 배울 수 있었다.
  • 클래스 변수인지 객체 변수인지 구분하는 게 중요하다는 것을 알 수 있었음.
  • 클래스 메서드는 객체 변수를 사용할 수 없음!
  • 제네릭 클래스를 활용해서 클래스명 뒤에 <T> 를 사용해서 제네릭 클래스임을 명시해 주고 타입에 T 를 사용해서 유동적인 타입을 줄 수 있음.
  • 부모 클래스자식 클래스 에게 자신의 모든 속성메서드상속 해요.
  • final 을 사용해서 하나의 클래스 로부터 자식 클래스 를 만들 수 없도록 할 수 있음
    • final class [class 명]{}

✍️ 주요 학습 내용

배운 내용

  • 클래스
  • 클래스의 정적 변수
  • 메서드와 함수
  • 제네릭 클래스

새로 알게된 개념

클래스

class [클래스 이름] { … }

class Person {
String name;
int age;

Person(this.name, this.age);

void introduce() {
print('안녕 ? 나는 $age살 $name !');
}
}

속성 (attribute)

  1. 인스턴스 변수(Instance Variable)

    1. 객체에 속해 있는 변수

      class Person {
      String name = '강미래';
      int age = 25;
      }
    2. this 를 통해 접근 가능(this 객체를 의미)

    3. 객체가 존재하는 동안 계속 메모리 상에 존재

  2. 지역 변수 (Local Variable)

    1. 특정 코드 블록 안에 선언된 변수

      class Person {
      String name = '강미래';

      void sayName() {
      String nameSentence = '내 이름은 $name !';
      print(nameSentence);
      }
      }
    2. 변수가 선언된 코드 블록의 실행이 끝나면 메모리 상에서 사라짐

  3. 정적 변수 (Static Variable)

    • 클래스 변수라고 불림
    • 객체에 종속되지 않고 클래스 자체에 속하는 변수
    class Circle {
    static double pi = 3.14159;
    }
    • 클래스 이름을 통해 접근 가능
    class Circle {
    static double pi = 3.14159;
    double radius = 0;
    }

    void main() {
    print(Circle.pi); // 3.14159
    print(Circle.radius); // Error: Member not found: 'radius'.
    }
    • 객체를 통해 접근할 수 없음
    class Circle {
    static double pi = 3.14159;
    double radius = 0;
    }

    void main() {
    Circle circle = Circle();
    print(circle.radius); // 0
    print(circle.pi); // 오류 발생
    }
    • this 를 통해 접근할 수 없음
    • 모든 객체가 서로 값을 공유함
branch 관리

mileStone에서 이슈를 만들어서 이슈명에 맞게 브랜치 명에 맞게 함

pull request 남기기 전에 rebase가 깔끔한 것 같음

메서드
  • 메서드 (Method)
    • 어떤 친구인가요 ?
      • 객체동작 을 정의하는 함수
      • 속성 을 변경하거나 객체 를 가지고 특정 작업을 수행해요.
      • 여기서 잠깐 ! 🧐 함수 (Function) 랑 메서드 (Method) 는 서로 같은 개념일까요 ?
        • 엄밀히 말하면, 완전히 같지는 않아요 !
          • 두 친구 모두 동작을 정의한다는 점에서는 같지만,
          • 메서드클래스 에 의존하고, 함수클래스 에 의존하지 않는다는 차이가 있어요.
            void function() {
            print('저는 함수입니다 !');
            }

            class Class {
            void method() {
            print('저는 메서드입니다 !');
            }
            }

            void main() {
            function(); // 저는 함수입니다 !

            Class object = Class();
            object.method(); // 저는 메서드입니다 !
            }
    • 종류에는 무엇이 있나요 ?
      • 인스턴스 메서드 (Instance Method)
        • 어떤 친구인가요 ?
          • 객체 에 속해 있는 메서드
            class Person {
            String name = '강미래';
            int age = 25;

            void introduce() {
            print('안녕 ? 나는 $age살 $name !');
            }
            }
        • 어떤 특징이 있나요 ?
          • this 를 통해 접근할 수 있어요.
            class Person {
            String name = '강미래';
            int age = 25;

            void printName() {
            print(name);
            }

            void printNameAndAge() {
            this.printName();
            print(age);
            }
            }
          • 클래스 의 모든 곳에서 접근할 수 있어요.
            class Person {
            String name = '강미래';
            int age = 25;

            void printName() {
            print(name);
            }

            void printNameAgain() {
            printName();
            }
            }
      • 정적 메서드 (Static Method)
        • 클래스 메서드 라고도 불러요.
        • 어떤 친구인가요 ?
          • 객체 에 종속되지 않고, 클래스 자체에 속하는 메서드
            class Circle {
            static double pi = 3.14159;

            static void printPi() {
            print('원주율은 $pi !');
            }
            }
        • 어떤 특징이 있나요 ?
          • 클래스 이름을 통해 호출해요.
            • 그래서 객체 를 생성하지 않고도 메서드 를 호출할 수 있답니다 👍🏼
              class Circle {
              static double pi = 3.14159;
              double radius = 0;

              static void printPi() {
              print(pi);
              }

              void printRadius() {
              print(radius);
              }
              }

              void main() {
              Circle.printPi(); // 3.14159
              Circle.printRadius(); // 오류 발생
              }
          • 객체 를 통해 호출할 수 없어요.
            class Circle {
            static double pi = 3.14159;
            double radius = 0;

            static void printPi() {
            print(pi);
            }

            void printRadius() {
            print(radius);
            }
            }

            void main() {
            Circle circle = Circle();
            circle.radius = 5;
            circle.printRadius(); // 5
            circle.printPi(); // 오류 발생
            }
          • this 를 통해 호출할 수 없어요.
            class Circle {
            static double pi = 3.14159;
            double radius = 0;

            static void printPi() {
            print(pi);
            }

            void printPiAgain() {
            this.printPi(); // 오류 발생
            }
            }
          • 코드 블록에서 인스턴스 변수 를 사용할 수 없어요.
            class Circle {
            double pi = 3.14159;
            double radius = 0;

            static void printPi() {
            print(pi); // 오류 발생
            }
            }
            • 그럼 인스턴스 메서드 의 코드 블록에서 정적 변수 를 쓸 수 있을까요 ?
              • Yes !! 완 ~ 전 ~ 가능 🎶
                class Circle {
                static double pi = 3.14159;
                double radius = 0;

                void printArea() {
                print(pi * radius * radius);
                }
                }
          • 객체마다 개별적으로 동작하지 않고, 모두 동일하게 동작한다.
  • 속성메서드클래스 안에 있는 요소라서 클래스멤버 (Member) 라고 부르기도 해요 !
생성자
  • 생성자 (Constructor) 라는 친구인데요 !
    • 어떤 친구인가요 ?
      • 객체 를 생성하고, 초기화하기 위해 사용하는 특수한 메서드
    • 종류에는 어떤 것이 있나요 ?
      • 기본 생성자 (Default Constructor)
        • 어떤 친구인가요 ?
          • 매개변수 를 갖지 않는 생성자
        • 어떻게 생겼나요 ?
          • [클래스 이름]();
            class Car {
            Car();
            }
        • 어떤 특징이 있나요 ?
          • 자동으로 정의되기 때문에 클래스 에 따로 명시하지 않아도 돼요.
            class Car {

            }

            void main() {
            Car car = Car();
            }
            class Car {
            Car();
            }

            void main() {
            Car car = Car();
            }
            class Car {

            }

            void main() {
            Car car = new Car();
            }
          • 인스턴스 변수 들이 모두 초기화되어 있는 상태여야 해요.
            class Car {
            String name = '';
            List<String> models = [];

            Car();
            }
            class Car {
            String name; // Error: Field 'name' should be initialized because its type 'String' doesn't allow null.
            List<String> models; // Error: Field 'models' should be initialized because its type 'List<String>' doesn't allow null.

            Car();
            }
      • 매개변수 생성자 (Parameterized Constructor)
        • 어떤 친구인가요 ?
          • 매개변수 를 갖는 생성자
          • 매개변수 를 통해 외부에서 인스턴스 변수 들의 초기값을 설정해요.
        • 어떻게 생겼나요 ?
          • [클래스 이름](this.변수);
            class Car {
            String name;
            List<String> models;

            Car(this.name, this.models);
            }
          • [클래스 이름]([타입] [매개변수 이름]) : this.변수;
            class Car {
            String name;
            List<String> models;

            Car(String name, List<String> models)
            : this.name = name,
            this.models = models;
            }
          • [클래스 이름]([타입] [매개변수 이름]) { this.변수; }
            class Car {
            String name = '';
            List<String> models = [];

            Car(String name, List<String> models) {
            this.name = name;
            this.models = models;
            }
            }
        • 어떤 특징이 있나요 ?
          • 객체 생성할 때 매개변수 를 넣지 않으면 오류가 나요 🚨
            class Car {
            String name;
            List<String> models;

            Car(this.name, this.models);
            }

            void main() {
            Car car = Car(); // Error: Too few positional arguments: 2 required, 0 given.
            }
      • 네임드 생성자 (Named Constructor)
        • 어떤 친구인가요 ?
          • 클래스 메서드 와 같은 형식으로 호출하는 생성자
        • 어떻게 생겼나요 ?
          • [클래스 이름].[메서드 이름]([타입] [매개변수 이름]) : this.변수;
            class Car {
            String name;
            List<String> models;

            Car.fromList(List values)
            : this.name = values[0],
            this.models = values[1];
            }
        • 어떻게 사용하나요 ?
          class Car {
          String name;
          List<String> models;

          Car.fromList(List values)
          : this.name = values[0],
          this.models = values[1];

          void speakName() {
          print('저희는 $name 입니다 !');
          }

          void speakModels() {
          print('$models 모델을 가지고 있습니다 !');
          }
          }

          void main() {
          Car car = Car.fromList([
          'BMW',
          ['320i', '340i', 'M3']
          ]);
          car.speakName(); // 저희는 BMW 입니다 !
          car.speakModels(); // [320i, 340i, M3] 모델을 가지고 있습니다 !
          }
        • 어떤 특징이 있나요 ?
          • 클래스 에 있는 변수타입 이 맞지 않는 값을 넣으면 오류가 나요 🚨
            class Car {
            String name;
            List<String> models;

            Car.fromList(List values)
            : this.name = values[0],
            this.models = values[1];
            }

            void main() {
            Car car = Car.fromList([
            'BMW',
            [1, 2, 3]
            ]); // TypeError: Instance of 'JSArray<int>': type 'List<int>' is not a subtype of type 'List<String>'
            }
    • 어떤 특징이 있나요 ?
      • 클래스 와 이름이 같아요.
      • 반환값 이 없기 때문에 void 타입이에요.
      • 클래스 를 통해 객체 가 생성될 때 자동으로 호출돼요.
      • 생성할 수 있는 객체 의 수에는 제한이 없어요.
        class Person {
        String name;
        int age;

        Person(this.name, this.age);
        }

        void main() {
        Person paul = Person('Paul', 25);
        Person mark = Person('Mark', 30);
        }
      • 생성한 객체 들은 서로 같지 않은 독립된 개체예요.
        class Person {
        String name;
        int age;

        Person(this.name, this.age);
        }

        void main() {
        Person paul1 = Person('Paul', 25);
        Person paul2 = Person('Paul', 25);
        print(paul1 == paul2); // false
        }
제네릭 클래스
  • 제네릭 클래스 (Generic Class) ?
    • 어떻게 생겼나요 ?
      • [클래스 이름]<타입 파라미터>
        class Box<T> {
        T value;

        Box(this.value);

        T getValue() {
        return value;
        }
        }
    • 왜 사용하나요 ?
      • 제네릭 함수 와 마찬가지로 특정 타입에 의존하지 않고, 여러 타입에 대해 동일한 코드를 적용할 수 있어서 재사용성 높은 코드를 짤 수 있겠죠 👍🏼

        class IntBox {
        int value;

        IntBox(this.value);

        int getValue() {
        return value;
        }
        }

        class StringBox {
        String value;

        StringBox(this.value);

        String getValue() {
        return value;
        }
        }

        void main() {
        var intBox = IntBox(10);
        print(intBox.getValue()); // 10

        var stringBox = StringBox('Hello');
        print(stringBox.getValue()); // Hello
        }
        class Box<T> {
        T value;

        Box(this.value);

        T getValue() {
        return value;
        }
        }

        void main() {
        var intBox = Box<int>(10);
        print(intBox.getValue()); // 10

        var stringBox = Box<String>('Hello');
        print(stringBox.getValue()); // Hello
        }
상속(Inheritance)

상속 (Inheritance)

  • 어떤 친구인가요 ?
    • 기존 클래스의 기능을 확장하여 새로운 클래스를 만드는 것
    • 하나의 클래스 가 다른 클래스속성메서드 를 물려받는 것
      • 물려주는 클래스부모 클래스 (Parent Class, Superclass), 물려받는 클래스자식 클래스 (Child Class, Subclass) 라고도 불러요.
  • 어떻게 생겼나요 ?
    • class [자식 클래스 이름] extends [부모 클래스 이름] { … }
      class Person {
      void eat() {
      print('냠냠 !');
      }
      }

      class Student extends Person {
      void study() {
      print('열공 !');
      }
      }
  • 어떤 특징이 있나요 ?
    • 부모 클래스자식 클래스 에게 자신의 모든 속성메서드상속 해요.
      class Person {
      String name = '';

      void eat() {
      print('냠냠 !');
      }
      }

      class Student extends Person {
      void study() {
      print('열공 !');
      }
      }

      void main() {
      Student student = Student();
      student.name = '강미래';
      student.eat(); // 냠냠 !
      student.study(); // 열공 !
      }
    • 부모 클래스자식 클래스 에 있는 멤버 (속성, 메서드) 를 사용할 수 없어요.
      class Person {
      void eat() {
      print('냠냠 !');
      }
      }

      class Student extends Person {
      void study() {
      print('열공 !');
      }
      }

      void main() {
      Person person = Person();
      person.study(); // Error: The method 'study' isn't defined for the class 'Person'.
      }
    • super 를 통해 자식 클래스부모 클래스속성메서드 를 사용할 수 있어요.
      class Person {
      String name = '강미래';

      void eat() {
      print('냠냠 !');
      }
      }

      class Student extends Person {
      void eatAndIntroduce() {
      super.eat();
      print('맛있게 먹는 ${super.name} ㅋㅋ');
      }
      }

      void main() {
      Student student = Student();
      student.eatAndIntroduce();
      }

      /*
      냠냠 !
      맛있게 먹는 강미래 ㅋㅋ
      */
    • 자식 클래스상속 받은 속성메서드재정의 (Overriding) 하거나 기능을 확장할 수 있어요.
      • 재정의 (Overriding) ?
        • 어떤 친구인가요 ?
          • 자식 클래스부모 클래스 로부터 상속 받은 속성메서드 를 그대로 사용하지 않고, 덮어 씌우는 것을 의미해요.
        • 언제 사용하나요 ?
          • 부모 클래스 에 정의되어 있는 속성 이나 메서드 가 마음에 안 들어서 새로 정의하고 싶을 때 사용해요 🤣
        • 어떻게 생겼나요 ?
          • @override [변수 이름] = [값];
            class Person {
            String name = '강미래';

            void eat() {
            print('냠냠 !');
            }
            }

            class Student extends Person {
            @override
            String name = '여러분';

            void study() {
            print('열공하는 $name !');
            }
            }

            void main() {
            Student student = Student();
            student.study(); // 열공하는 여러분 !
            }
          • @override [반환 타입] [함수 이름]() { … }
            class Person {
            void eat() {
            print('냠냠 !');
            }
            }

            class Student extends Person {
            @override
            void eat() {
            print('쩝쩝 !');
            }
            }

            void main() {
            Student student = Student();
            student.eat(); // 쩝쩝 !
            }
      • 재정의 는 알겠는데요 ~ 기능 확장은 어떻게 해요 ? 🤔
        class Person {
        void eat() {
        print('냠냠 !');
        }
        }

        class Student extends Person {
        @override
        void eat() {
        super.eat();
        print('쩝쩝 !');
        }
        }

        void main() {
        Student student = Student();
        student.eat();
        }

        /*
        냠냠 !
        쩝쩝 !
        */
  • 왜 사용하나요 ?
    • 공통적인 속성메서드부모 클래스 에 정의하고, 공통되지 않는 요소들만 따로 자식 클래스 에 정의해서 중복된 코드를 줄이고, 코드의 재사용성을 높일 수 있어요 👍🏼
  • 근데요 .. 어떤 클래스상속 당하지 (?) 않게 하고 싶을 수도 있잖아요 😅
    • 그 경우에는 final 을 사용하면 돼요 !
    • final ?
      • 어떤 친구인가요 ?
        • 하나의 클래스 로부터 자식 클래스 를 만들 수 없도록 하는 것
        • 상속 받을 수 없도록 만드는 키워드라고 생각하면 돼요 🙂
      • 어떻게 생겼나요 ?
        • final class [클래스 이름] { … }
          final class Person {
          void eat() {
          print('냠냠 !');
          }
          }

          class Student extends Person {
          // Error: The type 'Student' must be 'base', 'final' or 'sealed' because the supertype 'Person' is 'final'.
          }

실습한 내용

  • 쇼핑몰 콘솔 프로그램 제작
    • 다음 글에 포스팅할 예정🙂

🚨 발생한 문제/에러

  • 없음

📝 코드 스니펫

// 오늘 배운 주요 코드
final class NoChildClass{}

📚 내일 학습할 내용

  • 예외처리
  • 라이브러리

💭 오늘의 회고

잘한 점 👍

  • 강의에 집중할 수 있었음

개선할 점 🔨

  • 시간관리 조금 더 디테일하게 하면 좋을듯

배운 점 💡

  • 클래스 개념
  • 메서드와 함수의 차이
  • 상속
  • 객체지향 프로그래밍

✏️ 참고 자료

함수형 프로그래밍(고차 함수 꿀기능인듯;;)

· 31 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

🖥️ 오늘의 코딩

❓ 로마 문자를 숫자로 바꾸시오!

Class Solution{
int ramanToInt(String s){
List<String> romans = s.spit('');
Map<String, int> romanMap = {
'I': 1,
'V': 5,
'X': 10,
'L': 50,
'C': 100,
'D': 500,
'M': 1000,
};
int sum = 0;
for(int i = 0; i < romans.length; i++{
if(i + 1 < romans.length
&& romanMap[romans[i] < romanMap[romans[i+1]){
sum -= romanMap[romans[i]];
}else{
sum += romanMap[romans[i]];
}
}
}
}

main() {
Solution solution = Solution();
print(solution.romanToInt("III"));
print(solution.romanToInt("LVIII"));
print(solution.romanToInt("MCMXCIV"));
}

알게 된 점

  • 로마자들을 Map 으로 만들어서 구현해 낼 생각을 처음에는 못했던 것 같다. 역시 Map 을 자주 사용하는 것 같아서 Map 에 익숙해져야 할 필요가 있다고 느꼈다.

오늘은 내가 익숙하지 않았던 여러 가지 함수에 대해서 배울 수 있었다. 그리고 Collection 에서 사용되는 다양한 고차 함수를 익히면서 메서드 체이닝 방식으로 간편하게 코딩을 할 수 있다는 것을 알 수 있게 되었다.

함수에 익숙하지 않으면 평소에 내가 익숙한 함수로만 코딩을 하기 때문에 이 고차 함수에 익숙해질 수 있도록 이 고차 함수 및 형변환 함수들은 외워놔야 될 필요성을 느꼈다!

✍️ 주요 학습 내용

배운 내용

  • 함수형 프로그래밍
  • 순수 함수
  • 형변환 함수
  • 고차 함수

새로 알게된 개념

함수형 프로그래밍
  • 함수 의 연속으로 프로그램을 구성하는 방식
    • 함수 의 연속 ?
      • 메서드 체이닝 (Method Chaining) 이라고도 불러요.
      • 메서드 체이닝 (Method Chaining) ? 🤔
        • 어떤 친구인가요 ?
          • . 을 사용해서 여러 개의 함수를 하나로 연결하는 방식
        • 예시 코드가 궁금해요 👀
          int number = -12345
          var result = number.abs().toString().contains('3');
          print(result); // true
          String word = 'abcd';
          var index = word.toUpperCase().indexOf('B');
          print(index); // 1
  • 순수 함수
    • 출력값이 항상 함수의 매개변수에만 의존하는 함수
    • 함수 밖에 있는 변수를 사용하지 않는 함수
    • 값은 값을 입력하면 항상 같은 값이 나오기 때문에 예상하지 못했던 상황이 생길 일이 적어짐
  • method
    • toUpperCase() : 대문자 바꿔주는 것
    • toLowerCase() : 소문자로 바꿔주는 것
    • abs() : 절대값 출력
    • indexOf() : 해당값의 인덱스 출력
    • contains() : 해당 값을 포함하고 있는지 알려줌
형 변환 함수
  • toString() : 문자열로 만들어 줌
  • int.parse(문자열) : 문자열을 int 로 바꿔줌
  • double.parse(문자열) : 문자열을 double 형태로 바꿔줌
  • toList() : Collection 타입의 값을 List 타입으로 변환한 값을 반환해 줌
    Set<String> fruitSet = {'사과', '오렌지', '수박'};
    var fruitList = fruitSet.toList();
    print(fruitList); // [사과, 오렌지, 수박]
    print(fruitList.runtimeType); // List<String>
    • Map 타입에는 toList() 를 사용할 수 없음
  • toSet() : 특정 Collection 타입의 값을 Set 타입으로 변환한 값을 반환해요.
    • Set 은 중복값을 허용하지 않기 때문에 Collection 값에 중복된 값을 제외한 Set 을 반환함
    • Map 에는 사용할 수 없음
  • asMap() : 특정 Collection 타입의 값을 Map 타입으로 변환한 값을 반환해요.
    • List 의 인덱스를 키 값으로 List 의 값을 값으로 할당해 줌
    • Map 의 값은 중복이 되기 때문에 중복값 적용 가능!
    • Setindex 가 없기 때문에 Set 에는 적용하지 못함
    • Set 에서 toList()List 로 바꿔준 후에 asMap() 으로 Map 형태로 바꿔줄 수 있음
고차 함수(Higher-order Function)
  • Collection 타입의 데이터에 있는 요소를 처리하거나 변환할 때 사용해요.
  • 고차함수에 대해서는 익숙하지 않아서 이것은 암기해서 앞으로 필요한 상황이 있을 때 사용하면 좋을 것 같음
  • 나만의 정리!
    • map()Collection 에 어떤 작업을 해서 새로운 Collection 을 얻고자 할 때
    • where()Collection 에서 원하는 조건에 해당하는 새로운 Collection 을 얻고자 할 때
    • firstWhere() , lastWhere() 은 원하는 조건의 값 1개를 얻고자 할 때. 하지만 값이 없으면 에러가 나오니 조심
    • reduce()Collection 에 있는 전체 요소를 가지고 뭔가를 할 때. 예를 들면 전체 요소의 합을 구한다든지 할 때 쓰면 좋을 것 같음,
      • Collection 에 데이터가 없으면 에러 발생하니 조심
      • 다른 형태로 반환 불가능
    • fold() reduce() 와는 다르게 초기값을 설정해 주고 모든 요소들과 특정 동작을 수행할 수 있게 함
      • 초기값을 설정해 주니 데이터가 없어도 에러 발생하지 않음
      • 다른 형태로 반환 가능
    • any() : Collection 에 특정 조건을 해당하는 값이 있는지 확인할 때
    • every() : Collection 의 모든 요소가 특정 조건을 충족하는지 확인할 때
    • takeWhile() 조건에 부합하지 않는 첫 요소가 나올 때까지의 요소를 반환
    • skipWhile() : 조건에 부합하지 않는 첫 요소가 나올 때부터의 요소를 반환

종류

  • map()

    • 어떤 친구인가요 ?

      • Collection 타입인 데이터의 각 요소에 특정 함수를 적용한 새로운 Collection 타입의 데이터를 반환해요.
    • 어떻게 생겼나요 ?

      • map(([매개변수]) { return [매개변수에 적용할 동작] });

        List<String> fruitList = ['사과', '오렌지', '수박'];
        var delicious = fruitList.map((fruit) {
        var word = '맛있는 ';
        word += fruit;
        return word;
        });
        print(delicious); // (맛있는 사과, 맛있는 오렌지, 맛있는 수박)
        List<String> fruitList = ['사과', '오렌지', '수박'];
        var delicious = fruitList.map((fruit) {
        return '맛있는 $fruit';
        });
        print(delicious); // (맛있는 사과, 맛있는 오렌지, 맛있는 수박)
        List<int> numbers = [1, 2, 3, 4, 5];
        var doubledNumbers = numbers.map((n) {
        return n * 2;
        });
        print(doubledNumbers); // (2, 4, 6, 8, 10)
        Set<String> carSet = {'BMW', '현대', '기아'};
        var goodCar = carSet.map((car) {
        return '짱 멋진 $car';
        });
        print(goodCar); // (짱 멋진 BMW, 짱 멋진 현대, 짱 멋진 기아)
        Map<String, int> fruits = {'사과': 5, '포도': 2, '귤': 3};

        var delicious = fruits.keys.map((fruit) {
        return '맛있는 $fruit';
        });
        print(delicious); // (맛있는 사과, 맛있는 포도, 맛있는 귤)

        var numbers = fruits.values.map((number) {
        return '$number개';
        });
        print(numbers); // (5개, 2개, 3개)
      • map(([매개변수]) => [매개변수에 적용할 동작] );

        • 매개변수에 적용할 동작을 한줄로 표현 가능한 경우에만 사용할 수 있어요.
          List<int> numbers = [1, 2, 3, 4, 5];
          var doubledNumbers = numbers.map((n) => n * 2);
          print(doubledNumbers); // (2, 4, 6, 8, 10)
          List<String> fruits = ['사과', '오렌지', '수박'];
          var delicious = fruits.map((fruit) => '맛있는 $fruit');
          print(delicious); // (맛있는 사과, 맛있는 오렌지, 맛있는 수박)
    • 어떤 특징이 있나요 ?

      • 원본 데이터를 직접 가공하지 않고, 특정 함수를 적용한 새로운 데이터를 반환해요.
        List<String> alphabets = ['A', 'B', 'C', 'D'];
        var lowercasedAlphabets = alphabets.map((alphabet) {
        return alphabet.toLowerCase()
        });
        print(lowercasedAlphabets); // (a, b, c, d)
        print(alphabets); // [A, B, C, D]
      • 원본 데이터와 크기가 같은 데이터를 반환해요.
        List<String> alphabets = ['a', 'b', 'c', 'd'];
        final uppercasedAlphabets = alphabets.map((alphabet) {
        return alphabet.toUpperCase()
        });
        print(alphabets); // [A, B, C, D]
        print(alphabets.length); // 4
        print(uppercasedAlphabets); // (A, B, C, D)
        print(uppercasedAlphabets.length); // 4
  • where()

    • 어떤 친구인가요 ?
      • Collection 타입의 데이터에 있는 각 요소들을 특정 조건에 넣었을 때 참인 요소들만 필터링한 새로운 Collection 타입의 데이터를 반환해요.
    • 어떻게 생겼나요 ?
      • where(([매개변수]) { return [조건식] });
        List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var result = numbers.where((number) {
        return number > 5;
        });
        print(result); // (6, 7, 8, 9, 10)
        List<String> fruits = ['사과', '오렌지', '수박'];
        var result = fruits.where((fruit) {
        return fruit.length == 2;
        });
        print(result); // (사과, 수박)
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.where((number) {
        return number.isEven
        });
        print(result); // (2, 4, 6)
      • where(([매개변수]) => [조건식] );
        • 매개변수에 적용할 동작을 한줄로 표현 가능한 경우에만 사용할 수 있어요.
          List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
          var result = numbers.where((n) => n > 5);
          print(result); // (6, 7, 8, 9, 10)
          List<String> fruits = ['사과', '오렌지', '수박'];
          var result = fruits.where((f) => f.length == 2);
          print(result); // (사과, 수박)
          List<int> numbers = [1, 2, 3, 4, 5, 6];
          var result = numbers.where((n) => n.isEven);
          print(result); // (2, 4, 6)
    • 어떤 특징이 있나요 ?
      • 원본 데이터를 직접 가공하지 않고, 특정 함수를 적용한 새로운 데이터를 반환해요.
        List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var result = numbers.where((number) {
        return number > 5
        });
        print(result); // (6, 7, 8, 9, 10)
        print(numbers); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
        List<String> fruits = ['사과', '오렌지', '수박'];
        var filteredFruits = fruits.where((fruit) {
        return fruit.length == 2
        });
        print(filteredFruits); // (사과, 수박)
        print(fruits); // ['사과', '오렌지', '수박']
      • 조건식이 참인 요소가 없는 경우에는 빈 값을 반환해요.
        List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var result = numbers.where((number) {
        return number > 10;
        });
        print(result); // ()
  • firstWhere()

    • 어떤 친구인가요 ?
      • Collection 타입의 데이터에 있는 각 요소들을 특정 조건에 넣었을 때 참인 요소들 중 첫번째 요소를 반환해요.
    • 어떻게 생겼나요 ?
      • firstWhere(([매개변수]) { return [조건식] });
        List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var result = numbers.firstWhere((number) {
        return number > 5;
        });
        print(result); // 6
        List<String> fruits = ['사과', '오렌지', '수박'];
        var result = fruits.firstWhere((fruit) {
        return fruit.length == 2;
        });
        print(result); // 사과
      • firstWhere(([매개변수]) => [조건식] );
        • 매개변수에 적용할 동작을 한줄로 표현 가능한 경우에만 사용할 수 있어요.
          List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
          var result = numbers.firstWhere((n) => n > 5);
          print(result); // 6
          List<String> fruits = ['사과', '오렌지', '수박'];
          var result = fruits.firstWhere((f) => f.length == 2);
          print(result); // 사과
    • 어떤 특징이 있나요 ?
      • 원본 데이터를 직접 가공하지 않고, 특정 함수를 적용한 새로운 데이터를 반환해요.
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.firstWhere((number) => number > 2);
        print(result); // 3
        print(numbers); // [1, 2, 3, 4, 5]
      • 조건식이 참인 요소가 없는 경우에는 오류가 발생해요 🚨
        List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var result = numbers.firstWhere((number) {
        return number > 10;
        });
        print(result); // StateError
  • lastWhere()

    • 어떤 친구인가요 ?
      • Collection 타입의 데이터에 있는 각 요소들을 특정 조건에 넣었을 때 참인 요소들 중 마지막 요소를 반환해요.
    • 어떻게 생겼나요 ?
      • lastWhere(([매개변수]) { return [조건식] });
        List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var result = numbers.lastWhere((number) {
        return number > 5;
        });
        print(result); // 10
        List<String> fruits = ['사과', '오렌지', '수박'];
        var result = fruits.lastWhere((fruit) {
        return fruit.length == 2;
        });
        print(result); // 수박
      • lastWhere(([매개변수]) => [조건식] );
        • 매개변수에 적용할 동작을 한줄로 표현 가능한 경우에만 사용할 수 있어요.
          List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
          var result = numbers.firstWhere((n) => n > 5);
          print(result); // 6
          List<String> fruits = ['사과', '오렌지', '수박'];
          var result = fruits.firstWhere((f) => f.length == 2);
          print(result); // 사과
    • 어떤 특징이 있나요 ?
      • 원본 데이터를 직접 가공하지 않고, 특정 함수를 적용한 새로운 데이터를 반환해요.
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.lastWhere((number) => number > 2);
        print(result); // 5
        print(numbers); // [1, 2, 3, 4, 5]
      • 조건식이 참인 요소가 없는 경우에는 오류가 발생해요 🚨
        List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        var result = numbers.lastWhere((number) {
        return number > 10;
        });
        print(result); // StateError
  • reduce()

    • 어떤 친구인가요 ?

      • Collection 타입의 데이터에 있는 요소들을 하나의 값으로 결합해요.
    • 어떻게 생겼나요 ?

      • reduce(([매개변수1], [매개변수2]) { return [적용할 동작] });
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.reduce((a, b) {
        return a + b;
        });
        List<int> numbers = [1, 2, 3, 4];
        var result = numbers.reduce((a, b) {
        return a * b;
        });
        List<String> words = ['다트는 ', '참 ', '재미있군 ?'];
        var result = words.reduce((a, b) {
        return a + b;
        });
      • reduce(([매개변수1], [매개변수2]) => [적용할 동작] );
        • 매개변수에 적용할 동작을 한줄로 표현 가능한 경우에만 사용할 수 있어요.
          List<int> numbers = [1, 2, 3, 4, 5];
          var result = numbers.reduce((a, b) => a + b);
          List<int> numbers = [1, 2, 3, 4];
          var result = numbers.reduce((a, b) => a * b);
          List<String> words = ['다트는 ', '참 ', '재미있군 ?'];
          var result = words.reduce((a, b) => a + b);
    • 어떻게 실행되나요 ?

      • 매개변수1 에는 이전 실행에서 반환된 값 (첫번째 실행에서는 이전 실행이 없기 때문에 Collection 타입의 데이터에 있는 첫번째 값) 이 할당되고, 매개변수2 에는 Collection 타입의 데이터에 있는 다음 값이 할당돼요.

        List<int> numbers = [1, 2, 3, 4, 5];
        int result = numbers.reduce((a, b) {
        print('a : $a');
        print('b : $b');
        print('a + b : ${a + b}');
        print('----------------------');
        return a + b;
        });
        print('result : $result');

        /*
        a : 1
        b : 2
        a + b : 3
        ----------------------
        a : 3
        b : 3
        a + b : 6
        ----------------------
        a : 6
        b : 4
        a + b : 10
        ----------------------
        a : 10
        b : 5
        a + b : 15
        ----------------------
        result : 15
        */
        List<int> numbers = [1, 2, 3, 4];
        int result = numbers.reduce((a, b) {
        print('a : $a');
        print('b : $b');
        print('a * b : ${a * b}');
        print('----------------------');
        return a * b;
        });
        print('result : $result');

        /*
        a : 1
        b : 2
        a * b : 2
        ----------------------
        a : 2
        b : 3
        a * b : 6
        ----------------------
        a : 6
        b : 4
        a * b : 24
        ----------------------
        result : 24
        */
        List<String> words = ['다트는 ', '참 ', '재미있군 ?'];
        int result = words.reduce((a, b) {
        print('a : $a');
        print('b : $b');
        print('a + b : ${a + b}');
        print('----------------------');
        return a + b;
        });
        print('result : $result');

        /*
        a : 다트는
        b : 참
        a + b : 다트는 참
        ----------------------
        a : 다트는 참
        b : 재미있군 ?
        a + b : 다트는 참 재미있군 ?
        ----------------------
        result : 다트는 참 재미있군 ?
        */
    • 어떤 특징이 있나요 ?

      • Collection 타입의 데이터와 같은 타입으로만 반환할 수 있어요.
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.reduce((a, b) => '$a' + '$b');
        // Error: A value of type 'String' can't be returned from a function with return type 'int'.
      • Collection 타입의 데이터에 요소가 없는 경우에는 오류가 발생해요 🚨
        List<int> list = [];
        var result = list.reduce((a, b) => a + b); // StateError
  • fold()

    • 어떤 친구인가요 ?

      • Collection 타입의 데이터에 있는 요소들을 하나의 값으로 결합해요.
      • 오잉 ? 그럼 reduce() 랑 같은건가요 ? 🤔
        • 이거는 fold() 에 대해 다 배우고 나서 알려 드릴게요 !
    • 어떻게 생겼나요 ?

      • fold(초기값, ([매개변수1], [매개변수2]) { return [적용할 동작] });
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.fold(0, (a, b) {
        return a + b
        });
        List<int> numbers = [1, 2, 3, 4];
        var result = numbers.fold(1, (a, b) {
        return a * b;
        });
        List<String> words = ['다트는 ', '참 ', '재미있군 ?'];
        var result = words.fold('앗, ', (a, b) {
        return a + b;
        });
      • fold(초기값, ([매개변수1], [매개변수2]) => [적용할 동작] );
        • 매개변수에 적용할 동작을 한줄로 표현 가능한 경우에만 사용할 수 있어요.
          List<int> numbers = [1, 2, 3, 4, 5];
          var result = numbers.fold(0, (a, b) => a + b);
          List<int> numbers = [1, 2, 3, 4];
          var result = numbers.fold(1, (a, b) => a * b);
          List<String> words = ['다트는 ', '참 ', '재미있군 ?'];
          var result = words.fold('앗, ', (a, b) => a + b);
    • 어떻게 실행되나요 ?

      • 매개변수1 에는 이전 실행에서 반환된 값 (첫번째 실행에서는 초기값) 이 할당되고, 매개변수2 에는 Collection 타입의 데이터에 있는 다음 값이 할당돼요.

        List<int> numbers = [1, 2, 3, 4, 5];
        int result = numbers.fold(0, (a, b) {
        print('a : $a');
        print('b : $b');
        print('a + b : ${a + b}');
        print('----------------------');
        return a + b;
        });
        print('result : $result');

        /*
        a : 0
        b : 1
        a + b : 1
        ----------------------
        a : 1
        b : 2
        a + b : 3
        ----------------------
        a : 3
        b : 3
        a + b : 6
        ----------------------
        a : 6
        b : 4
        a + b : 10
        ----------------------
        a : 10
        b : 5
        a + b : 15
        ----------------------
        result : 15
        */
        List<int> numbers = [1, 2, 3, 4];
        int result = numbers.fold(1, (a, b) {
        print('a : $a');
        print('b : $b');
        print('a * b : ${a * b}');
        print('----------------------');
        return a * b;
        });
        print('result : $result');

        /*
        a : 1
        b : 1
        a * b : 1
        ----------------------
        a : 1
        b : 2
        a * b : 2
        ----------------------
        a : 2
        b : 3
        a * b : 6
        ----------------------
        a : 6
        b : 4
        a * b : 24
        ----------------------
        result : 24
        */
        List<String> words = ['다트는 ', '참 ', '재미있군 ?'];
        int result = words.fold('앗, ', (a, b) {
        print('a : $a');
        print('b : $b');
        print('a + b : ${a + b}');
        print('----------------------');
        return a + b;
        });
        print('result : $result');

        /*
        a : 앗,
        b : 다트는
        a + b : 앗, 다트는
        ----------------------
        a : 앗, 다트는
        b : 참
        a + b : 앗, 다트는 참
        ----------------------
        a : 앗, 다트는 참
        b : 재미있군 ?
        a + b : 앗, 다트는 참 재미있군 ?
        ----------------------
        result : 앗, 다트는 참 재미있군 ?
        */
    • 어떤 특징이 있나요 ?

      • Collection 타입의 데이터와 다른 타입으로도 반환이 가능해요.

        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.fold('', (a, b) => '$a' + '$b');
        print(result); // 12345
        print(result.runtimeType); // String
        List<String> words = ['다트는 ', '참 ', '재미있군 ?'];
        int result = words.fold(0, (a, b) {
        print('a : $a');
        print('b : $b');
        print('b length : ${b.length}');
        print('---------------');
        return a + b.length;
        });
        print('총 글자 수 : $result');

        /*
        a : 0
        b : 다트는
        b length : 4
        ---------------
        a : 4
        b : 참
        b length : 2
        ---------------
        a : 6
        b : 재미있군 ?
        b length : 6
        ---------------
        총 글자 수 : 12
        */
      • Collection 타입의 데이터에 요소가 없어도 오류가 발생하지 않아요.

        List<int> list = [];
        var result = list.fold(0, (a, b) => a + b);
        print(result); // 0
    • 자 - 이제 아까 그냥 넘어갔던 것 짚고 넘어갑시다 🧐

      • reduce()fold() 는 뭐가 다른지 이제 아시겠죠 ?
        reduce()fold()
        초기값Collection 데이터의 첫번째 요소첫번째 매개변수에 넣어준 값
        Collection 사용 가능 여부XO
        타입 유연성 여부
        (Collection 의 요소 타입과
        반환 타입이 달라도 되는지)XO
  • any()

    • 어떤 친구인가요 ?
      • Collection 타입의 데이터에 있는 요소 중 하나라도 주어진 조건을 만족하면 true 를 반환해요.
    • 어떻게 생겼나요 ?
      • any(([매개변수]) { return [조건식] });
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.any((number) {
        return number.isEven;
        });
        print(result); // true
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.any((number) {
        return number > 10;
        });
        print(result); // false
      • any(([매개변수]) => [조건식] );
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.any((n) => n.isEven);
        print(result); // true
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.any((number) => number > 10);
        print(result); // false
  • every()

    • 어떤 친구인가요 ?
      • Collection 타입의 데이터에 있는 모든 요소가 주어진 조건을 만족하면 true 를 반환해요.
    • 어떻게 생겼나요 ?
      • every(([매개변수]) { return [조건식] });
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.every((number) {
        return number > 0;
        });
        print(result); // true
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.every((number) {
        return number.isEven;
        });
        print(result); // false
      • every(([매개변수]) => [조건식] );
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.any((number) => number > 0);
        print(result); // true
        List<int> numbers = [1, 2, 3, 4, 5];
        var result = numbers.every((n) => n.isEven);
        print(result); // false
  • takeWhile()

    • 어떤 친구인가요 ?
      • Collection 타입의 데이터에 있는 요소들을 주어진 조건에 넣었을 때 참이 되는 동안은 해당 요소들을 반환하고, 조건이 처음으로 거짓이 되는 순간부터의 요소들은 모두 무시해요.
    • 어떻게 생겼나요 ?
      • takeWhile(([매개변수]) { return [조건식] });
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.takeWhile((number) {
        return number < 4;
        });
        print(result); // (1, 2, 3)
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.takeWhile((number) {
        return number.isOdd;
        });
        print(result); // (1)
      • takeWhile(([매개변수]) => [조건식] );
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.takeWhile((number) => number < 4);
        print(result); // (1, 2, 3)
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.takeWhile((number) => number.isOdd);
        print(result); // (1)
  • skipWhile()

    • 어떤 친구인가요 ?
      • Collection 타입의 데이터에 있는 요소들을 주어진 조건에 넣었을 때 참이 되는 동안은 해당 요소들을 건너뛰고, 조건이 처음으로 거짓이 되는 순간부터의 요소들을 모두 반환해요.
    • 어떻게 생겼나요 ?
      • skipWhile(([매개변수]) { return [조건식] });
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.skipWhile((number) {
        return number < 4;
        });
        print(result); // (4, 5, 6)
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.skipWhile((number) {
        return number.isOdd;
        });
        print(result); // (2, 3, 4, 5, 6)
      • takeWhile(([매개변수]) => [조건식] );
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.takeWhile((number) => number < 4);
        print(result); // (4, 5, 6)
        List<int> numbers = [1, 2, 3, 4, 5, 6];
        var result = numbers.takeWhile((number) => number.isOdd);
        print(result); // (2, 3, 4, 5, 6)

  • 실습한 내용
고차함수 실습
  • map() + where()

    • List 에 있는 숫자들 각각에 2 를 곱한 후 5 보다 큰 값들을 반환하고 싶다면 ?

      List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var doubledNumbers = numbers.map((number) => number * 2);
      var result = doubledNumbers.where((number) => number > 5);
      print(result); // (6, 8, 10, 12, 14, 16, 18, 20)

      List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var result = numbers
      .map((number) => number * 2)
      .where((number) => number > 5);
      print(result); // (6, 8, 10, 12, 14, 16, 18, 20)
    • List 에 있는 숫자들 중 짝수들만 골라낸 후 각각을 제곱한 값들의 합을 반환하고 싶다면 ?

      List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var evenNumbers = numbers.where((number) => number.isEven);
      var squaredNumbers = evenNumbers.map((number) => number * number);
      var sumOfSquares = squaredNumbers.reduce((a, b) => a + b);
      print(sumOfSquares); // 220

      List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var sumOfSquares = numbers
      .where((number) => number.isEven)
      .map((number) => number * number)
      .reduce((a, b) => a + b);
      print(sumOfSquares); // 220
    • List 에 있는 문자열들 중 글자가 5개보다 많은 문자열들만 골라낸 후 모든 글자를 대문자로 바꿔서 반환하고 싶다면 ? dart List<String> words = ['apple', 'orange', 'watermelon', 'pineapple']; var longerThanFiveWords = words.where((word) => word.length > 5); var result = longerThanFiveWords.map((word) => word.toUpperCase()); print(result); // (ORANGE, WATERMELON, PINEAPPLE)

      List<String> words = ['apple', 'orange', 'watermelon', 'pineapple'];
      var upperCasedWords = words
      .where((word) => word.length > 5)
      .map((word) => word.toUpperCase());
      print(upperCasedWords); // (ORANGE, WATERMELON, PINEAPPLE)
  • where() + reduce()

    • List 에 있는 숫자들 중 짝수들만 골라낸 후 그 숫자들을 모두 더한 값을 반환하고 싶다면 ?

      List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var evenNumbers = numbers.where((number) => number.isEven);
      var result = evenNumbers.reduce((a, b) => a + b);
      print(result); // 30

      List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var result = numbers
      .where((number) => number % 2 == 0)
      .reduce((a, b) => a + b);
      print(result); // 30
    • List 에 있는 숫자들 중 5 보다 작은 숫자들만 골라낸 후 그 숫자들을 모두 곱한 값을 반환하고 싶다면 ? dart List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; var smallerThanFive = numbers.where((number) => number < 5); var result = smallerThanFive.reduce((a, b) => a * b); print(result); // 24

      List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
      var result = numbers
      .where((number) => number < 5)
      .reduce((a, b) => a * b);
      print(result); // 24
  • where() + map() + fold()

    • List 에 있는 숫자들 중 양수들만 골라낸 후 그 숫자들 각각에 10 을 더한 숫자들을 모두 더한 값을 반환하고 싶은 경우 dart List<int> numbers = [-10, 20, -30, 40, 50]; var positiveNumbers = numbers..where((number) => number > 0); var plusTenNumbers = positiveNumbers.map((number) => number + 10); var result = plusTenNumbers.fold(0, (a, b) => a + b); print(result); // 140

      List<int> numbers = [-10, 20, -30, 40, 50];
      var result = numbers
      .where((number) => number > 0)
      .map((number) => number + 10)
      .fold(0, (a, b) => a + b);
      print(result); // 140

🚨 발생한 문제/에러

없었음.

📝 코드 스니펫

// 오늘 배운 주요 코드
List<int> numbers = [1,2,3,4,5];
int result = numbers.fold(0, (a,b){
return a + b;
}

📚 내일 학습할 내용

  • 예외 처리
  • 라이브러리 이용
  • 비동기 프로그래밍

💭 오늘의 회고

잘한 점 👍

  • 고차 함수 부분에서 빡집중함

개선할 점 🔨

  • 하루 계획과 목표를 구체적으로 세우고 시작하면 좋을 것 같음

배운 점 💡

  • map() 등 고차 함수 꿀 기능인듯.

✏️ 참고 자료

다트 심화 문법 익히기

· 10 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

👨‍💻 오늘의 코딩!

문제

정수 배열 nums와 정수 target이 주어질 때, 두 수를 더해서 target이 되는 배열 내 두 숫자의 인덱스를 반환하세요.

같은 요소를 두 번 사용할 수 없습니다. 답은 반드시 하나만 존재한다고 가정합니다.

다트 기초 문법 익히기

· 11 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

오늘은 dart에 대한 기초 문법을 공부했다. 기본적으로 익숙한 내용들이 있었지만 javascript 에는 없는 ? null handling 이런 개념들에게 대해서 확실히 정리할 수 있었다. 그리고 컴파일러 개념 등에 대해서도 확실히 알게 되었다.

플러터 상태관리

· 5 min read
Junseok Yang
Football Loving Programmer

📚 오늘의 학습 내용

오늘은 플러터 상태관리에 대해서 공부를 했다. vue에서도 state를 통해서 state 내의 값이 바뀌었을 때 바로바로 웹사이트에 뿌려줄 수 있었는데 그것과 개념이 비슷해서 화면에서 특정 값이 바뀌었을 때 그것을 실시간으로 보여주고 또 전체화면을 다시 빌드해서 보여주면 메모리가 많이 사용되기 때문에 바뀌는 부분만 다시 빌드할 수 있도록 GetX라는 Third Party Library를 사용하는 것을 배우게 되었다.

✍️ 주요 학습 내용

  • 배운 내용
    • 상태관리에 대해서 배웠는데 기본적으로 화면 내의 어떤 값이 바뀔 때 내부적으로는 바뀐 값을 저장하고 있지만 그 값을 화면에 뿌려주지 않기 때문에 내부적으로는 값이 바뀌어도 화면은 전혀 바뀌지 않는 것을 볼 수 있다.
    • 그렇기 때문에 앱에게 값이 바뀌었다는 것을 알리고 화면을 다시 띄울 수 있게 하는 게 필요하고 이것이 상태관리인 것 같다.
    • 처음에 StatefulWidgetStatelessWidget 을 배우는데 StatelessWidget 은 중간에 값이 바뀌지 않기 때문에 동일한 화면을 보여주면 되는데 StatefulWidget 은 중간의 어떤 값이 바뀌기 때문에 바뀐 값을 화면에 보여주기 위해서 빌드를 다시 하게 된다.
    • StatefulWidget 의 생애주기 StatefulWidget Lifecycle
    • 이것은 StatefulWidget의 생애주기인데 빌드라는 것을 해야 화면을 다시 띄우게 된다. 그렇기 때문에 변경된 값을 보여주기 위해서는 setState() 혹은 didUpdateWidget() 을 사용해서 빌드를 진행해 줘야 한다.
    • StatefulWidget 의 한계
      • flutter 는 위젯 트리라고 해서 위젯 간의 계층 구조가 있는데 가장 하위의 위젯에서 어떤 값을 변경하게 되면 그 변경된 값을 StatefulWidget 에게 까지 전달을 해줘야 되고 그 값을 또 나타내 주기 위해서 그 값을 보여주는 위젯까지 변경된 값을 전달해줘야 하는데 그렇기 때문에 이런 상태 공유가 어렵고 비효율적으로 된다.
    • 따라서 이러한 한계점들을 해결하기 위해서 다양한 써드 파티 라이브러리를 이용하게 되는데 대표적으로 4가지가 있다고 한다.
      • Provider
      • GetX
      • Bloc/Cubit
      • Riverpod
    • 하지만 여기서 우리는 GetX를 사용하기로 했고 GetX 를 통해서 상태에 변경이 생기면 흔히 Controller 라고 불리는 중앙 집중 상태에 바로 변경된 값을 알려주고 그 값을 뿌려줘야 하는 위젯에 바로 보낼 수 있어서 간편하게 상태관리를 할 수 있게 되었다.
  • 새로 알게된 개념
    • 상태관리의 개념
    • StatefulWidget 의 한계점
    • GetX 의 존재?
  • 실습한 내용
    • 단어 장바구니 앱 실습

🚨 발생한 문제/에러

  • 따로 발견한 문제/에러는 없었다.

📝 코드 스니펫

// 오늘 배운 주요 코드
import 'package:get/get.dart';

class ProductController extends GetxController {}

📚 내일 학습할 내용

  • 오늘 밤 중으로 5주차까지 강의를 다 듣고 개인과제를 제출할 예정!

💭 오늘의 회고

잘한 점 👍

  • 강의를 많이 듣지는 못했지만 그래도 위젯 및 상태관리에 대해서 익숙해지고 깊이 이해해 가는 것 같다.

개선할 점 🔨

  • 온라인으로 진행되다 보니 조금 더 시간관리를 잘해야 될 것 같다.

배운 점 💡

  • State Management
  • StatefulWidget의 한계
  • Third Party Library : GetX

✏️ 참고 자료