https://www.youtube.com/watch?v=oA2PngShjm8
1. 이건 꼭 알아야 한다^1
[? 질문] Flutter 기본 샘플 앱(Hello World + 숫자 + 플러스 버튼 증가)을 “직접” 어떻게 다시 구성하는가^1
[= 답] Text를 Center로 감싸 중앙 정렬을 만들고, 여러 위젯을 세로로 배치하려면 Column(children: [...])을 사용하며, 정렬은 mainAxisAlignment/crossAxisAlignment로 제어하고, 버튼 클릭 시 setState() 안에서 카운터 변수를 ++ 증가시키면 된다.^1
[? 질문] Text에 정수 카운터 값을 표시할 때 왜 오류가 나며 어떻게 해결하는가[^2]
[= 답] Text는 문자열을 받는 자리인데 카운터는 int이므로 그대로 넣을 수 없고, 작은따옴표 문자열 안에서 $counter처럼 문자열 보간(string interpolation) 으로 문자열로 만들어 표시한다.[^2]
[? 질문] Column을 쓰면 왜 내용이 “가운데”가 아니라 “위로 붙는가”, 그리고 어떻게 가운데로 되돌리는가[^3]
[= 답] Column은 기본적으로 가능한 세로 공간을 “꽉 채우는” 레이아웃으로 이해할 수 있고, 기본 정렬이 상단 쪽으로 배치되기 때문에 위로 붙어 보인다. mainAxisAlignment: MainAxisAlignment.center를 주면 세로(메인축) 방향 가운데로 정렬된다.[^3]
2. 큰 그림[^4]
이 콘텐츠는 Flutter 프로젝트를 처음 만들면 자동으로 들어있는 기본 샘플 코드(문구 + 숫자 + 플러스 버튼으로 증가)를 다시 되짚으면서, 화면 배치(센터/컬럼/정렬)와 상태 변경(카운터 증가)을 최소 코드로 구현하는 과정을 설명한다.[^4] 기존 코드를 “전부 지우지 않고”, 필요한 부분을 직접 추가/수정하면서 구조를 이해시키는 방식으로 진행한다.[^5]
- Center 위젯으로 단일 위젯(예:
Text)을 화면 중앙에 배치하는 방법을 보여준다.[^6] - Column + children으로 여러 위젯을 세로로 쌓고, mainAxisAlignment / crossAxisAlignment로 정렬을 제어하는 이유를 설명한다.[^7]
- 버튼 클릭 시 호출되는 함수 흐름을 따라가며
setState()내부에서 카운터 증가를 추가해 기본 예제를 완성한다.[^8]
3. 하나씩 살펴보기[^9]
3.1 “처음 프로젝트”에 있던 기본 샘플을 다시 만들어보기^1
강의자는 Flutter 프로젝트를 맨 처음 생성했을 때 기본으로 작성돼 있던 샘플 코드를 기준으로 다시 돌아가 보겠다고 말한다.^1 그 샘플 화면의 구성 요소를 먼저 기억해보듯이 짚는데, 화면에 어떤 글자가 있고(문구), 그 아래에 숫자가 있으며, 버튼을 누르면 숫자가 1씩 증가하던 형태였다고 설명한다.[^1][^10] 그리고 이제는(앞선 강의들을 통해) 그런 것들을 직접 만들 수 있게 됐으니, 그 샘플 형태를 재현해보자는 흐름으로 이어간다.[^5]
또한 “기존에 있는 코드를 지우지는 않을 것”이라고 하면서, 완전 초기화가 아니라 기존 코드 기반에서 바로 추가해보는 방식으로 진행한다고 예고한다.[^5]
3.2 카운터 변수 만들기: 숫자를 저장할 상태 준비[^11]
샘플 앱의 핵심 요소 중 하나는 “숫자”이며, 버튼을 누를 때마다 값이 바뀌어야 한다.[^10] 그래서 강의자는 “숫자를 저장할 변수를 하나” 만들고 그 이름을 counter로 두겠다고 한다.[^11] (말로는 “카운터라고 하나 만들어”라고 설명하며 초기값을 두는 흐름으로 진행한다.)[^11]
여기서 포인트는 다음과 같다.
- 숫자는 화면에 보여주기만 하는 값이 아니라, 버튼 클릭으로 변경될 상태(state) 이다.[^8][^10]
- 따라서 어딘가에 변수로 저장해두고, 변경 시 화면이 다시 그려지도록 연결해야 한다.[^8]
3.3 Text를 가운데로 보내기: Center로 감싸기 + IDE 단축키(Alt+Enter)[^6]
초기 상태에서 body에 Text가 하나만 남아 있는 형태를 가정하고, 이 텍스트를 “가운데로 옮기는” 방법을 설명한다.[^6] 강의자가 제시하는 방식은 간단하다:
Text위젯을Center위젯으로 감싼다.[^6]- 즉,
Center(child: Text(...))형태로 만들면 중앙 배치가 된다.[^6]
구체적으로는, 코드에서 텍스트를 선택한 뒤(윈도우 기준) Alt + Enter를 누르고, “Center 위젯”을 클릭하면 IDE가 자동으로 Center로 감싸주는 리팩토링을 해준다고 시연한다.[^6] 이렇게 감싸고 저장하면 텍스트가 가운데로 이동하는 것을 확인한다.[^6]
[!TIP] Center 적용을 빠르게 하는 방법(강의에서 제시한 흐름) 윈도우 환경에서는 텍스트 위젯에 커서를 두고
Alt+Enter→ “Center 위젯으로 감싸기”를 선택하면 자동으로 감싸진다.[^6]
3.4 텍스트를 하나 더 추가해야 함: “문구” + “카운터 표시”[^12]
샘플 화면은 글자 하나만 있는 게 아니라, 위에는 예를 들어 “Hello World” 같은 문구가 있고 그 아래에 숫자가 표시되는 형태다.[^10][^12] 강의자도 “텍스트가 하나 더 필요”하다고 하며, 새로 필요한 텍스트는 “카운터를 표시할 텍스트”라고 명확히 말한다.[^12]
하지만 Center는 기본적으로 child가 1개인 구조이므로(센터 안에 한 위젯), “위에서 아래로 주르륵 들어갈 수 있는” 위젯이 필요하다고 한다.[^13] 여기서 다음 단계인 Column으로 넘어간다.[^13]
3.5 Center 안에서 위젯을 세로로 쌓기: Column과 children[^14]
강의자는 Center의 자식으로 여러 위젯을 세로로 배치하려면 Column 을 사용해야 한다고 소개한다.[^14] Column은 “열(column)”이라는 의미이며, “세로 방향으로 위젯을 넣을 수 있다”고 설명한다.[^14]
이때 Column의 중요한 속성으로 children을 꺼낸다:
Column에는child가 아니라children이 있으며,- 여러 개를 자식으로 가질 수 있고,
children은 배열(list) 형태로 작성한다고 설명한다.[^15]
즉, children: [ 위젯1, 위젯2, ... ] 구조를 이해시키는 것이다.[^15]
강의 흐름에서는 기존에 있던 Text를 잠시 “오려내기(잘라내기)” 해서, Column(children: [...]) 안에 넣는 식으로 재배치하는 과정을 보여준다.[^16] 또한 괄호를 하나 빼먹는 실수(또는 흔히 생길 수 있는 문법 오류)를 언급하며, 괄호를 맞춰서 정상 컴파일되도록 정리한다.[^17] 그런 다음 텍스트를 하나 더 복사/붙여넣기 해서 두 개의 Text가 세로로 쌓인 화면을 만든다.[^18]
저장해보면 두 텍스트가 화면에 나타나지만, 기대와 달리 전체가 위쪽으로 붙어 보이는 상태가 된다.[^19]
3.6 두 번째 Text를 “숫자”로 바꾸기: int를 Text에 넣을 수 없고, $counter로 표시한다[^2]
두 번째 줄 텍스트는 더 이상 “Hello World” 같은 문구가 아니라, 실제 counter 값(숫자)이 나와야 한다.[^12] 여기서 강의자는 중요한 타입/표현식 문제를 짚는다:
counter는int(정수) 타입이다.[^2]- 그런데
Text위젯은 문자열이 들어갈 자리이므로,int를 그대로 넣을 수 없다.[^2] - 따라서 문자열로 바꿔줘야 한다.[^2]
강의자는 “앞뒤에 작은따옴표”를 두르고 문자열을 만들라고 하면서, Dart에서는 기본적으로 작은따옴표를 쓴다는 언급도 한다.[^2] 하지만 단순히 'counter'처럼 쓰면 “이렇게 하면 안 된다”고 강조한다.[^2] 변수 값을 문자열에 넣으려면 변수 앞에 $를 붙이는 Dart 문법을 사용해야 한다고 설명한다.[^2] 즉, '${counter}' 또는 더 단순히 '$counter' 형태로 화면에 값이 표시되도록 한다는 것이다.[^2]
정리하면 이 구간의 메시지는 다음이다.
- 문자열 리터럴:
'...'(작은따옴표 사용을 기본으로 설명)[^2] - 변수 값 삽입:
$counter(문자열 보간)[^2] - 결과: 숫자 값이 텍스트로 렌더링된다.[^2]
[!IMPORTANT] Text에 숫자를 바로 넣지 않는 이유
Text는 문자열 위치인데counter는int라서 타입이 맞지 않는다. 그래서'$counter'처럼 문자열 보간으로 표시한다.[^2]
3.7 Column을 쓰면 왜 위로 붙나: Column의 크기/정렬 기본값과 mainAxisAlignment[^3]
두 개의 텍스트를 Column으로 쌓았더니, 원래 Center로 가운데 있던 것이 위로 올라가 붙어 보인다고 말한다.[^19] 그 이유를 Column의 특성으로 설명한다:
- Column을 기본으로 쓰면 “전체 길이를 꽉 채우는 Column이 생긴다고 보면 된다”고 한다.[^3]
- 그리고 그 상태에서 기본 배치가 상단 쪽으로 붙어 보이게 된다.[^3]
그 다음 해결 방법으로 Column의 정렬 속성을 찾아보자며, alignment를 검색하면 2개가 나온다고 설명한다.[^7] 그 2개는:
mainAxisAlignmentcrossAxisAlignment[^7]
강의자는 먼저 mainAxisAlignment를 다루며, 여기에 center를 주는 예시를 든다.[^3] 저장해보면 다시 세로 방향 가운데로 정렬되는 것을 확인한다.[^3]
이때 “무슨 얘기냐”를 풀어서:
- Column은 위젯들을 “아래로 향하는 방향(세로)”으로 많이 담을 수 있는 컨테이너이고,[^3]
- 이 아래 방향이 Column의 메인 축(main axis) 이며,[^3]
- 그 메인 축 방향 정렬을
center로 주면, 위로 붙어 있던 것이 가운데로 내려온다.[^3]
또한 반대로 crossAxisAlignment는 메인축의 “반대 방향” 정렬(세로 Column이라면 가로 방향 정렬)을 다룬다고 말하며, 예를 들면 오른쪽 끝 정렬 같은 것도 할 수 있다고 언급한다.[^20] 즉, 두 축 정렬을 통해 세로/가로 모두 배치 제어가 가능하다는 것을 보여준다.[^20] 이후에는 다시 원래대로(가운데 정렬 등) 돌려놓고 다음 단계로 넘어간다.[^21]
[!TIP] Column 정렬을 이해하는 핵심 Column은 기본 축이 “세로(위→아래)”이므로, 세로 중앙 정렬은
mainAxisAlignment: MainAxisAlignment.center로 맞춘다. 가로 정렬은crossAxisAlignment로 제어한다.[^3][^20]
3.8 플러스 버튼 누르면 숫자 증가: onPressed → setState 내부에 counter++ 추가[^8]
마지막으로 “플러스 버튼을 눌렀을 때 이 숫자를 하나씩 증가”시키는 동작을 붙이면, 처음 프로젝트 생성 시 봤던 기본 예제와 같은 형태가 된다고 한다.[^8][^22]
강의자는 버튼 클릭 흐름을 이렇게 설명한다:
- 플러스 버튼을 누르면 현재 어떤 함수(강의 음성에서는 “체인지 메시지”처럼 들리지만, 맥락상 버튼의 콜백 함수)가 호출된다.[^8]
- 그리고 그 안에서
setState()로 상태를 변경하고 있다고 짚는다.[^8] - 그
setState()블록 안에 “추가로”counter변수를 증가시키는 코드를 작성하면 된다고 한다.[^8]
즉, 핵심은:
setState(() { counter++; })- 저장/실행하면 버튼을 누를 때마다 숫자가 증가한다.[^8]
그 결과, “맨 처음에 만들어져 있던 예제와 같은 형태”가 완성된다고 마무리한다.[^22]
[!IMPORTANT] 상태 변경 코드는 setState 안에 버튼 클릭 시 값만 바꾸면 끝이 아니라, 화면 갱신을 위해
setState()내부에서counter++를 수행해야 증가한 값이 UI에 반영된다.[^8]
4. 핵심 통찰[^23]
-
[h Flutter UI는 “위젯을 감싸는 방식”으로 레이아웃을 바꾼다.]
Text를 가운데로 보내는 것도 별도 좌표 계산이 아니라Center(child: ...)로 감싸는 구조적 조합으로 해결한다.[^6]- 실행: 현재 위젯을 다른 레이아웃 위젯으로 감쌀 수 있는지(예: Center, Padding, Column)부터 먼저 떠올린다.[^6]
-
[h 한 화면에 위젯이 여러 개 필요하면, 단일 child 구조를 children(List) 구조로 바꿔야 한다.]
Center하나로는 여러 위젯을 쌓을 수 없어서Column(children: [...])을 도입한다.[^13][^15]- 실행: “여러 개를 배치”하려는 순간
Row/Column과children을 고려한다.[^14][^15]
- 실행: “여러 개를 배치”하려는 순간
-
[h Column 정렬 문제는 mainAxis/crossAxis 축 개념으로 풀린다.] Column은 세로가 메인축이므로 세로 중앙은
mainAxisAlignment.center로, 가로 정렬은crossAxisAlignment로 다룬다.[^3][^20]- 실행: 레이아웃이 “위로 붙거나 한쪽으로 쏠리면” 축을 먼저 판별하고 해당 alignment 속성을 찾는다.[^7]
-
[h Text에 숫자를 보여주는 문제는 타입 문제가 아니라 “표현식 문법” 문제이기도 하다.]
int를 문자열로 바꿔야 하며, Dart에서는 작은따옴표 문자열 +$변수보간으로 처리한다.[^2]- 실행: UI 문자열이 필요할 때는
'$value'같은 보간을 습관화한다.[^2]
- 실행: UI 문자열이 필요할 때는
-
[c 버튼 클릭으로 값이 바뀌는 UI는 setState와 한 세트다.] 카운터 증가 코드는
setState()안에 들어가야 UI가 다시 그려져 숫자 변화가 보인다.[^8]- 실행: 값 변경이 UI에 반영되지 않으면 “setState 안에서 바꿨는지”부터 확인한다.[^8]
5. 헷갈리는 용어 정리[^24]
Widget(위젯): Flutter UI를 구성하는 모든 요소. 텍스트, 레이아웃, 버튼 등 화면 구성 단위로 계속 조합(감싸기)해서 UI를 만든다.[^6]
Center: child 1개를 화면(또는 부모 영역) 중앙에 배치하는 위젯.[^6]
Column: 여러 위젯을 세로 방향(위→아래) 으로 배치하는 위젯. 여러 자식은 children: [...]로 받는다.[^14][^15]
children: Column이 여러 자식을 받기 위한 리스트 속성. child(단일 자식)와 대비된다.[^15]
mainAxisAlignment: Column의 메인축(세로) 방향으로 자식들을 어떻게 정렬할지 결정하는 속성(예: center).[^3]
crossAxisAlignment: 메인축에 직교하는 축(가로) 방향 정렬을 결정하는 속성.[^20]
setState(): 상태가 바뀌었음을 Flutter에 알려 화면을 다시 그리게 하는 메커니즘. 카운터 증가 같은 변경을 여기 안에서 처리한다고 설명한다.[^8]
문자열 보간(String interpolation): 문자열 안에 변수 값을 넣는 Dart 문법. 강의에서는 작은따옴표 문자열에서 $counter 형태를 사용한다.[^2]
참고(콘텐츠 정보)[^25]
- 제목: Flutter 입문. 안드로이드, iOS 개발을 한 번에 #12 기본 샘플 앱 해설[^25]
- 채널: 오준석의 생존코딩[^25]
- 길이: 4분 34초[^25]
- 링크: https://www.youtube.com/watch?v=oA2PngShjm8[^25]
- 키워드: 안드로이드, Flutter, iOS[^25]
[^2]: @[02:11] "인티저 때문에 여기엔 스트링 자리이기 때문에 인 티저가 들어갈 수가 없어요" / @[02:23] "다트에서는 ... 작은 따옴표를 기본으로 씁니다" / @[02:31] "여기 변수 앞에 달러 를 붙여 주시면 됩니다"
[^3]: @[02:41] "컬럼을 기본적으로 쓰면 전체 길이를 꽉 채우는 컬럼" / @[03:06] "메인 ... 메인 엑시스 ... 센터" / @[03:35] "가운데로 오게 하겠다"
[^4]: @[00:00] 샘플코드로 돌아가겠다는 도입 / @[00:10] 버튼으로 숫자 증가 샘플 설명
[^5]: @[00:17] "자 기존에 있는 코드를 지우지는 않을 거에요" / @[00:22] "그냥 바로 추가를 해 보도록"
[^6]: @[00:38] "가운데로 옮겨 보려면 ... 센터라는 위젯으로 감싸면 되요" / @[00:46] "알트 엔터 ... 센터 위젯" / @[00:57] "저장하면 가운데로"
[^7]: @[02:56] "얼라인먼트 를 검색해보면 2개 ... 메인 엑시스 ... 크로스 ... "
[^8]: @[04:08] "플러스 버튼 눌렀을 때 ... 증가" / @[04:14] "스테이트 에서 변경 ... 여기다가 추가" / @[04:17] "카운터 변수를 하나 증가"
[^9]: @[00:00]~@[04:27] 전체 전개가 샘플 앱을 단계적으로 구성하는 흐름
[^10]: @[00:07] "글자가 있었고 아래의 숫자가" / @[00:10] "버튼을 눌르면 숫자가 하나씩 증가"
[^11]: @[00:22] "숫자를 저장할 변수를 하나 카운터 라고"
[^12]: @[00:59] "카운터를 표시할 텍스트" / @[02:04] "헬로 월드 게 아니라 숫자가 나오게"
[^13]: @[01:05] "센터 위젯 ... 위에서 아래로 ... 위젯이 필요한데 그게 컬럼"
[^14]: @[01:11] "그게 컬럼 이에요" / @[01:15] "세로 방향으로 위젯을 넣을 수 있어요"
[^15]: @[01:26] "컬럼 속성 중에 칠드런" / @[01:30] "차일드 가 아니고 ... 여러개" / @[01:36] "엔터 ... 배열"
[^16]: @[01:19] "기존에 있던 이 텍스트는 오려 내기로"
[^17]: @[01:45] "괄호를 하나 뺐어요 ... 맞춰주고"
[^18]: @[01:48]~@[01:54] "텍스트를 하나더 복사해서 붙여"
[^19]: @[01:59] "이게 위로 올라 붙었는데"
[^20]: @[03:46] "크로스 ... 반대 ... 끝으로 정열"
[^21]: @[03:58] "다시 돌아가서 원래대로 해 놓고"
[^22]: @[04:27] "맨 처음에 만들어져 있던 그런 예제와 같은 형태"
[^23]: @[00:38]~@[04:27] Center/Column/alignment/setState 흐름 전반에서 도출
[^24]: @[00:38] Center / @[01:11] Column / @[01:26] children / @[03:06] mainAxisAlignment / @[03:46] crossAxisAlignment / @[04:14] setState / @[02:31] $ 보간 설명 근거
[^25]: 사용자가 제공한 메타데이터(제목/채널/길이/링크/키워드)