[Flutter] 스나이퍼팩토리 11일차

KWANWOO·2023년 2월 8일
1
post-thumbnail

스나이퍼팩토리 플러터 11일차

어제는 조건문을 학습했는데, 오늘은 반복문을 학습했다. 그리고 List에서 사용할 수 있는 여러 멤버함수들과 사용 방식을 알아보았고, 위젯도 반복문을 사용해 코드를 간결하게 하는 방법을 살펴보았다.

학습한 내용

  • Dart 반복문
  • List Method (forEach, where, map)
  • ListView.builder Widget

추가 내용 정리

Dart 반복문

반복문은 코;드를 반복 실행시키는 문장이다. 반복문을 잘못 작성하면 코드가 무한히 실행될 수 있으므로 주의해야한다.

  • for문 예시
for (int i = 0; i < 10; i++) {
    print(i);
}
  • for (..in..) 구문 예시
  List<String> fruits = ['사과', '배', '포도', '귤', '딸기'];

  for (String fruit in fruits) {
    print('나는 $fruit을 좋아해');
  }
  • forEach 메소드 (List의 멤버함수) 예시
 List<String> fruits = ['사과', '배', '포도', '귤', '딸기'];

  fruits.forEach((fruit) {
    print('나는 $fruit을 좋아해');
  });
  • forEach로 Map 다루기 예시
Map<String, String> gifts = {
  'first': 'partridge',
  'second': 'turtledoves',
  'third': 'necklace',
  'fourth': 'flower',
  'fifth': 'golden rings'
};

gifts.forEach((String key,String value) {
  print('$key, I like $value');
});
  • while문 예시
int i = 0;

while (i < 10) {
    print(i);
    i++;
}

List Method (멤버함수)

Dart에서 List에는 많은 멤버함수가 존재하지만 forEach where map는 정말 많이 쓰이는 메소드이다.

forEach는 위에서 반복문과 함께 정리하였으므로 List의 멤버함수를 포함하는 List관련 유용한 메소드들을 정리해보고자 한다.

  • ... (스프레드 연산자)
    아래와 같은 코드처럼 배열을 복사할 수 있다.
var list = [1, 2, 3, 4];

//얕은 복사(주소 값을 복사, 참조하는 실제 값은 같음)
var newList = list;
print(newList); //[1, 2, 3, 4]

//깊은 복사 (스프레드 연산자- 실제 값을 새로운 메모리 공간에 복사)
var spreadList = [10, 20, ...list];
print(spreadList); // [10, 20, 1, 2, 3, 4]
  • toList
    생성되는 값들을 리스트로 만들어 반환한다. map 등의 함수를 사용하면 Iterable 타입의 그룹이 반환되기 때문에 리스트로 변경하고 싶으면 뒤에 toList를 같이 사용한다.(추가로 깊은 복사를 하고 싶을 때 사용)

  • map
    Iterable을 대상으로 forEach를 수행한다. 아래는 map 함수의 예시이다.

var list = [1, 2, 3];
var newList = list.map((e) => e+1).toList(); //자신에게 1을 더해 리턴
print(list) // [1, 2, 3]
print(newList) // [2, 3, 4]
  • where
    리스트 요소를 필터링한다.
var list = [1, 2, 3, 4];

//3보다 작은 값만 필터링
var filterList = list.where((e) => e < 3).toList();
print(filterList) //[1,2]
  • asMap
    리스트 값에 Index 키 값을 삽입해서 반환한다.
var words = ['A', 'B', 'C', 'D'];
var wordMap = words.asMap(); // {0: A, 1: B, 2: C, 3: D}

//키 값만 리스트로 변환해 출력
print(wordMap.keys.toList()); // [0, 1, 2, 3]

더 많은 List 관련 함수들은 아래의 링크를 참고
[Flutter/Drat]다트 유용한 메소드 Method 함수 Function 정리~

ListView.builder Widget

