2020년 1월 20일 월요일

2019년 팟빵에 올라왔던 로봇시대? 어디까지 왔는가? 고태봉 센터장님의 방송 입니다.

출근과 퇴근을 할 때 매일 듣고 있는 팟빵 방송에 로봇 특집이 나와서 영상 링크를 걸어 봅니다. 기술이 하루가 다르게 발전하고 있는 것을 볼 수 있습니다.
https://www.youtube.com/watch?time_continue=4784&v=t4VoR1HQE-o&feature=emb_logo

7분과 8분, 13분 17분, 40분에 보시면 각각 상용화되고 있는 로봇 영상들이 나옵니다.
하루가 다르게 발전하고 있는 모습들을 멋진 설명과 함께 보실 수 있습니다.
2020년 1월에는 CES 정리한 동영상도 올라왔네요.
https://www.youtube.com/watch?v=1zQDNFM1zP8
스크린샷 2019-07-08 오후 8.20.01.png
스크린샷 2019-07-08 오후 8.20.21.png
스크린샷 2019-07-08 오후 8.19.14.png
포드사에서 만든 마더쉽에서 내려서 배송을 하를 로봇의 홍보 영상입니다.

2020년 1월 11일 토요일

iOS 13.*에 추가된 SwiftUI의 입력 처리하기 입니다.

