본 책에 앞서 Swift 기초 문법에 대해서는 이미 배웠으리라 생각됩니다. 아직 struct, class, extension, 익명함수 등이 익숙하지 않아도 됩니다. Do it 입문서는 Xcode를 이용해서 아이폰 UI(Toolbar, Tabbar, 화면전환, StackView, Lable, Button 등) 를 그리는 것을 배우는 책이기 때문에 아이폰 개발을 위해 "기초문법 - UI - 주요기능코딩(SNS인증, Rest APi호출, DB연동 등)" 에서 UI는 화면을 그리는 것이라 문법이 약해도 상관없이 따라할 수 있습니다.
안드로이드와 비교해서 xml기반보다는 GUI기반으로 다가와 조금더 귀찮고, 실수로 잘못된 여지가 좀 있는 것 같지만 아직 Swift코딩에 익숙하지 않아도 빨리 따라할 수 있도록 잘 구성된 책입니다. 특히, 다른 책들은 예제소스를 따라하기에 반복적인 구성(버튼, 그림, 동일한 기능)으로 시간이 오래 걸리는데, 이책은 중복을 최소화하여 핵심 위주로 예제를 구성해서 따라하기 편하게 되어 있습니다.
개정 5판이라 그런지, 따라해본 예제들은 모두 문법적 오류나 오타가 없었고, flutter처럼 버전에 따른 지원불가로 인한 오류도 없었습니다. 따라하는 과정에서 잘 안되는 경우는 UI를 그렸다가 지우고 다시 그리는 과정에서 Editor에 보이는 소스가 아닌 설정에 연결된 것을 지우지 않거나, 사진이미지를 너무 큰 것을 이용해서 제대로 보이지 않는 경우(이미지가 작은 사진들은 크기를 줄여서 프로젝트에 등록 필요)라 사진의 크기만 적절히 수정하면 됩니다.
다른 책에서도 프로젝트 생성시 "Single View App"을 선택하라는 말이 있는데, 실제 Xcode화면에는 "Single View App"이란 단어가 없습니다. 그것이 가리키는 것은 바로 "App" 화면입니다. 이 책은 모든 과정에서 메뉴 선택하는 화면 하나하나를 보여주고 있어서 초보자들도 쉽게 배울 수 있습니다.
프로젝트 파일 살펴보기
가. AppDelegate : 앱의 실행주기를 관리하는 클래스 파일. 앱을 실행하거나 종료 또는 백그라운드를 실행할 때 하는 일을 관리
나. SceneDelegate : 사용자 인터페이스의 실행주기를 관리하는 클래스 파일
다. ViewController : 화면에 보이는 뷰에서 처리하는 내용의 소스가 담긴 클래스. 일반적으로 프로그래머는 이 파일에서 코딩하게 되며 뷰하나당 클래스 하나가 대응됩니다. 따라 스토리보드에서 여러 개의 뷰를 추가하면 뷰의 갯수 만큼 뷰 컨트롤러 클래스를 추가해야 합니다.
라. Main.storyboard : 앱의 내용을 시각적으로 쉽게 이해하고 프로그래밍할 수 있도록 그림으로 표현한 파일입니다. 스토리보드를 통해 화면에 보이는 내용 및 뷰 간의 연결 관계 등을 표현할 수 있습니다.
마. Assets.xcassets : 앱의 아이콘을 보관하는 저장소입니다.
바. LaunchScreen.storyboard : 앱이 실행될 때 잠시 나타나는 스플래시 화면을 만드는 스토리보드
사. Info.plist : 앱이 실행되는데 필요한 정보를 정하는 파일(권한 설정 등) : 권한 설정 기능을 따로 코딩하는 것이 아니라, 이 파일에 설정해 놓으면 앱에서 필요시 권한 추가 요청 기능이 실행됨(그러고 보면 아이폰에서 권한 요구하는 화면은 모두 동일한 것 같습니다.)
Objects Library 단축키 : command + shift + L 을 누르거나, 메인스토리 화면 위의 "+" 클릭하면 됩니다. Object를 많이 사용한다면 command + shift + L + option 를 누르면, Object를 선택하더라도 Object 팔레트 창이 닫히지 않아 계속 이용할 수 있습니다.
아웃렛 변수/액션 함수 추가/삭제시 주의 사항
ViewController의 소스에서 삭제할지라도 실제 생성된 액션함수는 사라진 것이 아니라서 반드시 Show the connection inspector 에서 해당 객체를 삭제해줘야 합니다. 실제 이걸 삭제하지 않아서 오류가 발생하기도 합니다.
iOS 시뮬레이터는 좌우 회전, 흔들기 효과,멀티 터치(option키 누르고 클릭), GPS(수동입력) 테스트가 가능합니다. 다만, GPS를 이용한 실제 위치 취득, 전화 착신시 동작, 카메라 기능, 가속도 센서 는 테스트할 수 없습니다.
개발자 사이트에 가입후 개발할 어플리케이션까지 등록을 하면, 아래와 같이 4개의 키가 자동발급됩니다. 우리는 여기서 REST API 키를 이용할 계획입니다.
개발자 사이트에서 REST API 키 확인
2. http 통신 패키지 설정
pubspec.yaml 파일의 dependencies 아래에 http를 추가합니다. 만약 null safety 지원 등으로 오류가 발생하면, https://pub.dev/packages/http/versions 에 접속해서 PC에 설치된 SDK 버전에 맞는 http버전을 입력하시면 됩니다. 참고로, 제 SDK 는 2.16.XX입니다.
dependencies:
flutter:
sdk: flutter
http: ^0.13.3
버전에 따라, Null safety 가 존재하고, 존재하지 않는 버전이 있음.
3. http 통신 확인
main.dart 파일에서 http를 import한 후, 플로팅 버튼을 클릭하면, 특정 페이지를 읽어 화면에 출력하는 페이지(골격)을 만들어봅니다. 비동기(async)를 이용해서 http.get(url)을 수행하면 됩니다.
먼저 jsonData를 가져올 함수를 비동기함수로 생성하고, url을 처음 발급받은 REST API 키를 이용해서 카카오 api 서버를 호출합니다.
Future<String> getJSONData() async {
var query = _editingController?.value.text;
String url = "https://dapi.kakao.com/v3/search/book?target=title&query=${query}&page=${page}";
var response = await http.get(Uri.parse(url),
headers: {"Authorization" : "KakaoAK cf********************6"});
setState(() {
var dataConvertedToJSON = json.decode(response.body);
List result = dataConvertedToJSON['documents'];
data.addAll(result);
});
return response.body;
}
카카오 개발문서에 보면, Request할 때, 헤더값으로 Authorization에 Authorization: KakaoAK ${REST_API_KEY} 을 입력합니다. 도서, 비디오, 이미지 등 조회 내용에 따라 질의 항목, 결과 항목이 다르니 확인하시고 이용하시기 바랍니다. 카카오 개발사이트 > Docs > Daum Search > REST API
카카오 도서 관련 REST API, 조회건수는 default 값이 10
ListView.builder를 이용해서, Card() 안에 리스트 건에 대한 내용을 표시합니다. 개발하시다가 이미지가 화면을 벗어나면 오류 표시가 나는데, MediaQuery.of(context).size.width- 150 으로 하면, 화면에 모두 표시됩니다. 여기서 -150은 디바이스 전체 width에 들어가는 내용이, "이미지 + 글박스"로 구성되는데, 여기서 이미지 사이즈보다 큰 값을 입력하면 됩니다.
아들 교육용으로 구매한 것이 액정이 파손되어 사용하고 있지 않아, 액정 교체를 해볼까 해서 인터넷에 찾아보니, 네이버 블로그에는 대부분 액정 교체 서비스 광고글이 98%였고, 유투브는 액정 교체 영상이 잘 나와 있습니다. 직접 해보면서 전문가가 아닌 일반 사람이 교체하는 입장에서 글을 써봅니다.
결론적으론 제 태블릿은 사용을 못하게 되었습니다. 게다가 서비스센터에서도 고객이 임의로 손을 덴 제품에 대해서는 서비스 거부를 하기에 직접 하실 경우, 태블릿이 터치가 안될 수도 있다는 걸 유념하시기 바랍니다.
1. 액정을 인터넷에서 구매
쇼핑몰에 액정 가격이 4~5만원 정도였습니다. 구매 내용물은 심플합니다. 액정(전자신호를 태블릿에 전달해주는 꼬리 달린) 과 도움될만 한 도구들입니다. 도구는 거의 사용하지 않고 집에 있는 일자 드라이버를 사용했습니다.
액정과 작업 도구
2. 우선 후면부와 전면부를 분리해야 합니다.
태블릿의 까만 부분과 흰색 부분을 분리하는 것인데, 생각보다 잘 안됩니다. 요령이 없어서 그런지 힘도 제법들어가구요. 저는 여러번 해보니, 태블릿 옆에 MicroSD카드 넣는 곳에 드라이버를 넣고 전면부(액정부분)을 밀어서 벌렸습니다. 그리고 전.후면부 사이를 드라이버로 벌리면서 분리했습니다. 유투브 영상을 보시면 이해가 잘 되실겁니다. 5cm라도 일단 틈을 만들면 그다음부터는 힘껏 하셔도 제품이 튼튼해서 부서지지 않고 분리됩니다.
3. 기존 액정 분리
어떤 분들은 열처리 없이 잘 분리된다고 하고, 어떤 분은 열처리를 하면서 분리하는 영상이 있을 겁니다. 액정은 테두리 밑에 본드로 붙어 있는 상태입니다. 그래서 열처리 없이는 사실 엄청 어렵습니다. 저는 마침 집에서 교체를 하고 있어 하일라이트로 10cm 정도 떨어뜨려서 살짝 살짝 온도를 높이고 분리하고 또 온도를 높이고 분리했습니다. 액정을 분리하는 과정에서 액정이 깨지면서 미세한 유리가 조각이 엄청 나옵니다. ㅠㅠ 그래서 청소를 고려해서 주변을 깔끔하게 정리하고 시작하셔야 합니다.
액정을 분리하면서 액정이 더 깨지고 유리조각이 많이 생김
4. 액정 교체
교체는 쉽습니다. 기존 액정 분리후, 새로운 액정을 붙이고 뒤에 전선 한개만 연결하면 됩니다. 기존 액정을 잘 붙이기 위해 본드를 이용하시거나, 다시 열처리를 한 후 붙이시면 잘 붙습니다.
액정의 신호를 태블릿으로 연결하는 전선
5. 작업 결과 확인 및 청소
후면부를 붙이기 전, 전원을 켜서 제대로 작동하는 확인 하시기 바랍니다. 정상적으로 터치가 되면 주변 유리들을 깔끔하게 정리하시기 바랍니다.
#. 주의 사항
저는 지금 교체 이후 터치 반응이 오지 않아, 열처리 과정에서 태블릿 본체에 문제가 생겼나? 구매한 액정이 문제가 있나? 싶어 삼성서비스 센터을 찾아갔습니다. 센터 직원은 고객이 임의로 작업한 제품에 대해서는 서비스 거부 권한이 있다고 체크해 주지 않습니다. 그래서 태블릿? 액정? 어디가 문제인지 알 수가 없었습니다. 액정의 전선은 태블릿에 잘 연결되어 있다고 육안으로 확인만 해주셨습니다.
인터넷 블로그에 10~12만원 선에서 액정 교체 서비스 광고가 많습니다. 액정값을 제외하면 5~7만원의 공임비가 들어가는 것입니다. 직접 교체하면 5~7만원을 아낄 수도 있지만, 저처럼 잘못된 경우 오히려 이후 점검/수리비가 더 나올 수도 있어서 정말 필요한 태블릿이라면, 서비스를 맡기시는 것을 추천합니다.
저는 나중에 사용하지 않는 태블릿이 생기면, 지금 사용 못하는 태블릿이랑 비교해보면서 무엇이 문제인지 확인해 보려합니다.
안드로이드 스튜디오 Run > Edit ConfigurationAdditional run args 에 항목 추가
사실 의미도 잘 이해하지 못한채 null safety 를 맞추려고 ?, ! 를 무분별하게 남발하는 것보다는 소스를 깔끔하게 관리하면서, 코딩하는 것도 방법입니다. 특히, Do it 플러터 외에 다른 책들도 ?, ! 이 없던 예전 플러터 버전에 작성된 책들이 많아 그대로 따라 코딩하려면 이 방식이 제일 좋습니다.
이렇게 설정해도 실행과정에서 Null 값 오류가 발생되면 똑같이 Error가 발생합니다. 상황에 따라 소스를 수정하거나, ?, !를 추가해서 오류를 잡을 수 있습니다.
요약 • Run > Edit Configurations > Additional run args 에 [ -- no-sound-null-saftey ] 를 추가하여 null safety 검증을 중지할 수 있다.
ListView.builder를 이용해서 리스트뷰를 만들고, 이벤트(클릭, 더블클릭 등) 동작 처리
아래의 문법을 활용해서 Card안에 이미지, 텍스트 위젯을 코딩하면 됩니다. ListView.builder(itemBuilder : (context, position) { return Card( // 이 부분에 위젯을 이용한 데이터 표시 ); , itemCount : list!.length), // List 만큼의 스크롤을 생성해 줍니다. }
위는 교제에 있는 기본적인 소스입니다. 코딩을 따라하시다가 null safety 오류가 나오면 변수타입 선언 및 이용시에 ?, ! 을 적절히 이용하시면 오류가 잡히실 겁니다. 플러터는 2.0부터 강력한 null safety 정책 적용했습니다. 기본적으로 모든 변수는 'non nullable' 입니다. 하지만 개발 과정에 당장 초기값을 설정하지 않는다면 오류가 발생할 수 있습니다. 그래서 변수타입 뒤에 '?' 울 붙여서 nullable 이라고 선언해줍니다. (ex. int? age) 선언은 했지만, 실제 소스검증 과정에서 null값인 경우 오류가 발생할 것으로 예상되는 부분에 대해서는 '!' 을 붙여서 '이 부분은 로직상 무조건 값이 들어가 있다고 개발자가 표시'해야 합니다.
null safety 정책에 따른 ?, ! 를 추가한 소스
// FirstPage.dartimport'package:flutter/material.dart';
import'../animalItem.dart';
classFirstAppextendsStatelessWidget{
final List<Animal>? list;
FirstApp({Key? key, this.list}) : super(key:key);
@overrideWidget build(BuildContext context){
return Scaffold(
body: Container(
child: Center(
child: ListView.builder(itemBuilder: (context, position) {
return Card( // 이 부분에 위젯을 이용해 데이터 표시
child: Row(
children: <Widget>[
Image.asset(list![position].imagePath!,
height: 100,
width: 100,
fit: BoxFit.fitHeight),
Text(list![position].animalName!)
],
),
);
},
itemCount: list!.length),
),
),
);
}
}
ListView 를 이용하려면 생명주기(initState(), dispose())에 따라 개발
initState()에서 TabController를 생성하고, 리스트를 만듭니다. dispose()에서 메모리 누수 방지를 위해 controller를 제거합니다. 그리고 build()에서 TabBarView, TabBar를 만듭니다. 앞에 2개에는 모두 controller가 들어가 있어야 합니다.
ListView.Builer 안에 Card를 GestureDetector 위젯으로 감싼 후, 이벤트를 정의하면 됩니다. 이벤트는 터치(탭, 클릭), 두번 터치(더블 클릭), 길게 누르기 , 끌기 등이 있습니다.
return GestureDetector(
child : Card( // 이 부분에 위젯을 이용해 데이터 표시
child: Row(
children: <Widget>[
Image.asset(list![position].imagePath!,
height: 100,
width: 100,
fit: BoxFit.fitHeight),
Text(list![position].animalName!)
],
),
),
onTap: () {
AlertDialog dialog = AlertDialog(
content: Text('이 동물은 ${list![position].kind}', style: TextStyle(fontSize: 30),
),
);
showDialog(context: context, builder: (BuildContext context)=> dialog);
},
);
요약 • ListView.Builer(itemBuilder:(context, position)을 이용해서 리스트뷰를 생성 • itemCount : list!.length 를 이용해서 스크롤 생성 • initState(), dispose() 에서 컨트롤 생성 및 파기 • GestureDetector 위젯으로 터치 등 이벤트 처리
안드로이드 앱을 개발하려면 구글에서 지정한 디자인 지침이 있습니다. 머티리얼 디자인(material Design). 개발하는 앱의 특별함, 독특한 디자인도 좋지만, 사용자 입장에서 직관적이고 일관된 UI를 제공해야 거부감없이 자연스럽게 이용 가능하기에 플러터는 아래와 같이 머티리얼 디자인 라이브러리를 제공합니다.
import'package:flutter/material.dart';
voidmain(){
runApp(constMyApp());
}
classMyAppextendsStatelessWidget {constMyApp({Key? key}) : super(key: key);// This widget is the root of your application.
@override
Widget build(BuildContext context){
returnMaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MaterialFlutterApp(),
);
}
}
classMaterialFlutterAppextendsStatefulWidget {
@override
State<MaterialFlutterApp> createState()=> _MaterialFlutterApp();
}
class _MaterialFlutterAppextendsState<MaterialFlutterApp> {
@override
Widget build(BuildContext context){
returnScaffold(
);
}
}
Scafold 를 이용한 머티리얼 디자인
위의 위젯을 build 할때, Scafold() 내용의 구조는 아래와 같습니다.
class _MaterialFlutterAppextendsState<MaterialFlutterApp> {
@override
Widget build(BuildContext context){
returnScaffold(
appBar: AppBar(
title: Text('Materail Design App'),
),
floatingActionButton: FloatingActionButton(child: Icon(Icons.add),
onPressed: () {
},
),
body: Container(
// Center is a layout widget. It takes a single child and positions it// in the middle of the parent.
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.android),
Text('android')
],
),
),
);
}
}
추가로, 아이콘을 직접 제작하기 보다는 기본적으로 제공하는 이미지를 활용하는 것이 좋습니다. 아래의 주소에 들어가시면, 다양한 이미지를 한번에 볼 수 있으니 참고하시기 바랍니다.
pubspec.yaml 등록시 파일단위로 할 수도 있고, 폴더째로 할 수도 있습니다. 또한 asset/images, images 등 폴더명에 대한 제약사항은 없고 프로젝트 바로 아래에만 생성해 주시면 됩니다. 등록 후, "Pub get", "Pub update" 한번 클릭해주세요.
프로젝트내 image 폴더를 만들어 이미지 추가 및 pubspec.yaml 수정
이미지를 추가하는 방식은 2가지가 있습니다. 프로젝트 내에 있는 asset 항목은 Image.asset으로 외부에 있는 것은 Image.network로 코딩하시면 됩니다.
body: Container(
// Center is a layout widget. It takes a single child and positions it// in the middle of the parent.
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Image.asset('images/flutter.png'),
Image.network('https://w7.pngwing.com/pngs/14/381/png-transparent-flag-fluttering-red-flag-miscellaneous-flag-flag-of-india-thumbnail.png')
],
),
),
플러터의 이미지가 보이지 않는다면,
코딩할 때, 항목의 경로를 정확하게 오타없이 작성했는지 확인
pubspec.yaml 파일의 오타, 경로 확인 후, "Pub get" 실행
가상디바이스(Emulator) 재실행
사실 저도 이 포스트를 하면서 이미지가 나오지 않아 1시간 동안 위의 1~2번을 몇번을 했습니다. 폴더가 무조건 asset/images 여야 하나? 파일 단위가 아니라 폴더 단위로 해야 하나? 결국엔 가상디바이스 재실행까지 3번정도 하나가 어느순간 짜자~~~안...ㅠㅠ. 뭐가 문제인지는 정확히 알려나 주지..;;;
플러터의 이미지 크기 조절하는 fit 옵션값들
이미지가 원하는 규격이 아닐 경우, fit 옵션에 따라 아래와 그림과 같이 다양하게 표현할 수 있습니다.
pubspec.yaml 에 폰트를 등록한 후 사용합니다. 등록 과정에서 yaml을 탭간격이 띄어쓰기 2칸인데 줄맞춤이 맞질 않거나, 리소스명을 변경했다면, hot-reload가 실패할 경우가 많아 AVD를 재실행해야 합니다. 처음에 한글명을 이용했는데, 스튜디오에서는 인식 과정에 문제는 없었으나, 폰트가 변경되지 않은 것 같아 영문으로 변경하고, AVD 재실행하니 폰트가 변경되었습니다.
무료 폰트는 인터넷에 검색하면 많이 있습니다. 저는 relation2 라는 사이트에서 무료라인센스로 되어 있는 것은 확인 후 다운 받았습니다.