ListView는 리스트 내의 모든 위젯을 한 번에 그리기 때문에 성능이 떨어질 수 있다. 따라서 ListView.builder를 사용하면 화면에 보여지는 요소만 그리기 때문에 성능이나 속도가 좋아질 수 있다.

ListView.builder에 몇 개의 항목을 만들 것인지와 몇 번째 항목에는 어떤 위젯을 그려줄지를 알려줘야한다. 이는 아래의 두 가지 속성을 사용한다.

ListView.builder 주요 속성

  • itemCount
    int 값이며 ListView 항목들의 총 개수에 해당한다. 주어지지 않으면 무한히 항목을 만든다.

  • itemBuilder(BuildContext context, int index)
    index 번째에 해당하는 항목에 그려질 위젯을 반환하는 함수이다.

아래의 예시는 100개의 텍스트 위젯을 그리는 리스트 뷰를 의미한다. itemCount에는 보통 리스트 데이터의 length를 넣어 사용하기도 한다.

ListView.builder(
    itemCount: 100,
    itemBuilder: (BuildContext ctx, int idx) {
        return Text('Content Number ${idx}');
    }
)

ListView.separatedListView.builder와 같은 내용을 출력하지만, 항목 사이에 구분선이 추가된다. 아래의 코드 처럼 사용 가능하다.

 ListView.separated(
    itemCount: 100,
    itemBuilder: (BuildContext ctx, int idx) {
      return Text('Content Number ${idx}');
    },
    separatorBuilder: (BuildContext ctx, int idx) {
      return Divider();
    },
 )

11일차 과제

  1. 크롤링이란?
  2. Dart에서 반복문과 제어문을 이용한 코드 작성
  3. 주어진 데이터를 활용한 코드 작성 연습1
  4. 주어진 데이터를 활용한 코드 작성 연습2

1. 크롤링이란?

크롤링(Crawling) 또는 스크래핑(Scraping)이란 웹 페이지에 있는 데이터들을 프로그래밍적으로 추출하는 것을 의미한다.

크롤링: 여러 웹 페이지를 기계적으로 탐색하는 일
스크래핑: 하나의 웹 페이지를 탐색하고 특정한 정보를 집어 얻어내는 일

(크롤링과 스크래핑은 서로 다른 의미이긴 하지만 구현 방법이 거의 같기 때문에 구분없이 많이 불린다.)

즉, 웹 페이지에서 자신이 필요한 데이터를 추출하여 다시 활용 가능한 형태로 만드는 것이다.

웹 페이지의 구성

크롤링에 대해 쉽게 이해하기 위해 웹 페이지의 구성부터 살펴보자

웹페이지는 아래 그림과 같이 구조를 잡는 HTML, 디자인을 하는 CSS, 사용자와 동적으로 상호작용하는 Javascript를 이루어져 있다.

웹 페이지는 서버와 클라이언트의 요청과 응답으로 구성되는데 서버와 클라이언트는 각각 아래와 같은 의미를 가지고 있고, 크게 세 단계를 거쳐 웹 페이지를 해석한다.

서버: 요청에 대해 응답을 해주는 프로그램
클라이언트: 서비스를 요청하는 프로그램

이러한 요청과 응답 등의 정보를 주고 받을 때 서버와 클라이언트 사이에서 특정한 규약을 가지고 있는데 이것이 HTTP이다.

HTTP는 메소드를 사용해 CRUD(Create, Read, Update, Delete)를 수행할 수 있는데 자세한 HTTP 메소드의 내용은 스나이퍼 팩토리 플러터 1일차 과정에서 작성한 블로그 내용을 확인하면 알 수 있다.
[Flutter] 스나이퍼팩토리 1일차

[참고] CRUD와 HTTP 메소드

  • Create = POST
  • Read = GET
  • Update = PUT, PATCH
  • Delete = DELETE

크롤링

위에서 설명한 웹 페이지의 HTML들을 참고해서 해당 웹 크롤러 기술을 활용해 정보를 가져오는 것이 웹 크롤링의 원리이다.