세번째 데모는 입력 처리 추가하기 입니다.
아래의 링크에서 프로젝트를 다운로드 받아서 StartingPoing폴더에 있는 프로젝트를 오픈하면 됩니다.
사용자가 랜드마크를 보고 별표 표시를 하는 경우
스크린샷 2019-10-07 오후 4.18.52.png
StartingPoing폴더에 있는 시작 프로젝트를 오픈 합니다.
LandmarkRow파일에서 아래와 같이 수정합니다.
import SwiftUI
struct LandmarkRow: View {
var landmark: Landmark
var body: some View {
    HStack {
        landmark.image
            .resizable()
            .frame(width: 50, height: 50)
        Text(landmark.name)
        Spacer()
        
        if landmark.isFavorite {
            Image(systemName: "star.fill")
                .imageScale(.medium)
        }
    }
}
}
Section 2: List View를 필터링하기
사용자가 좋아하는 것만 필터링할 수 있습니다.
View에 상태를 추가하기 위해 @State속성을 사용할 수 있습니다.
LandmarkList를 아래와 같이 수정합니다.
import SwiftUI
struct LandmarkList: View {
@State var showFavoritesOnly = false

var body: some View {
    NavigationView {
        List(landmarkData) { landmark in
            if !self.showFavoritesOnly ||
                landmark.isFavorite {
                NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                    LandmarkRow(landmark: landmark)
                }
            }
        }
        .navigationBarTitle(Text("Landmarks"))
    }
}
}
Section 3: 상태를 토글하기 위해 컨트롤을 추가합니다.
유저가 리스트 필터링을 컨트롤하도록, 컨트롤을 추가합니다.
LandmarkList를 수정합니다.
import SwiftUI
struct LandmarkList: View {
@State var showFavoritesOnly = true

var body: some View {
    NavigationView {
        List {
            ForEach(landmarkData) { landmark in
                if !self.showFavoritesOnly ||
                    landmark.isFavorite {
                    NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                        LandmarkRow(landmark: landmark)
                    }
                }
            }
        }
        .navigationBarTitle(Text("Landmarks"))
    }
}
}
다시 아래와 같이 추가합니다.
import SwiftUI
struct LandmarkList: View {
@State var showFavoritesOnly = true

var body: some View {
    NavigationView {
        List {
            Toggle(isOn: $showFavoritesOnly) {
                Text("Favorites only")
            }
            
            ForEach(landmarkData) { landmark in
                if !self.showFavoritesOnly ||
                    landmark.isFavorite {
                    NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                        LandmarkRow(landmark: landmark)
                    }
                }
            }
        }
        .navigationBarTitle(Text("Landmarks"))
    }
}
}
스크린샷 2019-10-07 오후 4.11.38.png
Section 4: Storage를 위해 Observable Object를 사용한다.
좋아하는 랜드마크를 컨트롤하도록 준비하기 위해 먼저 observable object로
랜드마크 데이터를 저장해야 합니다.
observable object는 storage로 부터 SwiftUI환경으로 뷰를 바운드할 수 있습니다.
SwiftUI는 뷰에 영향을 주는 observable object에 대한 변경을 감시하고,
그리고 변경후에 뷰의 올바른 버전을 표시합니다.
Models폴더에 UserData.swift파일을 추가해서 아래와 같이 코딩 합니다.
import SwiftUI
import Combine
final class UserData : ObservableObject {
@Published var showFavoritesOnly = false
@Published var landmarks = landmarkData
}
Section 5: 뷰에 Model Object을 붙이기
UserData 오브젝트를 생성한 후에 앱의 데이터 저장으로 뷰를 적용하도록 업데이트합니다.
LandmarkList를 수정합니다.
import SwiftUI
struct LandmarkList: View {
//다음과 같이 수정한다.
@EnvironmentObject var userData: UserData

var body: some View {
    NavigationView {
        List {
            Toggle(isOn: $userData.showFavoritesOnly) {
                Text("Favorites only")
            }
            
            ForEach(userData.landmarkData) { landmark in
                if !self.userData.showFavoritesOnly ||
                    landmark.isFavorite {
                    NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                        LandmarkRow(landmark: landmark)
                    }
                }
            }
        }
        .navigationBarTitle(Text("Landmarks"))
    }
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
LandmarkList()
.environmentObject(UserData())
}
}
SceneDelegate도 수정합니다.
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

    // Use a UIHostingController as window root view controller
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(
            rootView: LandmarkList()
                .environmentObject(UserData())
        )
        self.window = window
        window.makeKeyAndVisible()
    }
}
LandmarkDetail을 수정합니다.
import SwiftUI
struct LandmarkDetail: View {
@EnvironmentObject var userData: UserData
var landmark: Landmark
var landmarkIndex: Int {
    userDAta.landmarks.firstIndex(
        where: { $0.id == landmark.id })!
}

var body: some View {
    VStack {
        MapView(coordinate: landmark.locationCoordinate)
            .frame(height: 300)

        CircleImage(image: landmark.image)
            .offset(x: 0, y: -130)
            .padding(.bottom, -130)

        VStack(alignment: .leading) {
            Text(landmark.name)
                .font(.title)

            HStack(alignment: .top) {
                Text(landmark.park)
                    .font(.subheadline)
                Spacer()
                Text(landmark.state)
                    .font(.subheadline)
            }
        }
        .padding()

        Spacer()
    }
    .navigationBarTitle(Text(verbatim: landmark.name), displayMode: .inline)
}
}
struct LandmarkDetail_Previews: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
.environmentObject(UserData())
}
}
Section 6: 각 랜드마크에 대한 Favorite 버튼을 생성합니다.
LandmarkDetail을 수정합니다.
import SwiftUI
struct LandmarkDetail: View {
@EnvironmentObject var userData: UserData
var landmark: Landmark
var landmarkIndex: Int {
    userData.landmarks.firstIndex(where: { $0.id == landmark.id })!
}

var body: some View {
    VStack {
        MapView(coordinate: landmark.locationCoordinate)
            .edgesIgnoringSafeArea(.top)
            .frame(height: 300)
        
        CircleImage(image: landmark.image)
            .offset(x: 0, y: -130)
            .padding(.bottom, -130)
        
        VStack(alignment: .leading) {
            HStack {
                Text(verbatim: landmark.name)
                    .font(.title)
                
                Button(action: {
                    self.userData.landmarks[self.landmarkIndex]
                        .isFavorite.toggle()
                }) {
                    if self.userData.landmarks[self.landmarkIndex]
                        .isFavorite {
                        Image(systemName: "star.fill")
                            .foregroundColor(Color.yellow)
                    } else {
                        Image(systemName: "star")
                            .foregroundColor(Color.gray)
                    }
                }
            }
            
            HStack(alignment: .top) {
                Text(verbatim: landmark.park)
                    .font(.subheadline)
                Spacer()
                Text(verbatim: landmark.state)
                    .font(.subheadline)
            }
        }
        .padding()
        
        Spacer()
    }
}
}
struct LandmarkDetail_Preview: PreviewProvider {
static var previews: some View {
let userData = UserData()
return LandmarkDetail(landmark: userData.landmarks[0])
.environmentObject(userData)
}
}
실행하면 다음과 같습니다.

