정보

    • 업무명     : [Flutter] 쉽게 배우는 플러터 앱 개발 실무 03강
    • 작성자     : 이상호
    • 작성일     : 2024.12.28
    • 설   명      :
    • 수정이력 :

     

     pubspec.yaml과 Pub 사이트

    [학습목표]

    • 외부에서 제공하는 라이브러리를 사용하기 위하여 pubspec.yaml 파일의 설정법을 알아봅니다

     

    [pubspec.yaml과 Pub 사이트]

    • Image를 자원(assets)으로 사용하기 위해 pubspec.yaml 파일을 사용했던 것처럼 Flutter의 외부 라이브러리 혹은 패키지를 사용하기 위해서도 pubspec.yaml 파일을 사용하는데 이전에는 스쳐지나갔던 pubspec.yaml에 대하여 조금 더 알아 보도록 합시다.

     

     

    • Java Spring 진영에 Maven Central 사이트가 있는 것처럼

     

    Maven Central (Gradle에서도 사용 가능)

     

    Maven Central Repository Search

     

    search.maven.org

     

    • 설명: Maven과 Gradle 프로젝트에서 가장 널리 사용되는 라이브러리 저장소입니다. Maven Central은 다양한 라이브러리를 쉽게 검색하고 추가할 수 있도록 지원합니다.
    • Flutter에는 Pub 사이트가 있어서 제공되는 패키지들에 대한 정보를 제공합니다. 우리는 찾아서 사용하면 됩니다.

     

    Flutter의 Pub 사이트 (pub.dev)

     

    The official repository for Dart and Flutter packages.

    Pub is the package manager for the Dart programming language, containing reusable libraries & packages for Flutter and general Dart programs.

    pub.dev

     

    • 설명: Flutter 및 Dart 패키지에 대한 중앙 저장소입니다. Flutter 개발자가 패키지를 관리하고 검색할 수 있는 사이트입니다.
    • 사용법: pubspec.yaml 파일에서 패키지를 정의하고, pub get 명령을 사용해 패키지를 다운로드합니다.
    • 아래와 같이 webview_flutter: 4.4.1 패키지를 pubspec.yaml에 등록 후 Pub Get하면 패키지를 가져다 사용할 수 있습니다.

     

    // Webview를 사용하기 위하여 import
    import 'package:webview_flutter/webview_flutter.dart';

     

    Fonts를 지정하여 사용하는 방법

    • 폰트 파일을 저장할 fonts 폴더를 만듭니다.

     

    • 파일 탐색기에서 사용할 수 있는 폰트를 확인합니다.

     

    • 일부 폰트의 경우에는 폰트 파일에서 마우스 우측 클릭을 한 후 속성을 HMFMPYUN.TTF와 같은 이름을 보고 폰트 파일의 이름을 알 수 있습니다. 그런 경우 파일 탐색기에서 폰트를 Drag하여 안드로이드 스튜디오의 fonts 폴더에 Drop합니다.

     

     

    • 파일 탐색기에서 폰트 파일의 이름을 확인하기 어려운 경우 Windows 명령어를 사용하여 폰트 파일 이름을 확인한 후 windows 명령어를 사용하여 복사합니다.
    C:\>cd c:\windows\fonts
    
    C:\Windows\Fonts>dir
    
    C:\Windows\Fonts>dir malgun*
    
    C:\Windows\Fonts>copy malgun*.ttf C:\Users\USER\StudioProjects\gesture_widgets\fonts

     

    • 폰트 파일을 복사해 온 후의 폴더의 형태는 아래 화면과 같습니다.

     

    • pubspec.yaml에 복사한 Font를 등록한 후 Pub get 명령어를 수행합니다.
    fonts:
        - family: Hmfmpyun
          fonts:
            - asset: fonts/HMFMPYUN.TTF
              weight: 700
        - family: MalgunGothic
          fonts:
            - asset: fonts/malgun.ttf
            - asset: fonts/malgunbd.ttf
              weight: 700

     

    • pubspec.yaml에 등록된 Font의 이름을 가져다 사용합니다.
      Text(
        "맑은 고딕",
        style: TextStyle(
          fontSize: 40,
          fontFamily: 'MalgunGothic',
        ),
      ),
      Text(
        "휴면 편지체",
        style: TextStyle(
          fontSize: 40,
          fontFamily: 'MalgunGothic',
        ),
      ),

     

    [실습] 자신의 가족을 소개하는 family_intro 앱을 개발하세요.

    • family_intro 프로젝트를 만들어 작업하시기 바랍니다.
    • 지금까지 배운 것들을 기반으로 자신의 가족을 소개하는 하나의 화면으로 구성된 앱을 개발하기 바랍니다.
    • 필수적으로 사용해야 할 Widget : Scaffold, Text, Image, Container, Column, Row, Stack, Positioned
    • 디자인 기준 : 팀 구성원들의 이미지를 모두 추가, Children 3개인 Row와 Children 2개를 포함하는 Row를 모두 사용, 팀 고유의 배경 색상, 한글 Font 사용
    • Instructor Note : family_intro 앱의 실행 화면을 스마트폰에서 팀즈로 화면을 공유하여 수강생들에게 보여 줄 것

     

    코드 팩토리의 플러터 프로그래밍 - 8장 블로그 웹 앱 (194페이지)

    • 프로젝트 이름 : blog_web_app
    • 설명 : https://blog.codefactory.ai 주소를 가진 블로그를 Web View에 보여 준 후 링크를 클릭하며 사용하다가 AppBar의 홈 버튼을 누르면 다시 https://blog.codefactory.ai 주소로 돌아 옵니다.

     

    • webview_flutter: 4.4.1 패키지를 pubspec.yaml에 등록 후 Pub Get

     

    코드 팩토리의 플러터 프로그래밍 - 9장 전자액자 (218페이지)

    • 프로젝트 이름 : image_carousel
    • 설명 : PageView Widget을 사용하면 스와이프를 통한 화면 전환이 이루어집니다. 특정 시간이 지나면 화면이 자동으로 전환되는 기능을 Timer 객체를 사용하여 구현합니다.

     

     

     

     Dart 언어 II

    [학습목표]

    • Python, Java, Javascript로 배운 프로그래밍의 기본 원리와 개념과 의미를 기억해 봅니다.
    • 이미 알고 있는 프로그래밍 지식을 확장하여 Dart 언어를 이해합니다.

     

    [Dart 언어의 기초 II]

    컬렉션 자료형

    • 컬렉션(Collection)은 여러 값을 하나의 변수에 저장할 수 있는 자료형입니다. List와 같이 여러 값을 순서대로 저장하거나, Map과 같이 특정 키값을 기반으로 빠르게 값을 검색해야 하거나, Set과 같이 중복된 데이터를 제거할 때 주로 사용됩니다.
    • 아래 코드와 같이 변수명을 디지핑과 같이 한글로 만들면 오류를 유발하는 경우가 많습니다. → 곧 수정해 놓겠습니다. 변수명을 영문으로 변환하여 이해바랍니다.

     

    • 리스트(List)는 값이 여러개이기 때문에 대괄호([])사이에 첨자(인덱스,Index)를 사용하여 값을 조회하는데 이때 첫번째 값의 인덱스는 0이 되고, 전체 길이는 변수명.length와 같은 형식으로 알아 볼 수 있습니다.

     

     

     

     

     

     

    var 동적 자료형 (List/Map/Set)

    • var 동적 자료형을 사용하면 코딩을 쉽고 단순하게 유지할 수 있습니다. 정의된 변수를 사용하는 방법은 자료형을 명시적으로 지정한 경우와 다르지 않습니다.
    • runtimeType 속성과 is 연산자를 사용하여 동적으로 지정된 자료형을 확인하거나 비교할 수 있습니다.
    • print() 함수를 사용하여 변수에 저장된 값들을 조회볼 수 있는데 디버거(Debugger)를 사용하면 프로그램의 흐름에 따른 변수의 값을 쉽게 확인해 볼 수 있습니다.
    // List의 예
    void main() {
      // 자료형의 명시적 지정 (정적 자료형)
      List<String> lists = [ "문자열 항목1", "문자열 항목2", "문자열 항목3" ];
      print(lists);
    
      print(lists[0]);
      print(lists[lists.length-1]);
    
      print(lists.runtimeType);
      print(lists is List<String>);
    
      // 자료형의 암묵적 지정 (동적 자료형)
      var listsVar = [ "문자열 항목1", "문자열 항목2", "문자열 항목3" ];
      print(listsVar);
      
      print(listsVar[0]);
      print(listsVar[listsVar.length-1]);
    
      print(listsVar.runtimeType);
      print(listsVar is List<String>);
    }
    
    // Map 혹은 Dictionary의 예
    void main() {
      // 자료형의 명시적 지정 (정적 자료형)
      Map<String,String> maps = {"홍길동": "프로젝트관리자","강감찬": "모듈 리더"};
      print(maps);
      print(maps["홍길동"]);
      
      print(maps.runtimeType);
      print(maps is Map<String,String>);
    
      // 자료형의 암묵적 지정 (동적 자료형)
      var mapsVar = {"홍길동": "프로젝트관리자","강감찬": "모듈 리더"};
      print(mapsVar);
      print(mapsVar["강감찬"]);
      
      print(mapsVar.runtimeType);
      print(mapsVar is Map<String,String>);
    }
    
    // Set의 예
    void main() {
      // 자료형의 명시적 지정 (정적 자료형)
      Set<String> sets = { "사과", "바나나", "배", "귤", "사과" };  // 사과가 중복
      print(sets);                                                 // 출력에 중복없음
    
      print(sets.contains("사과"));
      print(sets.contains("파인애플"));
    
      print(sets.runtimeType);
      print(sets is Set<String>);
    
      // 자료형의 암묵적 지정 (동적 자료형)
      var setsVar = sets = { "사과", "바나나", "배", "귤", "사과" };
      print(setsVar);
    
      print(setsVar.contains("사과"));
      print(setsVar.contains("파인애플"));
    
      print(setsVar.runtimeType);
      print(setsVar is Set<String>);
    }

     

    • var로 정의한 변수는 한번 변수의 유형이 결정되면 변경될 수 없습니다. dynamic으로 정의한 변수는 한번 변수의 유형이 결정된 뒤에라도 필요에 따라 다른 유형으로 변경될 수 있습니다.
    • 왜 dynamic과 같은 자료형이 존재해야 하는지 언듯 이해가 되지 않을텐데 나중에 꼭 필요한 예를 들어 다시 설명하겠습니다.
    • 지금은 그냥 이질적인 자료형을 모두 수용해야 할 때 dynamic을 사용한다는 정도만 이해하고 갑시다.

     

     

     

     

    연산자

     

    • Python은 몫연산자로 //을 사용하는데 Dart 언어는 ~/를 사용하는군요.

     

     

     

    • Python은 논리 연산자로 and, or, not을 사용하지만, Dart는 Java나 JavaScript처럼 C 스타일의 논리 연산자 &&, ||, !을 사용합니다.

     

    • Dart는 Java나 JavaScript처럼 C 스타일의 증감 연산자인 ++와 --를 지원합니다. 이 연산자는 변수의 값을 1씩 증가 또는 감소시키는 데 사용됩니다. Python에서는 이러한 증감 연산자가 없기 때문에, 같은 기능을 하려면 += 1 또는 -= 1을 사용해야 합니다.

     

    • Dart 언어는 Java와 JavaScript와 같이 조건 ? 참일 때 값 : 거짓일 때 값 형태의 삼항 연산자를 사용하여 간결하게 조건문을 표현합니다. 반면 Python은 값 if 조건 else 값 형태의 삼항 연산자를 사용하여 조건에 따라 값을 할당하는 방식을 취합니다. 문법(Syntax)적인 형식은 다르나 의미(Semantics)는 if ~ else ~의 복잡한 표현을 단순화하는 것으로 동일합니다.

     

     

    // Dart 코드
    void main() {
        int num1 = 10;
        int num2 = 20;
        int max = num1 > num2 ? num1 : num2;
        print(max);
    
        int min;
        if(num1 < num2)
            min = num1;
        else
            min = num2;
        print(min);
    }
    
    # Python 코드  
    num1 = 10
    num2 = 20
    max_num = num1 if num1 > num2 else num2
    print(max_num)
    
    if num1 < num2:
        min_num = num1
    else:
        min_num = num2
    print(min_num)

     

    조건문

    • Dart 언어는 Java와 JavaScript와 같이 if와 else if 조건문을 지원합니다. 혹시 조건문의 흐름이 이해가 가지 않는다면 디버거를 사용하여 프로그램의 흐름을 추적해 보는 것이 좋습니다.

     

     

    // Dart 코드
    void main() {
        int num1 = 10;
        int num2 = 20;
        int max = num1 > num2 ? num1 : num2;
        print(max);
    
        int min;
        if(num1 < num2)
            min = num1;
        else
            min = num2;
        print(min);
    }

     

     

    • Dart 언어는 Java와 JavaScript와 같이 switch 조건문을 지원합니다. Python은 기존에는 switch 조건문을 지원하지 않았으나 Python 3.10 이상의 버전에서는 match 조건문을 지원합니다. 문법(Syntax)적인 형식은 다르나 의미(Semantics)는 if ~ else if ~ else 의 복잡한 표현을 단순화하는 것으로 동일합니다.
    // Dart 코드
    void main() {
        int number = 3;
    
        switch (number) {
            case 1:
                print("One");
            case 2:
                print("Two");
            case > 2:
                print ("Greater than Two");
            default:
                print("Other");
        }
    }
    
    # Python 코드  
    number = 3
    
    match number:
        case 1:
            print("One")
        case 2:
            print("Two")
        case _ if number > 2:
            print("Greater than Two")
        case _:
            print("Other")

     

     

    반복문

     

     

     

    • for in 반복문은 통상 컬렉션과 함께 사용되며 컬렉션의 요소만큼 반복하여 수행됩니다.

     

    // Dart 코드 (for in 반복문)
    void main() {
        // 자료형의 명시적 지정
        List<String> lists = [ "문자열 항목1", "문자열 항목2", "문자열 항목2" ];
        for(String item in lists) {
            print(item);
        }
    
        // 자료형의 암묵적 지정
        var items = [ "항목1", "항목2", "항목3" ];
        for(var item in items) {
            print(item);
        }
    }

     

    • while 반복문은 통상 break 문장과 함께 사용되어 특정한 조건이 만족할 때 반복을 중단하게 됩니다.

     

    // Dart 코드 (while 반복문)
    import 'dart:math';
    
    int factorial(int n) {
        if (n == 0 || n == 1) {
            return 1;
        }
        return n * factorial(n - 1);
    }
    
    void main() {
        // 초기 반복조건 설정
        double error = 100;
        const double tolerance = 0.001;
    
        double x = 3;
        double oldExpX = 1;
        int i = 1;
    
        // while 반복문
        while (true) {
            if (error <= tolerance) break;
    
            double expX = oldExpX + (1 / factorial(i)) * pow(x, i);
    
            error = (expX - oldExpX).abs();  // 반복조건 변경
    
            oldExpX = expX;
            i = i + 1;
        }
    
        print("무한급수를 $i 번 반복하여 찾아낸 exp(3) = $oldExpX");
        print("급수간 오차는 $error 입니다.");
    }

     

    • 혹시 반복문 코드의 흐름이 이해가 가지 않는다면 디버거를 사용하여 프로그램의 흐름을 추적하며 제어변수의 값을 관찰해 보는 것이 좋습니다.

     

    [실습] 장바구니 총합 계산

     

    [실습] 랜덤 점심 메뉴 출력

     

    함수

     

     

     

     

     

     

    • {int a=1, int b=3}과 같이 이름있는 파라메터에 required 키워드를 생략하고 초기값을 부여하면 생략가능한 파라메터(Optional Parameter)를 만들수 있습니다. add()와 같이 인자에 값을 넘기는 것을 생략하면 초기값이 대신 사용됩니다.
    int add({int a=1, int b=3}) => a + b;
    
    void main() {
      print(add());
    }

     

    [실습] 학생부 정리하기

    • 학생들의 이름과 성적이 담긴 리스트(List)는 아래와 같습니다. 아래의 리스트에서 구성요소인 맵(Map,딕셔너리/Dictionary)의 값의 자료형이 dynamic인 것을 눈여겨 봅시다.
    • 딕셔너리의 “name” 키의 값의 자료형은 문자열(String)이고 “score” 키의 값의 자료형은 정수(int)이니 이 두가지 자료형을 모두 리스트가 수용하는 맵의 자료형으로 지정하려면 여러가지 자료형을 수용할 수 있는 dynamic 자료형을 사용하여야 합니다.
    List<Map<String, dynamic>> students = [
    	{"name": "김민준", "score": 85},
    	{"name": "이서윤", "score": 92},
    	{"name": "박지우", "score": 78},
    	{"name": "최예은", "score": 89},
    	{"name": "정하윤", "score": 91},
    	{"name": "강서연", "score": 74},
    	{"name": "윤도윤", "score": 88},
    	{"name": "조현우", "score": 95},
    	{"name": "오하은", "score": 77},
    	{"name": "신우진", "score": 83},
    	{"name": "홍서준", "score": 82},
    	{"name": "임주원", "score": 94},
    	{"name": "류채은", "score": 72},
    	{"name": "김하람", "score": 86},
    	{"name": "문예준", "score": 80},
    	{"name": "최지호", "score": 90},
    	{"name": "박다인", "score": 79},
    	{"name": "이준우", "score": 88},
    	{"name": "김유찬", "score": 87},
    	{"name": "윤태민", "score": 93},
    	{"name": "전도현", "score": 81},
    	{"name": "서연우", "score": 92},
    	{"name": "한수민", "score": 76},
    	{"name": "유시현", "score": 89},
    	{"name": "최지안", "score": 84},
    	{"name": "신예지", "score": 85},
    	{"name": "장하준", "score": 74},
    	{"name": "정세준", "score": 78},
    	{"name": "송윤아", "score": 90},
    	{"name": "양지호", "score": 87},
    	{"name": "백다온", "score": 82},
    	{"name": "하지후", "score": 88},
    	{"name": "강민재", "score": 93},
    	{"name": "정유진", "score": 75},
    	{"name": "이재윤", "score": 91},
    	{"name": "박민혁", "score": 79},
    	{"name": "김태윤", "score": 80},
    	{"name": "이도현", "score": 84},
    	{"name": "오주원", "score": 77},
    	{"name": "조아인", "score": 92},
    	{"name": "송다인", "score": 86},
    	];
    }

     

     

    • 다음 명령어를 실행하여 결과를 확인해 보세요
      • print(searchByName(students, name: "윤")); // 이름에 "윤"이 포함된 학생 출력
      • print(searchByGrade(students, grade: 90)); // 90점 이상인 학생 출력

     

     참고 문헌

    [논문]

    • 없음

    [보고서]

    • 없음

    [URL]

    • 없음

     

     문의사항

    [기상학/프로그래밍 언어]

    • sangho.lee.1990@gmail.com

    [해양학/천문학/빅데이터]

    • saimang0804@gmail.com
    • 네이버 블러그 공유하기
    • 네이버 밴드에 공유하기
    • 페이스북 공유하기
    • 카카오스토리 공유하기