간단하게 사람과 비교해서 세 단계로 크롤링에 대해 설명해보고자 한다. 아래는 사람이 웹 페이지에서 정보를 얻는 과정이다.

  1. 열기: 웹 브라우저로 웹 페이지를 연다.
  2. 찾기: 눈으로 원하는 정보가 표시된 부분을 찾는다.
  3. 찾은 부분 안에 표시된 정보를 눈으로 보고 확인한다.

이러한 사람이 직접 찾는 과정을 프로그래밍하여 많은 정보를 추출할 수 있는 것이 크롤링인데 아래의 과정으로 진행된다.

  1. 열기: HTTP 통신으로 웹 페이지를 열어 HTML 코드 전체를 가져온다.
  2. 찾기: 원하는 정보가 표시된 HTML 태그를 찾는다.
  3. 보기: 찾은 HTML 태그 안에 기재된 정보를 가져온다.

위의 3가지 과정을 정확하게 소스코드로 구현할 수 있다면 어떤 프로그래밍 언어로든 웹 스크래핑을 구현할 수 있다.

보통 크롤링은 파이썬을 사용하는 경우가 많지만 아래의 링크에서는 PHP를 사용하여 미국 CNBC 방송의 웹사이트에서 S&P 500 지수의 값을 확인하는 과정을 자세히 보여준다.
웹 스크래핑(웹 크롤링)의 기본원리

2. Dart에서 반복문과 제어문을 이용한 코드 작성

2-1. 0부터 1000까지 49의 배수만 출력하는 코드를 작성하시오

  • 코드
void main() {
    for(int i = 1; i <= 1000; i++) {
      if (i % 49 == 0) print(i);
    }
}
  • 결과

for문을 사용해 0과 1000 사이의 49의 배수를 출력했다. 0은 49의 배수에 포함되지 않기 때문에 i를 1부터 시작했고, i값을 49로 나눴을 때 나머지가 0인 값을 출력했다.

2-2. 0부터 1000까지 2의 배수만 출력하는 코드를 작성하시오

  • 코드
void main() {
    for(int i = 1; i <= 1000; i++) {
      if (i % 2 == 0) print(i);
    }
}
  • 결과

    ...

2-1번의 문제와 마찬가지로 0은 2의 배수가 아니므로 i를 1부터 1000까지 설정했다. 2로 나눴을 때 나머지가 0인 숫자만 출력했고, 결과 값이 길어서 콘솔의 시작부분과 끝부분만 캡쳐해서 첨부했다.

2-3. 반복문 두 개를 사용하여 구구단을 출력하는 프로그램을 작성하시오

  • 코드
void main() {
    for(int i = 1; i <= 9; i++) {
      for(int j = 1; j <= 9; j++) {
        print('$i * $j = ${i*j}');
      }
      print('');
    }
}
  • 결과

이중 for문을 사용해서 1단부터 9단까지 출력했다. 첫 번째 for문에서 마지막에 print('')를 넣어 각 단을 구분했고, 결과 값이 길어서 3단씩 나눠서 캡쳐했다.

2-4. 다음의 결과물을 반복문을 사용하여 출력하는 프로그램을 작성하시오

  • 결과물 예시
//output
*
**
***
****
*****
******
*******
********
*********
**********
  • 코드
void main() {
  for (int i = 0; i < 10; i++) {
    print('*' * (i+1));
  }
}
  • 결과

i 값을 0부터 9까지 반복하여 ""을 출력하는데 각 라인의 ""에 i+1을 곱해서 별의 개수를 줄마다 다르게 출력했다.

2-5. 1부터 1000페이지까지 있다고 가정했을 때, url을 제작하여 startCrawling 함수에 전달하는 예시코드를 작성하시오.

  • 크롤링 예시 코드
bool startCrawling(String url){
  //...크롤링 하는 코드... //
	var	data = url;
  print(url+'에 크롤링 성공함');
	return true;
}

