Flutter 1부터 배우기 : 나만의 퀴즈 앱 -3 [List, Map]

개발하자 백조·2022년 12월 26일
1
post-thumbnail

아직 2편 화면분할을 못 봤다면? 보러가기 👀


반갑습니다 여러분! 코딩백조입니다🦢

지난 시간에는 우리의 앱 화면을 main.dart 에 만드는 것이 아니라, quiz_screen.dart 에다가 나눠서 만들어 봤었어요! 그 위젯을 메인 함수 내에서 불러오기도 했구요.

오늘은 작성한 질문/대답을 통해 어떻게 퀴즈가 진행될 지에 대해 설명해드릴게요!

📍 [ 3 / 7 ] 질문/대답의 구조 소개, List & Map 소개

대답 버튼을 눌렀을 때 어떻게 화면이 바뀔지에 대해 고민해보는 시간이 될거에요.
또한, setState 라고 하는 함수에 대해 알아볼게요!

플러터에서 데이터를 어떻게 저장하고 관리할 지에 대해 짧게 설명해드리겠습니다 🤩

그럼, 바로 출발 ~~ 💨


지난 시간에 숙제로 드렸던 질문과 대답에 대해 하나 알려드릴 게 있어요!

뭔가.. 평소에 우리가 보는 형식이랑은 달라요. 그냥 문자가 아니라 막 [ ] { } : 이런게 있어요. 그쵸?! 🤨

[
    {
      'questionText': '평화로운 휴일!\n간만에 찾은 자유시간,\n당신은 무엇을 하시겠습니까?',
      'answers': [
        {'text': '나에게 휴식이란 없다. 소맥 달려~!', 'score': 8},
        {'text': '운동은 못참지! 헬스장 가기', 'score': 6},
        {'text': '노래 들으며 산책이나 할까?', 'score': 4},
        {'text': '피곤해.. 누워서 넷플 정주행하기', 'score': 2},
      ],
    },
  ];

이건 Dart 에서 사용하는 컴퓨터 언어 문법이에요!

으으.. 영문법도 질리는데 코딩에도 문법이.. 라고 생각 할 수도 있지만!!
사람마다 말투가 다르고 주로 쓰는 단어가 있듯, 컴퓨터가 쓰는 말투라고 생각해 주세요. 🤪

짧게 이 문법들을 설명해 드릴게요! 따라 하지는 않으셔도 됩니다 😉

List [ ]

리스트, 말 그대로 목록 입니다.
대괄호 안에 넣어진 항목을 순서대로 (0번째 1번째 2번째 ...) 접근할 수 있게끔 해주는 문법이에요!
새로운 리스트를 만들려면 이렇게 하면 됩니다.

List breakfast = ["bread", "egg", "strawberry"];

오늘 제 아침을 리스트로 정리해 봤습니다. 🤤

첫 번째 항목인 "bread" 를 꺼내고 싶으면, String first = breakfast[0]; 이렇게 변수 이름 뒤 [ ] 안에다가 순서를 숫자로 넣어주면 됩니다!
0은 컴퓨터에게 첫 번째라는 뜻이라서, first 변수에 "bread" 가 저장될거에요!

우리 숙제를 보면 맨 앞뒤에 [ ] 로 묶여있죠? 여러 개의 질문을 목록으로 모았다! 라는 뜻입니다 😲

Map { : }

맵, 혹은 딕셔너리 라고 부르는 이 문법은, 좀 독특해요.

사전이랑 똑같은 형식을 취하는데요,
사전에는 한 단어 당 여러 뜻이 올 수 있지만! 똑같은 단어가 두 번 기록되지는 않죠?
그리고 단어의 을 찾기 위해 사전을 쓰는 것 처럼,

단어(key)를 통해 단어의 뜻(value)을 찾아주는 구조가 바로 맵 입니다!

맵은 0번째 1번째.. 같은 순서가 없구요, 항상 key 를 통해 값에 접근합니다.

Map coffee = {
  'ice': 'Americano',
  'hot': 'Latte',
},