스크린샷 2019-10-07 오후 4.46.32.png
스크린샷 2019-10-07 오후 4.46.40.png

iOS 13.*에 추가된 SwiftUI의 리스트와 네비게이션 사용입니다 .#2

두번째로 리스트와 네비게이션 사용하기 입니다.
아래의 예제가 상당히 재미있습니다.
기존에 스토리보드를 많이 사용하던 개발자라면 한번 테스트해 보세요.
아래의 링크에서 샘플을 받아서 StartingPoint폴더에 있는 프로젝트를 오픈 해야 합니다.
새로운 파일들이 많이 추가되어 있다. 새로 제공된 시작 프로젝트를 오픈 합니다.
Section 2: Row View 생성하기
스크린샷 2019-10-07 오후 3.08.41.png
각 랜드마크의 상세를 표시하는 row를 생성합니다.
SwiftUI템플릿을 선택해서 LandmarkRow.swift를 추가합니다.
아래와 같이 입력합니다.
import SwiftUI
struct LandmarkRow: View {
var body: some View {
HStack {
landmark.image
.resizable()
.frame(width: 50, height: 50)
Text(landmark.name)
}
}
}
struct LandmarkRow_Previews: PreviewProvider {
static var previews: some View {
LandmarkRow(landmark: landmarkData[0])
}
}
Section 3: Row Preview를 커스터마이징하기
Xcode의 canvas는 자동으로 현재 에디터의 어떤 형식도 감지하고 표시합니다.
Preview provider는 하나 또는 그 이상의 뷰들을 리턴합니다. 사이즈와 디바이스로 셋팅된 옵션과 함께 합니다.
import SwiftUI
struct LandmarkRow: View {
var body: some View {
HStack {
landmark.image
.resizable()
.frame(width: 50, height: 50)
Text(landmark.name)
}
}
}
struct LandmarkRow_Previews: PreviewProvider {
static var previews: some View {
Group {
LandmarkRow(landmark: landmarkData[0])
.previewLayout(.fixed(width:300, height: 70))
LandmarkRow(landmark: landmarkData[1])
.previewLayout(.fixed(width:300, height: 70))
}
.previewLayout(.fixed(width:300, height: 70))
}
}
LandmarkList라는 SwiftUI템플릿을 사용한 파일을 추가합니다. 아래와 같이 수정합니다.
import SwiftUI
struct LandmarkList: View {
var body: some View {
List {
LandmarkRow(landmarK: landmarkData[0])
LandmarkRow(landmarK: landmarkData[1])
}
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
LandmarkList()
}
}
Section 5: 동적인 리스트 만들기
컬렉션에서 직접 로우를 생성할 수 있습니다.
아래와 같이 LandmarkList를 수정합니다.
import SwiftUI
struct LandmarkList: View {
var body: some View {
List(landmarkData, id: .id) { landmark in
LandmarkRow(landmark: landmark)
}
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
LandmarkList()
}
}
Models폴더에 있는 Landmark.swift를 살펴봅니다.
아래와 같이 id:을 삭제하고 코드를 수정합니다.
import SwiftUI
struct LandmarkList: View {
var body: some View {
List(landmarkData) { landmark in
LandmarkRow(landmark: landmark)
}
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
LandmarkList()
}
}
실행하면 아직은 상세화면만 출력됩니다.
스크린샷 2019-10-07 오전 11.52.40.png
Section 6: 리스트와 상세 사이에 네비게이션
import SwiftUI
struct LandmarkList: View {
var body: some View {
NavigationView {
List(landmarkData) { landmark in
NavigationLink(destination: LandmarkDetail()) {
LandmarkRow(landmark: landmark)
}
}
.navigationBarTitle(Text("Landmarks"))
}
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
LandmarkList()
}
}
Section 7: Child View로 데이터 전달하기
LandmarkDetail 뷰는 상세 정보가 하드 코딩되어 있습니다.
데이터를 넘겨받도록 합니다.
LandMarkDetail을 아래와 같이 수정합니다.
import SwiftUI
struct LandmarkDetail: View {
var landmark: Landmark
var body: some View {
    VStack {
        MapView(coordinate: landmark.locationCoordinate)
            .frame(height: 300)

        CircleImage(image: landmark.image)
            .offset(x: 0, y: -130)
            .padding(.bottom, -130)

        VStack(alignment: .leading) {
            Text(landmark.name)
                .font(.title)

            HStack(alignment: .top) {
                Text(landmark.park)
                    .font(.subheadline)
                Spacer()
                Text(landmark.state)
                    .font(.subheadline)
            }
        }
        .padding()

        Spacer()
    }
    .navigationBarTitle(Text(verbatim: landmark.name), displayMode: .inline)
}
}
struct LandmarkDetail_Previews: PreviewProvider {
static var previews: some View {
LandmarkDetail(landmark: landmarkData[0])
}
}
LandmarkRow는 아래와 같이 수정합니다.
import SwiftUI
struct LandmarkRow: View {
var landmark: Landmark
var body: some View {
    HStack {
        landmark.image
            .resizable()
            .frame(width: 50, height: 50)
        Text(verbatim: landmark.name)
        Spacer()
    }
}
}
struct LandmarkRow_Previews: PreviewProvider {
static var previews: some View {
Group {
LandmarkRow(landmark: landmarkData[0])
LandmarkRow(landmark: landmarkData[1])
}
.previewLayout(.fixed(width: 300, height: 70))
}
}
Models폴더에 있는 Landmark는 프로토콜만 추가합니다.
import SwiftUI
import CoreLocation
struct Landmark: Hashable, Codable, Identifiable {
var id: Int
var name: String
fileprivate var imageName: String
fileprivate var coordinates: Coordinates
var state: String
var park: String
var category: Category
LandmarkList는 아래와 같이 수정합니다.
import SwiftUI
struct LandmarkList: View {
var body: some View {
NavigationView {
List(landmarkData) { landmark in
NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
LandmarkRow(landmark: landmark)
}
}
.navigationBarTitle(Text("Landmarks"))
}
}
}
struct LandmarkList_Previews: PreviewProvider {
static var previews: some View {
ForEach(["iPhone SE", "iPhone XS Max"], id: .self) { deviceName in
LandmarkList()
.previewDevice(PreviewDevice(rawValue: deviceName))
.previewDisplayName(deviceName)
}
}
}
진입점 역할을 수행하는 코드는 SceneDelegate에 있습니다.
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
    // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
    // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).

    // Use a UIHostingController as window root view controller
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: LandmarkList())
        self.window = window
        window.makeKeyAndVisible()
    }
}
실행하면 다음과 같이 네비게이션이 되고 상세 화면으로 전환할 수 있습니다.