var url = "https://example.sniperfactory.com/board?pages=";

위의 크롤링 코드를 보면 url의 마지막에 pages= 뒤의 페이지 번호가 생략되어 있다. 즉, url에 1부터 1000까지의 번호를 넣어 startCrawling() 함수에 전달해야 한다. 매개변수를 전달하면 startCrawling() 함수는 url에 맞는 크롤링을 수행하고 결과를 리턴할 것이다. 이를 수행하는 main() 함수 코드를 아래와 같이 작성했다.

bool startCrawling(String url) {
  //...크롤링 하는 코드... //
  var data = url;
  print(url + '에 크롤링 성공함');
  return true;
}

var url = "https://example.sniperfactory.com/board?pages=";

void main() {
  for (int i = 1; i <= 1000; i++) {
    startCrawling(url + i.toString());
  }
}
  • 결과

    ...

main 함수에서 for문을 사용해 1에서 1000까지의 숫자를 url의 뒷부분에 더해 매개변수로 startCrawling() 함수에 전달했다. 결과 값이 길어서 콘솔의 시작부분과 끝부분만 캡쳐해서 첨부했다.

2-6. 0부터 1000까지 2의 배수만 출력할 때, if문을 사용하지 않고 출력하시오

  • 코드
void main() {
  for (int i = 2; i <= 1000; i += 2) {
    print(i);
  }
}
  • 결과

    ...

2의 배수는 2부터 시작해서 2씩 커지는 값이므로 i를 1부터 1000까지 반복하면서 값이 2씩 증가하도록 했다. 결과 값이 길어서 콘솔의 시작부분과 끝부분만 캡쳐해서 첨부했다.

2-7. 다음의 myVars 변수가 있을 때, 다음의 실행결과를 만들 수 있는 코드를 작성하시오

  • Requirement
    반복문을 사용하여 해결할 것, 그 외 코드 작성 자유

  • Data
List myVars = [1,2,3,4,5,6,7];
  • 결과물 예시
// 실행결과
//[5,10,15,20,25,30,35]
  • 코드
List myVars = [1,2,3,4,5,6,7];

void main() {
  for (int i = 0; i < myVars.length; i++) {
    myVars[i] *= 5;
  }
  
  print(myVars);
}
  • 결과

주어진 변수를 선언하고 for문을 사용해 리스트의 값들을 5를 곱하여 저장했다. for문은 0부터 myVars.length -1까지 반복했다. 마지막으로 리스트를 출력했다.

2-8. 다음의 코드 조각을 플러터를 통하여 실행하고, 실행결과를 스크린샷찍어 첨부하시오 이 때, 동작원리를 간략하게 설명하시오.

  • 코드 조각