이게 바로 Map 입니다!
제가 커피를 차갑게 먹는지, 뜨겁게 먹는지 정리했어요. ☕️

ice 와 hot 라는 key 값에다가 각각 아메리카노와 라떼를 value 로 넣었습니다.

차가운 커피로 뭘 먹는지 확인하고 싶으면, String coldCoffee = coffee["ice"]; 이렇게 [" "] 따옴표 내부에 key 값을 넣어주면 됩니다! coldCoffee 라는 변수에 "Americano" 라는 값이 저장 되었겠죠?


이렇게 list 와 map 에 대해 간단하게 알아보았습니다.
왜냐면 우리의 질문 대답이 그렇게 이뤄졌기 때문이죠!!

[

  {
    'questionText': '평화로운 휴일!\n간만에 찾은 자유시간,\n당신은 무엇을 하시겠습니까?',
    'answers': [
      {'text': '나에게 휴식이란 없다. 소맥 달려~!', 'score': 8},
      {'text': '운동은 못참지! 헬스장 가기', 'score': 6},
      {'text': '노래 들으며 산책이나 할까?', 'score': 4},
      {'text': '피곤해.. 누워서 넷플 정주행하기', 'score': 2},
    ],
  },
  
  {
    'questionText': '카페에서 이상형을 본 당신!\n무엇을 하시겠습니까?',
    'answers': [
      {'text': '말은 부끄러워서 못 걸거 같다. 눈에만 담기', 'score': 2},
      {'text': '가서 말을 걸어본다. 혹시 애인 있으세요?', 'score': 8},
      {'text': '나 오늘 .. 상태 괜찮나? 일단 거울 보기', 'score': 4},
      {'text': '그 사람 앞에 쪽지를 남기고 떠난다.', 'score': 6},
    ],
  },
  
  {
    'questionText': '안 친한 친구에게 받은 카톡.\n너 이런 점은 고쳤으면 좋겠어.',
    'answers': [
      {'text': '알겠어 근데 내 일은 내가 알아서 할게..^^', 'score': 4},
      {'text': '이렇게 생각할 수도 있군. 고쳐본다고 한다.', 'score': 2},
      {'text': '어쩌라는거지? 참견 말라고 한 소리 한다.', 'score': 8},
      {'text': '굳이 얼굴 붉히기 싫다. 읽씹한다.', 'score': 6},
    ],
  },
  
];

어떤가요? 맵과 리스트가 몇 개나 보이시나요?

이 전체가 하나의 리스트죠! 3개의 map 을 가지고 있네요.
각각의 map 은 questionText 와 answers 라는 key 값을 가지고 있고, answers 의 value 값은 리스트네요!
그 리스트는 또 4개의 map 으로 이루어져있습니다. 각각 text 와 score 라는 key 를 가지고 있네요.

휴.. 복잡하죠? 😮‍💨
그래도 이제 좀 파악이 되었으니 설명을 할 수 있겠어요!!

자.. 이 두개를 보면 어디가 어디로 연결 되어있는지 파악이 되실거에요!

  {
    'questionText': '평화로운 휴일!\n간만에 찾은 자유시간,\n당신은 무엇을 하시겠습니까?',
    'answers': [
      {'text': '나에게 휴식이란 없다. 소맥 달려~!', 'score': 8},
      {'text': '운동은 못참지! 헬스장 가기', 'score': 6},
      {'text': '노래 들으며 산책이나 할까?', 'score': 4},
      {'text': '피곤해.. 누워서 넷플 정주행하기', 'score': 2},
    ],
  },

questionText 가 바로 질문,
answers 의 text 가 바로 대답이었습니다!! 🤩
그리고 score 을 통해 각각 대답을 눌렀을 때 더해질 점수가 정해지겠죠?

이렇게 미리 질문과 대답을 정한 이유가 뭐냐구요?
매번 Text 와 ElevatedButton 에 값을 넣어주지 않고, 이 질문과 대답 리스트에서 값을 가져가는 것이 코드를 효율적으로 짤 수 있기 때문이죠!
필요한 데이터를 한 곳에 몰아넣고 나중에 가져가는 게 훨씬 관리하기 쉽답니다.😉