스크린샷 2019-10-07 오후 3.00.29.png
스크린샷 2019-10-07 오후 3.00.36.png

iOS 13.*에 추가된 SwiftUI 연습입니다. #1

다른 코드들은 큰 변화가 없는데 SwiftUI가 상당히 좋아 보입니다. 아직은 사용하려면 연습이 필요하고 익숙해지는 시간이 필요하지만 꽤 잘 만들어져있습니다.
선언적인 UI구성과 미리보기등이 가능합니다.
스크린샷 2019-10-07 오전 11.09.13.png
스크린샷 2019-10-07 오전 11.10.59.png
이런 앱을 직접 만들어볼 수 있는 튜토리얼 사이트가 무척 재미있게 제공됩니다.
Landmarks라는 싱글뷰 앱을 SwiftUI기반으로 만든다. 미리 리소스를 다운로드하면 됩니다.
기본적으로 추가된 ContentView에는 2개의 구조체가 있습니다. 미리보기는 macOS 10.15에서 지원됩니다.
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Hello World")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
그냥 실행해서 결과를 보면 Hello World가 출력됩니다.
아래와 같이 추가해서 텍스트뷰를 커스터마이징합니다.
import SwiftUI
struct ContentView: View {
var body: some View {
Text("Turtle Rock")
.font(.title)
.foregroundColor(.green)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
스택뷰를 통해 쌓기를 합니다.
struct ContentView: View {
var body: some View {
VStack {
Text("Turtle Rock")
.font(.title)
Text("Joshua Tree National Park")
}
}
}
스크린샷 2019-10-07 오전 11.26.01.png
struct ContentView: View {
var body: some View {
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
}
    }
        
}
}
스크린샷 2019-10-07 오전 11.31.49.png
struct ContentView: View {
var body: some View {
VStack(alignment: .leading) {
Text("Turtle Rock")
.font(.title)
HStack {
Text("Joshua Tree National Park")
.font(.subheadline)
Spacer()
Text("California")
}
    }
    .padding()       //약간의 여유를 위해 추가합니다. 
}
}
이미지 커스터마이징하기
다운로드 받은 turtlerock.jpg를 에셋에 추가합니다.
프로젝트에 새로운 파일을 추가하면서 Swift UI템플릿을 사용합니다. CircleImage라는 이름으로 추가합니다.
스크린샷 2019-10-07 오전 11.38.30.png
아래와 같이 코드를 수정합니다.
import SwiftUI
struct CircleImage: View {
var body: some View {
Image("turtlerock")
.clipShape(Circle())
.overlay(
Circle().stroke(Color.gray, lineWidth: 4))
.shadow(radius: 10)
}
}
struct CircleImage_Previews: PreviewProvider {
static var previews: some View {
CircleImage()
}
}
UIKit과 SwiftUI를 같이 사용할 수 있습니다.
새로운 파일을 추가하면서 Swift UI템플릿을 선택합니다. MapView라는 이름을 입력합니다.
아래와 같이 코드가 추가됩니다. 생성된 코드를 아래와 같이 수정합니다.
import MapKit
struct MapView: UIViewRepresentable {
func makeUIView(context: Context) -> MKMapView {
MKMapView(frame: .zero)
}
func updateUIView(_ view: MKMapView, context: Context) {
    let coordinate = CLLocationCoordinate2D(
        latitude: 34.011286, longitude: -116.166868)
    let span = MKCoordinateSpan(latitudeDelta: 2.0, longitudeDelta: 2.0)
    let region = MKCoordinateRegion(center: coordinate, span: span)
    view.setRegion(region, animated: true)
}
}
struct MapView_Previews: PreviewProvider {
static var previews: some View {
MapView()
}
}
Section 6: 상세뷰를 조합하기
ContentView파일을 아래와 같이 수정하면 병합된 뷰를 볼 수 있습니다.
//
// ContentView.swift
// Landmarks
//
// Created by JONG DEOK KIM on 07/10/2019.
// Copyright © 2019 multicampus. All rights reserved.
//
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
MapView()
.frame(height:300)
        CircleImage()
            .offset(y: -130)
            .padding(.bottom, -130)
        
        VStack(alignment: .leading) {
            Text("Turtle Rock")
                .font(.title)
            HStack {
                Text("Joshua Tree National Park")
                    .font(.subheadline)
                Spacer()
                Text("California")
                    .font(.subheadline)
            }
        }
        .padding()
            
        Spacer()
    }
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
스크린샷 2019-10-07 오전 11.52.40.png
아직은 저도 연습을 하고 있는데 재미있는 기술입니다. ^^