Column(
  children: [
    Text('0'),
    for(var i=1; i<100; i++)
      Text(i.toString()),
    Text('101'),
  ]
)
  • 실행 코드
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: SingleChildScrollView(
            child: Column(
              children: [
                Text('0'),
                for (var i = 1; i < 100; i++) Text(i.toString()),
                Text('101'),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
  • 결과

화면을 보기 쉽게 구성하기 위해 주어진 코드를 SafeAreaSingleChildScrollView 위젯으로 감싸주었다.

결과는 0부터 99까지의 숫자가 순서대로 출력되었고 마지막에 101이라는 숫자가 출력되었다.

해당 페이지의 원리는 다음과 같다.

  1. Column의 children 리스트에 "0"이라는 텍스트가 적인 Text 위젯이 그려진다.
  2. 아래에 for문으로 반복되어 "1"부터 "99"까지의 숫자가 적힌 Text 위젯이 그려진다.
  3. 마지막에 "101"이 쓰여진 Text 위젯이 그려진다.

즉, 처음의 0과 마지막의 101 Text 위젯은 따로 그려진 것이고 1부터 99까지의 Text 위젯은 i 값이 반복되어 Text 위젯으로 그려진 것이다.

3. 주어진 데이터를 활용한 코드 작성 연습1

  • Data
    randomData, mathData에 각각 총 100개의 요소가 있다.
var randomData = ['x', 'p', 's', 'j', 'm', 'V', 'X', 'g', 'v', 'o', 
	'c', 'f', 'R', 'L', 'a', 'T', 'q', 'S', 'Z', 'l', 'F', 
	'E', 'D', 'r', 'k', 'G', 'H', 't', 'd', 'C', 'e', 'I', 
	'K', 'Q', 'B', 'i', 'W', 'N', 'J', 'O', 'h', 'w', 'U', 
	'P', 'u', 'A', 'Y', 'M', 'y', 'z', 'b', 'n', 'x', 'p', 
	's', 'j', 'm', 'V', 'X', 'g', 'v', 'o', 'c', 'f', 'R', 
	'L', 'a', 'T', 'q', 'S', 'Z', 'l', 'F', 'E', 'D', 'r', 
	'k', 'G', 'H', 't', 'd', 'C', 'e', 'I', 'K', 'Q', 'B', 
	'i', 'W', 'N', 'J', 'O', 'h', 'w', 'U', 'P', 'u', 'A', 'Y', 'M']

var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90];

3-1. mathData에 50이 넘는 수가 몇 개인지 확인하는 코드를 작성하시오.

  • 코드
var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90];

void main() {
  print(mathData.where((e) => e > 50).length);
}
  • 결과

mathData 리스트에서 where 함수를 사용하여 50보다 큰 조건의 원소들만으로 Iterable 타입의 값을 반환했고, 이 값에 length 함수를 사용해 원소의 개수를 구해 출력했다. mathData 리스트에 50이 넘는 숫자는 총 41개이다.

3-2. mathData에 80이 넘어가는 수만 고르고 난 뒤, 각 수에 곱하기 2를 한 후 변수 mathData2에 새로 저장하는 코드를 작성하시오.

var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90];

void main() {
  var mathData2 = mathData.where((e) => e > 80)
                          .map((e) => e*2)
                          .toList();
  
  print(mathData2);
}
  • 결과

mathData 리스트에 where 함수를 사용하여 80이 넘어가는 숫자를 고르고 map 함수를 사용해 2를 곱한 수들을 toList를 사용해 리스트로 변환한 뒤 변수 mathData2에 저장했다.

3-3. mathData와 randomData의 데이터를 섞어서 다음과 같은 결과를 만드시오.

  • 결과물 예시
    (x26은 mathData[0]과 mathData[0]이 합쳐져 만들어진 결과이다. 코드 작성은 자유방식이다.)
x26
p2
s9
j47
m98
V24
X43
g99
//...(생략)
A93
Y63
M90
  • 코드
var randomData = ['x', 'p', 's', 'j', 'm', 'V', 'X', 'g', 'v', 'o', 
	'c', 'f', 'R', 'L', 'a', 'T', 'q', 'S', 'Z', 'l', 'F', 
	'E', 'D', 'r', 'k', 'G', 'H', 't', 'd', 'C', 'e', 'I', 
	'K', 'Q', 'B', 'i', 'W', 'N', 'J', 'O', 'h', 'w', 'U', 
	'P', 'u', 'A', 'Y', 'M', 'y', 'z', 'b', 'n', 'x', 'p', 
	's', 'j', 'm', 'V', 'X', 'g', 'v', 'o', 'c', 'f', 'R', 
	'L', 'a', 'T', 'q', 'S', 'Z', 'l', 'F', 'E', 'D', 'r', 
	'k', 'G', 'H', 't', 'd', 'C', 'e', 'I', 'K', 'Q', 'B', 
	'i', 'W', 'N', 'J', 'O', 'h', 'w', 'U', 'P', 'u', 'A', 'Y', 'M'];

var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90];
  