자, 이제 본격적으로 이것들을 활용해보겠습니다!! 😎

간단하게 첫 화면이 동작하는지만 보고 넘어가겠습니다.

우리가 써온 질문과 대답을 새로운 파일에다가 넣어줄게요!
question_list.dart 라는 파일을 새로 만들겠습니다.

그 다음, 이 리스트를 변수에 저장할게요!
List<Map<String, dynamic>> questionList = ... 라고 써주시고, ... 부분에 써온 코드를 입력해줍시다.

List<Map<String, dynamic>> 은 무슨 뜻이냐구요? 🤔

Dart 문법에서 <> 이것으로 타입을 선언해줍니다. 그니까, 뭐로 이루어졌는지를 알려주는거죠!
List 이긴 한데, 일반 리스트가 아니라 맵으로 이뤄진 리스트고, 그 맵은 또 String 타입의 key 와 dynamic 타입의 value 를 가진다는 뜻이에요!
(dynamic은 '모든 것' 이라고 생각하시면 됩니다.)

이렇게! question_list.dart 에 이 리스트 하나만 넣어줄게요.

이렇게 보이면 됩니다! 왼쪽에 초록색이 되거나 question_list.dart 가 파란색이 아니더라도 걱정마세요. 현재는 변화 없는게 정상입니다! 😉

그리고!

quiz_screen.dart 로 이동해볼게요. 💨

일단은 이해가 안 되어도 따라 해보세요!


우리의 questionList 의 첫 번째 문항을 사용해보겠습니다.
첫 번째는 컴퓨터에게 0번이라고 했었죠?

QuizScreen 의 Column 값 중에서 우리가 질문으로 주었던 Text 위젯을 바꿔보겠습니다.

Text("질문 입니다"), 를 이렇게 바꿔줄게요!

Text(questionList[0]["questionText"]), 이렇게 바꿔주었습니다.

우리가 다른 파일에서 썼던 questionList 를 불러오기 해서 (엔터 치면 자동으로 불러오기 됨),
그 중 첫 번째 항목(0번째) 의,
'questionText' 라는 key 값을 가지는 value 값을 가져온 것입니다!

저에게는 그게 '평화로운 휴일!\n간만에 찾은 자유시간,\n당신은 무엇을 하시겠습니까?' 라는 값이 되었어요.

한 번 Run ▶️ 눌러볼까요?

여러분의 첫 번째 questionText 가 보이면 성공입니다!

대박!!
성공적으로 화면이 보여요!

마찬가지로 ElevatedButton 의 child: 값에 이렇게 넣어줄게요!
일단은 첫 번째 버튼 값만 바꿔볼게요.

ElevatedButton(
  onPressed: () {},
  child: Text(questionList[0]["answers"][0]["text"]),
),

다시 Run 해볼까요?

오!! 버튼도 성공적으로 바뀌었어요! 🥳

이제 다음 시간을 위한 준비가 다 되었네요.
이번 파트가 길어서 힘들었을 텐데, 끝까지 수고 많으셨습니다!! 😎

그럼, 다음 시간에 봐요 🥰


quiz_screen.dart

import 'package:flutter/material.dart';
import 'package:personal_quiz/question_list.dart';

class QuizScreen extends StatelessWidget {
  const QuizScreen({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          const SizedBox(height: 100),
          Text(questionList[0]["questionText"]),
          const SizedBox(height: 150),
          ElevatedButton(
            onPressed: () {},
            child: Text(questionList[0]["answers"][0]["text"]),
          ),
          ElevatedButton(onPressed: () {}, child: Text("대답 2")),
          ElevatedButton(onPressed: () {}, child: Text("대답 3")),
          ElevatedButton(onPressed: () {}, child: Text("대답 4")),
        ],
      ),
    );
  }
}
profile
개발자로서 100가지 일을 해보고 싶은 조경현의 개발 블로그

0개의 댓글