걷는 사람 하정우 독서 후기입니다.

저도 가능하면 하루에 1만2천보를 걸으려고 합니다. 작년에 다이어트를 한 이후에 1년 평균을 내보니 약 1만3천보를 걸었습니다. 요요현상이 나타나지 않는 것을 보니 현미와 채식도 중요하지만 걷는 행위도 매우 중요한 것 같습니다. 몸무게 84키로에서 73키로까지 줄이고 1년동안 유지하고 있습니다.
작년 9월에 애플와치3를 구매해서 1년을 사용하고 있습니다. 애플와치에서 평균을 내보니 하루 평균 1만3천보 달성한 것을 확인할 수 있습니다. 운동을 해야겠다는 결심이 했다면 하정우가 핏빗을 사용한 것 처럼 저는 애플와치를 착용해서 측정을 해 보시길 권하고 싶습니다. 측정하고 기록해야 개선할 수 있습니다. ^^ 아래가 제가 달성한 걷기 통계 입니다.
IMG_0498.png
목차는 다음과 같습니다.
1부 하루 3만보, 가끔은 10만보
2부 먹다 걷다 웃다
3부 사람, 걸으면서 방황하는 존재
마포에서 강남까지 편도로 하루 3만보를 걷는다는 것을 읽고 무척 놀랐습니다. 저도 많이 걷는다고 생각했는데 거의 3배를 걸어다니고 하와이를 가면 최소 4만보에서 10만보를 걸었다고 하니 사람의 한계에 대해 깊이 생각하게 됩니다. ㅎㅎ
눈에 띄는 문구들을 필사해 봅니다.
내 갈 길을 스스로 선택해서 걷는 것, 내 보폭을 알고 무리하지 않는 것, 내 숨으로 걷는 것, 걷기에서 잊지 말아야 할 것은 묘하게도 인생과 이토록 닮았다.
나는 촬영을 앞두고 "급다이어트"를 해야 하는 경우, 절대 먹지 말아야 할 금지식만 몇 개 정해놓고 평소처럼 먹고 계속 걷는다. 햄버거, 탄산음료, 설탕과 소금이 과하게 들어간 음식 - 장담하는데 딱 이 메뉴만 식단에서 걷어내고 꾸준히 걷기만 해도 확실히 살이 빠진다. ==> 저는 맥주가 문제 입니다. ㅎㅎ 맥주와 과자만 줄여도 될 것 같습니다.
"도대체 누가 텔리비젼을 앉아서 봐?"
당연히 "제뛰"를 하며 보는 게 원칙이다. 이 역시 우리 걷기 모임 멤버들이 쓰는 용어로, "제자리뛰기"를 말한다. 우리의 구호는 또 있다. "비상구만이 살 길이다"
도저히 나가서 걸을 수 없을 것만 같은 날, 혹은 걷다가 체력이 달려서 집으로 당장 돌아가고 싶었던 날, 그런 순간들을 견디게 만든 것은 결국 걷기를 다 마치고 돌아올 때의 성취감이었다는 것을 기억해 낸다.
하와이에서 아직 해가 남아 있을 때 걸으면 노을이 내 머리 위로 가만히 흘러간다.
걷기의 매력 중 하나는 날씨와 계절의 변화를 피부로 느낄 수 있다는 점이다. 햇빛의 양이 적당해서 아주 아름답고 부드러운 매직 아워의 하늘 ==> 이 책의 단점은 다 읽고 나면 하와이를 가보고 싶다는 생각이 너무 많이 든다는 겁니다. ㅎㅎ
내가 지키는 루틴은 다음과 같다.
아침에 일어나자마자 일단 러닝머신 위에 올라가 걸으며 몸을 푼다.
아침식사는 반드시 챙겨먹는다.
작업실이나 영화사로 출근하는 길엔 별일이 없는 한 걷는다. ==> 저도 아침에 일어나면 무조건 스트레칭을 20분 합니다. 강의가 있어서 출근하는 날에는 삼성역에서 내려서 천천히 선릉역까지 걸어갑니다. 약 15분 정도 걸어서 도착하면 아침이 무척 상쾌합니다. 저녁에도 별일 없으면 커뮤니티에 있는 헬쓰장에서 걷고, 자전거를 타고 합니다. 루틴이 생기면 삶이 좀 더 단순해지고 건강해 집니다.
우리들만의 독서 모임에서 그간 읽은 책들의 리스트는 다음과 같다. 다비드 르 보르통의 "걷기 예찬", 구가야 아키라의 "최고의 휴식", 일자 샌트의 "센서티브", 마이클 해리스의 "잠시 혼자 있겠습니다.", 토니 포터의 "맨박스", 조훈현의 "조훈현, 고수의 생각법", 다다 후미아키의 "말의 한수", 이기주의 "말의 품격"등이다.
책을 보니 레오나르도 다빈치, 아인슈타인, 스필버그 등도 ADHD성향이 있었다고 한다.
그러나 한편으로 우리는 누구나 ADHD 성향을 갖고 있는지도 모른다는 생각도 들었다. 가만있기보다는 자꾸만 움직이고 싶고, 자신의 감정을 상대가 알아채지 못할까봐 넘치게 표현하고, 한 가지에만 진득하게 집중하지 못하는 성질, 이것은 가장 어린아이 다운 본능이기도 하다.
새로운 도시에 갔을 때 내 두 다리로 지도를 만들어나가는 이 작업은 내게 꽤 중요하다. "베를린"을 촬영할 때도 나는 일부러 숙소를 호텔이 아닌 브란덴부르크 광장 옆의 일반 주택으로 정해달라고 부탁했다. ==> 저도 여행을 가면 시내 중심지에서 걷기 좋은 것을 얻어서 많이 걸어다닙니다. 평균 하루에 3만보 정도는 걸었던 것 같습니다. 그래야 밤에 더 곤하게 잠을 잘 수 있습니다.
티베트어로 "인간"은 "걷는 존재" 혹은 "걸으면서 방황하는 존재"라는 의미라고 한다. 나는 기도한다. 내가 앞으로도 계속 걸어나가는 사람이기를. 어떤 상황에서도 한 발 더 내딘는 것을 포기하지 않는 사람이기를.
이 책을 다 읽고 나면 하와이로 날아가서 걸어보고 싶다는 생각이 많이 듭니다. 한번 도전해 보고 싶어졌습니다. 내 두 다리가 멀쩡하다면 끊임 없이 걷고 내 삶을 쇄신 했으면 좋겠습니다.