void main() {
  for (int i = 0; i < 100; i++) {
    randomData[i] += mathData[i].toString();
    
    print(randomData[i]);
  }
}
  • 결과

    ...

for문을 사용하여 0부터 99까지 반복하며 randomData[i]mathData[i].toString()을 더해 저장했다. 결과 값은 저장한 값을 반복할 때마다 randomData[i]를 출력하여 확인했다. 결과 값이 길어서 콘솔의 시작부분과 끝부분만 캡쳐해서 첨부했다.

두 리스트의 데이터가 섞인 값들은 randomData에 저장되어 있다.

4. 주어진 데이터를 활용한 코드 작성 연습2

  • Data
    randomData, mathData에 각각 총 100개의 요소가 있다.
var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90];

4-1. 모든 요소를 Colors.amber 색상을 적용하여 아래 예시와 같은 화면을 출력하시오.

  • 결과 예시

  • 코드

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // root Widget
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(), // 홈 페이지 호출
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
    var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90]; // 데이터 리스트

    return Scaffold(
      body: SafeArea(
      	// 그리드 뷰
        child: GridView.builder(
          padding: EdgeInsets.all(8.0),
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            mainAxisSpacing: 8,
            crossAxisSpacing: 8,
            crossAxisCount: 4, //한 줄에 4개의 아이템
          ),
          itemCount: mathData.length, // 그리드 뷰 개수는 mathData 길이
          itemBuilder: ((context, index) {
            return Card(
              color: Colors.amber, //카드 색 설정
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(16), //테두리 곡선
              ),
              child: Center(
                child: Text(mathData[index].toString()), //텍스트
              ),
            );
          }),
        ),
      ),
    );
  }
}
  • 결과

MyHomePage 위젯을 생성하여 주어진 데이터를 입력했다.

build 메소드 내에서 그리드 뷰를 생성했는데 GridView.builder를 사용했다. 그리드 뷰를 화면에서 안전 영역에 위치하도록 SafeArea로 감싸 주었다.

그리드 뷰는 한 줄에 4개의 아이템이 위치하도록 했고, itemCountmathData의 길이로 설정했다.

itemBuilder로 내부 요소를 리턴했는데 Card 위젯을 색상과 테두리 곡선을 설정해 주었다. child로는 Text위젯을 사용하여 mathData[index].toString()으로 데이터를 출력했다.

4-2. 10이 넘지 않는 수만 아래 예시와 같이 출력하시오.

  • 결과 예시

  • 코드

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // root Widget
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(), // 홈 페이지 호출
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
  	var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90];

    //10이 넘지 않는 수를 저장한 리스트
    var newData = mathData.where((element) => element < 10).toList();

    return Scaffold(
      body: SafeArea(
        // 그리드 뷰
        child: GridView.builder(
          padding: EdgeInsets.all(8.0),
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            mainAxisSpacing: 16,
            crossAxisSpacing: 16,
            crossAxisCount: 4, //한 줄에 4개의 아이템
          ),
          itemCount: newData.length, // 그리드 뷰 개수는 mathData 길이
          itemBuilder: ((context, index) {
            return Container(
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(16), //테두리 곡선
                //박스 그림자
                boxShadow: [
                  BoxShadow(
                    color: Colors.grey.withOpacity(0.7),
                    spreadRadius: 1,
                    blurRadius: 5.0,
                  ),
                ],
              ),
              child: Center(
                child: Text(newData[index].toString()), //텍스트
              ),
            );
          }),
        ),
      ),
    );
  }
}
  • 결과

주어진 mathData 리스트에서 where을 사용하여 10을 넘지 않는 수들을 저장하는 리스트 newDatabuild 전에 생성했다.

4-1번과 마찬가지로 GridView.builder를 사용해서 그리드 뷰를 구성했는데 이번에는 newData의 데이터를 사용하여 itemCount를 설정하여 만들었다.

내부요소는 Card가 아닌 Container를 사용하여 만들었다. 컨테이너의 색은 흰색으로 하고 테두리 곡선과 그림자를 추가했다. child로는 Text를 사용해서 newData[index].toString()을 출력했다.

4-3. 스크롤이 가능한 형태이며 모든 수를 대상으로 width : [수*2], height: 24 만큼의 크기를 가진 Container를 100개를 나열하는 코드를 작성하시오.

  • 결과 예시

  • 코드

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // root Widget
  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(), // 홈 페이지 호출
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  
  Widget build(BuildContext context) {
  	var mathData = [26, 2, 9, 47, 98, 24, 43, 99, 96, 45, 35, 
			19, 37, 60, 31, 74, 26, 4, 28, 19, 59, 14, 75, 13, 
			93, 88, 64, 15, 68, 34, 96, 48, 1, 44, 14, 11, 31, 
			39, 28, 100, 22, 73, 78, 98, 36, 49, 74, 16, 35, 91, 
			14, 73, 93, 49, 3, 99, 4, 29, 86, 56, 17, 13, 97, 55, 
			94, 7, 100, 66, 59, 85, 94, 11, 16, 48, 16, 44, 75, 14, 
			17, 88, 92, 12, 49, 35, 42, 82, 19, 27, 11, 21, 34, 27, 
			47, 40, 66, 90, 99, 93, 63, 90];

    return Scaffold(
      body: SafeArea(
        // 리스트 뷰
        child: ListView.builder(
          itemCount: mathData.length, // 그리드 뷰 개수는 mathData 길이
          itemBuilder: ((context, index) {
            return Align(
              alignment: Alignment.topLeft,
              child: Container(
                width: mathData[index] * 2,
                height: 24,
                margin: EdgeInsets.all(8.0),
                alignment: Alignment.center,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(16), //테두리 곡선
                  //박스 그림자
                  boxShadow: [
                    BoxShadow(
                      color: Colors.grey.withOpacity(0.7),
                      spreadRadius: 1,
                      blurRadius: 5.0,
                    ),
                  ],
                ),
                child: Text(mathData[index].toString()),
              ),
            );
          }),
        ),
      ),
    );
  }
}
  • 결과

4-2와 같은 방식이지만 이번에는 GridView.builder() 대신에 ListView.builder()를 사용했다.

전체 데이터에 대해 화면을 구성하기 위해 itemCountmathData.length로 설정했다.

ContainerListView 아래에서 width를 설정해도 최대로 확장되기 때문에 우선 Align으로 감싸 Alignment.topLeft를 설정했다. Container에서는 width: mathData[index] * 2height: 24를 설정하고, 내부 텍스트를 가운데 설정하기 위해 이번에는 Center 위젯 대신 컨테이너에서 alignment: Alignment.center를 작성해 보았다. 컨테이너 그림자와 테두리 곡선은 4-2번과 같다.

child의 요소로는 Text위젯을 사용하여 mathData[index].toString()을 출력했다.


오늘은 지금까지 중에 젤 오래걸림 ㅠㅠ

진짜로 지금까지 학습하고 과제했던 날 중에 가장 오래걸렸다. ㅠㅠ 아침 9시에 시작해서 밥 먹는 시간 제외하고 거의 쉬지 않고 했는데 4시 조금 지나서 끝났다. 음...그렇게 엄청 어렵거나 하진 않았는데 양이 좀 많았던것 같다(정리할 내용도 많았고...) 그래서 그런건 아니고 후기는 일찍 마치겠습니다 ㅎㅎ 😭😭 (예전에 플러터 사용했을 때는 몰랐는데 안드로이드에 있는 RecyclerView와 같은 게 플러터에도 있지 않을까 했는데 오늘 공부해보니 ListView.builder와 같은 것이 보이는 화면만 그려주는거라 비슷하게 성능이 좋아지게 하는 역할을 하는 것 같다. 아마도...? ㅋㅋㅋㅋ)

📄 Reference

profile
관우로그

0개의 댓글