IMG_0635.jpeg

IMG_0636.jpeg

IMG_0637.jpeg

IMG_0638.jpeg

IMG_0639.jpeg

IMG_0640.jpeg

IMG_0641.jpeg

IMG_0642.jpeg

IMG_0643.jpeg

IMG_0644.jpeg

IMG_0645.jpeg

IMG_0646.jpeg
IMG_0647.jpeg

파이썬 기반의 머신러닝, 딥러닝을 공부할 때 보시면 좋은 책들과 순서입니다.

연초에 시간에 많아서 조금씩 자료를 수집하고 공부하고 있습니다. 매년 설날과 추석을 전후로 2주에서 3주정도 시간이 되어서 조금씩 공부를 하고 있습니다. 목표는 2년정도(작년와 올해)를 잡아서 꾸준히 공부하는 것입니다. 아무래도 우리의 일상생활 전반에 인공지능이 성큼 다가오는 것 같습니다. 개발자라면 미리 준비하고 있어야겠죠!
저도 여러번 시행착오를 겪고 있어서 아래와 같은 순서로 접근해 보시면 좋을 것 같습니다.
첫번째: 파이썬 문법을 알고 있어야 합니다. 책이 없다면 점프투파이썬같은 온라인 컨텐츠를 참고하면 됩니다.
두번째: 두잇 판다스 입문과 같은 책이 필요합니다. 판다스는 파이썬에 있어서 엑셀과 같은 도구입니다. 데이터를 로딩, 가공, 결측치 변경과 같은 다양한 처리들을 모두 수행할 수 있습니다.
스크린샷 2019-02-01 오전 10.48.13.png
세번째: 가볍게 딥러닝을 살펴볼 수 있는 텐서플로로 시작하는 딥러닝 입문 책이 있습니다. 최근에 본 책인데 CNN, DNN, RNN등을 무척 쉬운 그림과 수식없이 파이썬 코드로 보여줍니다.
스크린샷 2019-01-31 오전 10.38.24.png
네번째: 조금 더 심도 있게 공부할 때 "밑바닥부터 시작하는 딥러닝"책이 있습니다. 넘파이를 사용한 연산과 브로드캐스트, AND, NAND, OR, XOR게이트 구현, 시그모이드 함수 구현부터 시작을 합니다. 정말 쉽게 되어 있는 책입니다. 강력하게 추쳔하는 책입니다.
스크린샷 2019-02-01 오후 3.21.13.png
다섯번째: 좀 더 실무적인 예제들이 필요하시면 정말 번역이 잘되어 있는 핸즈온 머신러닝 책을 보시면 됩니다. 한권으로 머신러닝과 딥러닝을 끝낼 수 있는 끝판왕 격의 책입니다. ^^
스크린샷 2019-02-01 오후 3.21.39.png

요즘 많이 들리는 RAG에 대한 멋진 정리가 있어서 공유합니다. ㅎㅎ

 작년에는 ChatGPT가 크게 유행을 했는데 올해는 Gen AI, LLM, 랭체인등이 유행하고 있습니다. ㅎㅎ  RAG라는 단어도 상당히 많이 들리고 있습니다. 멋진 정리의 링크입니다.  https://brunch.co.kr/@ywkim36/146?...