SlideShare a Scribd company logo
1 of 41
이종인 
*바람 인터렉티브 Founder 
*Windows Platform Development MVP 
* Windows Phone 앱 개발 
- 
- 
lunelake@outlook.com 
http://www.facebook.com/BaramInteractive design me
나를 디자인 하는 서비스 
삶의 목표에 다가가기 쉽게 
만들어주기 위한 서비스
나를 디자인 하는 서비스 
삶을 쉽게 계획하고 
순간을 기록하기 쉽게
2013년 10월 출시 15개의 언어 지원
중국, 미국 스토어 유료앱 전체 순위 40위권 기록(2014.3) 
20% 
20% 
9% 
5% 
4% 
42% 
국가별 다운로드 비율 
중국 미국 인도 영국 베트남 기타
다양한 디바이스와 환경 속에서 
유연하게 이어지는 서비스를 만드는 것
Cross platform – 코드 공유 
추가/수정 사항 
발생시
멀티 디바이스 환경에서 유연한 데이터 처리
디바이스의 크기와 환경에 따라 달라지는 유저들의 요구와 
그로 인해 파편화된 경험들 합치기
데스크탑, 태블릿, 폰을 아우르는 서비스를 한 프로젝트에서 
(Shared project, PCL)
Shared Project
통합이 안된 API들 
Windows 
Runtime API 
Bing Map 
일정 데이터 
연락처 데이터 
… 
90% 10% 
조건부 컴파일 + 별도 처리 시나리오 
public void ClearMap() 
{ 
#if WINDOWS_APP 
_shapeLayer.Shapes.Clear(); 
_pinLayer.Children.Clear(); 
#elif WINDOWS_PHONE_APP 
_map.MapElements.Clear(); 
_map.Children.Clear(); 
#endif 
}
화면 크기에 대응하는 UI 
4.5” 
6” 
7” 
5” 
x 
Infinite virtual canvas 
y 
Landscape Portrait
윈도우 사이즈가 변했을 때 x 
protected override void OnNavigatedTo(NavigationEventArgs e) 
{ 
this.navigationHelper.OnNavigatedTo(e); 
Window.Current.SizeChanged += Current_SizeChanged; 
} 
protected override void OnNavigatedFrom(NavigationEventArgs e) 
{ 
this.navigationHelper.OnNavigatedFrom(e); 
Window.Current.SizeChanged -= Current_SizeChanged; 
} 
/// <summary> 
/// 윈도우의 사이즈가 변했을 때 이벤트 
/// </summary> 
public void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e) 
{ 
double windowWidth = e.Size.Width; 
double windowHeight = e.Size.Height; 
//로직 
}
Viewbox x 
Viewbox 
Control
Viewbox x 
Element 비율 따라 크기 조정 Element 크기 조정 
<Grid Background="Black"> 
<GridView Margin="100,100,0,0"> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
</GridView> 
</Grid> 
<Grid Background="Black"> 
<Viewbox HorizontalAlignment="Left"> 
<GridView Margin="100,100,0,0" Height="768" > 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
<Rectangle Fill="Red" Height="200" Width="200" /> 
</GridView> 
</Viewbox> 
</Grid>
스케일 이슈 
Windows Phone Windows 
DPI > 
Font 글씨 글씨 
<Style x:Key="TextblockStyle" TargetType="TextBlock"> 
<Setter Property="FontSize" Value=“17"></Setter> 
</Style> 
Viewbox의 크기를 플랫폼별로 다르게 지정
Binding 
ValueConverter 
<TextBlock Margin="-1,0,0,0" FontSize="40" 
Foreground="{Binding TitleForegroundColor}" 
Text="{Binding PagesTitle}" /> 
<TextBlock Margin="-1,0,0,0" FontSize="40" 
Foreground=“#FF444444” Text=“Pages” /> 
Data binding 
결과
복잡한 뷰 로직의 간결한 처리 
Home 
Textblock1 
Textblock2 
Textblock3 
Textblock4 
Home 
Textblock1 
Textblock2 
Textblock3 
Textblock4 
기본 방식 
TitleTextblock.Foreground = new SolidColorBrush(Colors.White); 
Textblock1.Foreground = new SolidColorBrush(Colors.White); 
Textblock2.Foreground = new SolidColorBrush(Colors.White); 
Textblock3.Foreground = new SolidColorBrush(Colors.White); 
Textblock4.Foreground = new SolidColorBrush(Colors.White); 
public bool WhiteMode 
{ 
get{return _WhiteMode;} 
set 
{ 
_WhiteMode = value; 
OnPropertyChanged(); 
if (value == true) 
TitleForegroundColor = "#FFFFFFFF"; 
else 
TitleForegroundColor = "#FF444444"; 
} 
} 
Data binding
굴비 엮듯이 엮어지는 데이터 바인딩 
Monthly 
Calendar Viewer 
MonthlyCalendar 
DailyViewer 
Calendar 
SelectedDate 
Calendar 
SelectedDate 
Calendar 
SelectedDate 
일간 일정 
업데이트 
월간뷰어 
업데이트 
MonthSelect 
Picker 
DailyCalendar 
Viewer 
AgendaCalendar 
Viewer 
MainViewModel 
Appointment 
Dictionary 
Calendar 
SelectedDate 
Appointment 
Dictionary 
달력 
업데이트 
Monthly 
Calendar Viewer 
MonthlyCalendar 
DailyViewer
MVVM 
View 
Model 
View 
View Model
INotifyPropertyChanged 
public class ViewModel : INotifyPropertyChanged 
{ 
private string _ID; 
public string ID 
{ 
get{return _ID;} 
set{_ID = value; 
OnPropertyChanged();} 
} 
public event PropertyChangedEventHandler PropertyChanged; 
protected bool SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null) 
{ 
if (object.Equals(storage, value)) return false; 
storage = value; 
this.OnPropertyChanged(propertyName); 
return true; 
} 
protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) 
{ 
if (PropertyChanged != null) 
{ 
PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
} 
} 
}
Control에 DependencyProperty 추가하기 
public static readonly DependencyProperty CalendarSelectedDateProperty = 
DependencyProperty.Register("CalendarSelectedDate", typeof(DateTime), typeof(MonthlyCalendarViewer), new PropertyMetadata(null, new 
PropertyChangedCallback(OnCalendarSelectedDateChanged))); 
public DateTime CalendarSelectedDate 
{ 
get { return (DateTime)GetValue(CalendarSelectedDateProperty); } 
set { base.SetValue(CalendarSelectedDateProperty, value); } 
} 
private static void OnCalendarSelectedDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
((MonthlyCalendarViewer)d).OnCalendarSelectedDateChanged(e); 
} 
void OnCalendarSelectedDateChanged(DependencyPropertyChangedEventArgs e) 
{ 
if (e.OldValue != null) 
{ 
DateTime oldValue = (DateTime)e.OldValue; 
DateTime newValue = (DateTime)e.NewValue; 
if (oldValue.Month != newValue.Month || oldValue.Year != newValue.Year) 
DrawCalendarBase(); 
} 
else 
{ 
DrawCalendarBase(); 
DrawCalendarContent(); 
loaded = true; 
} 
}
데이터 바인딩 이럴때 쓰세요!
멀티디바이스에서의 데이터 동기화 시나리오 
비용 지출X 비용 지출O 
즉결성 보장X)
Local 
Storage 
Local 
Storage 
디자인 미의 유저 데이터 처리
OnlineIdAuthenticator를 통한 Onedrive 동기화 
public class WindowsAccountAuthenticator 
{ 
OnlineIdAuthenticator authenticator; 
public WindowsAccountAuthenticator() 
{ 
authenticator = new OnlineIdAuthenticator(); 
} 
/// <summary> 
/// 마이크로소프트 계정 로그인 및 인증 
/// </summary> 
public async Task SignIn() 
{ 
var targetArray = new List<OnlineIdServiceTicketRequest>(); 
targetArray.Add(new OnlineIdServiceTicketRequest("wl.signin", "DELEGATION")); 
var result = await authenticator.AuthenticateUserAsync(targetArray, CredentialPromptType.PromptIfNeeded); 
string AccessToken = result.Tickets[0].Value; 
} 
}
OnlineIdAuthenticator를 통한 Onedrive 동기화
Credential Locker 
MSA 
void SaveCredential(string username, string password) 
{ 
PasswordVault vault = new PasswordVault(); 
PasswordCredential cred = new 
PasswordCredential("MyAppResource", username, password); 
vault.Add(cred); 
} 
IReadOnlyList<PasswordCredential> RetrieveCredential(string 
resource) 
{ 
PasswordVault vault = new PasswordVault(); 
return vault.FindAllByResource(resource); 
}
tech days 2014 Universal Windows App - Jongin Lee
tech days 2014 Universal Windows App - Jongin Lee

More Related Content

Similar to tech days 2014 Universal Windows App - Jongin Lee

[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)
[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)
[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)
Sang Don Kim
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발
NAVER D2
 

Similar to tech days 2014 Universal Windows App - Jongin Lee (20)

안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트안드로이드 개발자를 위한 스위프트
안드로이드 개발자를 위한 스위프트
 
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
2.Connect Sunshine to the Cloud - 시온고 안드로이드 스터디
 
[115] clean fe development_윤지수
[115] clean fe development_윤지수[115] clean fe development_윤지수
[115] clean fe development_윤지수
 
자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기자바스크립트 프레임워크 살펴보기
자바스크립트 프레임워크 살펴보기
 
MVP 패턴 소개
MVP 패턴 소개MVP 패턴 소개
MVP 패턴 소개
 
Clean Front-End Development
Clean Front-End DevelopmentClean Front-End Development
Clean Front-End Development
 
Do IoT Yourself! - 사물 간의 연결을 위한 Open API
Do IoT Yourself! - 사물 간의 연결을 위한 Open APIDo IoT Yourself! - 사물 간의 연결을 위한 Open API
Do IoT Yourself! - 사물 간의 연결을 위한 Open API
 
Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기Meteor React Tutorial 따라하기
Meteor React Tutorial 따라하기
 
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
#19.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_국비지원IT학원/실업자/재직자환급교육/자바/스프링/...
 
처음배우는 자바스크립트, 제이쿼리 #4
처음배우는 자바스크립트, 제이쿼리 #4처음배우는 자바스크립트, 제이쿼리 #4
처음배우는 자바스크립트, 제이쿼리 #4
 
[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)
[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)
[Td 2015]치즈케이크 팩토리는 알겠는데, 데이터 팩토리는 뭔가요(한기환)
 
Webframeworks angular js 세미나
Webframeworks angular js 세미나Webframeworks angular js 세미나
Webframeworks angular js 세미나
 
Appview 소개
Appview 소개Appview 소개
Appview 소개
 
[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발[1A5]효율적인안드로이드앱개발
[1A5]효율적인안드로이드앱개발
 
20201121 코드 삼분지계
20201121 코드 삼분지계20201121 코드 삼분지계
20201121 코드 삼분지계
 
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
GKAC 2015 Apr. - Battery, 안드로이드를 위한 쉬운 웹 API 호출
 
Airflow를 이용한 데이터 Workflow 관리
Airflow를 이용한  데이터 Workflow 관리Airflow를 이용한  데이터 Workflow 관리
Airflow를 이용한 데이터 Workflow 관리
 
[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초[Codelab 2017] ReactJS 기초
[Codelab 2017] ReactJS 기초
 
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
Dreamweaver CS5.5 를 이용한 jQueryMobile 개발
 
Actionbar and fragment
Actionbar and fragmentActionbar and fragment
Actionbar and fragment
 

tech days 2014 Universal Windows App - Jongin Lee

  • 1.
  • 2. 이종인 *바람 인터렉티브 Founder *Windows Platform Development MVP * Windows Phone 앱 개발 - - lunelake@outlook.com http://www.facebook.com/BaramInteractive design me
  • 3.
  • 4. 나를 디자인 하는 서비스 삶의 목표에 다가가기 쉽게 만들어주기 위한 서비스
  • 5. 나를 디자인 하는 서비스 삶을 쉽게 계획하고 순간을 기록하기 쉽게
  • 6. 2013년 10월 출시 15개의 언어 지원
  • 7. 중국, 미국 스토어 유료앱 전체 순위 40위권 기록(2014.3) 20% 20% 9% 5% 4% 42% 국가별 다운로드 비율 중국 미국 인도 영국 베트남 기타
  • 8.
  • 9.
  • 10. 다양한 디바이스와 환경 속에서 유연하게 이어지는 서비스를 만드는 것
  • 11.
  • 12. Cross platform – 코드 공유 추가/수정 사항 발생시
  • 13. 멀티 디바이스 환경에서 유연한 데이터 처리
  • 14. 디바이스의 크기와 환경에 따라 달라지는 유저들의 요구와 그로 인해 파편화된 경험들 합치기
  • 15.
  • 16. 데스크탑, 태블릿, 폰을 아우르는 서비스를 한 프로젝트에서 (Shared project, PCL)
  • 18. 통합이 안된 API들 Windows Runtime API Bing Map 일정 데이터 연락처 데이터 … 90% 10% 조건부 컴파일 + 별도 처리 시나리오 public void ClearMap() { #if WINDOWS_APP _shapeLayer.Shapes.Clear(); _pinLayer.Children.Clear(); #elif WINDOWS_PHONE_APP _map.MapElements.Clear(); _map.Children.Clear(); #endif }
  • 19. 화면 크기에 대응하는 UI 4.5” 6” 7” 5” x Infinite virtual canvas y Landscape Portrait
  • 20. 윈도우 사이즈가 변했을 때 x protected override void OnNavigatedTo(NavigationEventArgs e) { this.navigationHelper.OnNavigatedTo(e); Window.Current.SizeChanged += Current_SizeChanged; } protected override void OnNavigatedFrom(NavigationEventArgs e) { this.navigationHelper.OnNavigatedFrom(e); Window.Current.SizeChanged -= Current_SizeChanged; } /// <summary> /// 윈도우의 사이즈가 변했을 때 이벤트 /// </summary> public void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e) { double windowWidth = e.Size.Width; double windowHeight = e.Size.Height; //로직 }
  • 21. Viewbox x Viewbox Control
  • 22. Viewbox x Element 비율 따라 크기 조정 Element 크기 조정 <Grid Background="Black"> <GridView Margin="100,100,0,0"> <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> </GridView> </Grid> <Grid Background="Black"> <Viewbox HorizontalAlignment="Left"> <GridView Margin="100,100,0,0" Height="768" > <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> <Rectangle Fill="Red" Height="200" Width="200" /> </GridView> </Viewbox> </Grid>
  • 23. 스케일 이슈 Windows Phone Windows DPI > Font 글씨 글씨 <Style x:Key="TextblockStyle" TargetType="TextBlock"> <Setter Property="FontSize" Value=“17"></Setter> </Style> Viewbox의 크기를 플랫폼별로 다르게 지정
  • 24.
  • 25.
  • 26. Binding ValueConverter <TextBlock Margin="-1,0,0,0" FontSize="40" Foreground="{Binding TitleForegroundColor}" Text="{Binding PagesTitle}" /> <TextBlock Margin="-1,0,0,0" FontSize="40" Foreground=“#FF444444” Text=“Pages” /> Data binding 결과
  • 27. 복잡한 뷰 로직의 간결한 처리 Home Textblock1 Textblock2 Textblock3 Textblock4 Home Textblock1 Textblock2 Textblock3 Textblock4 기본 방식 TitleTextblock.Foreground = new SolidColorBrush(Colors.White); Textblock1.Foreground = new SolidColorBrush(Colors.White); Textblock2.Foreground = new SolidColorBrush(Colors.White); Textblock3.Foreground = new SolidColorBrush(Colors.White); Textblock4.Foreground = new SolidColorBrush(Colors.White); public bool WhiteMode { get{return _WhiteMode;} set { _WhiteMode = value; OnPropertyChanged(); if (value == true) TitleForegroundColor = "#FFFFFFFF"; else TitleForegroundColor = "#FF444444"; } } Data binding
  • 28. 굴비 엮듯이 엮어지는 데이터 바인딩 Monthly Calendar Viewer MonthlyCalendar DailyViewer Calendar SelectedDate Calendar SelectedDate Calendar SelectedDate 일간 일정 업데이트 월간뷰어 업데이트 MonthSelect Picker DailyCalendar Viewer AgendaCalendar Viewer MainViewModel Appointment Dictionary Calendar SelectedDate Appointment Dictionary 달력 업데이트 Monthly Calendar Viewer MonthlyCalendar DailyViewer
  • 29. MVVM View Model View View Model
  • 30. INotifyPropertyChanged public class ViewModel : INotifyPropertyChanged { private string _ID; public string ID { get{return _ID;} set{_ID = value; OnPropertyChanged();} } public event PropertyChangedEventHandler PropertyChanged; protected bool SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] String propertyName = null) { if (object.Equals(storage, value)) return false; storage = value; this.OnPropertyChanged(propertyName); return true; } protected void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = null) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
  • 31. Control에 DependencyProperty 추가하기 public static readonly DependencyProperty CalendarSelectedDateProperty = DependencyProperty.Register("CalendarSelectedDate", typeof(DateTime), typeof(MonthlyCalendarViewer), new PropertyMetadata(null, new PropertyChangedCallback(OnCalendarSelectedDateChanged))); public DateTime CalendarSelectedDate { get { return (DateTime)GetValue(CalendarSelectedDateProperty); } set { base.SetValue(CalendarSelectedDateProperty, value); } } private static void OnCalendarSelectedDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { ((MonthlyCalendarViewer)d).OnCalendarSelectedDateChanged(e); } void OnCalendarSelectedDateChanged(DependencyPropertyChangedEventArgs e) { if (e.OldValue != null) { DateTime oldValue = (DateTime)e.OldValue; DateTime newValue = (DateTime)e.NewValue; if (oldValue.Month != newValue.Month || oldValue.Year != newValue.Year) DrawCalendarBase(); } else { DrawCalendarBase(); DrawCalendarContent(); loaded = true; } }
  • 32.
  • 34.
  • 35. 멀티디바이스에서의 데이터 동기화 시나리오 비용 지출X 비용 지출O 즉결성 보장X)
  • 36. Local Storage Local Storage 디자인 미의 유저 데이터 처리
  • 37. OnlineIdAuthenticator를 통한 Onedrive 동기화 public class WindowsAccountAuthenticator { OnlineIdAuthenticator authenticator; public WindowsAccountAuthenticator() { authenticator = new OnlineIdAuthenticator(); } /// <summary> /// 마이크로소프트 계정 로그인 및 인증 /// </summary> public async Task SignIn() { var targetArray = new List<OnlineIdServiceTicketRequest>(); targetArray.Add(new OnlineIdServiceTicketRequest("wl.signin", "DELEGATION")); var result = await authenticator.AuthenticateUserAsync(targetArray, CredentialPromptType.PromptIfNeeded); string AccessToken = result.Tickets[0].Value; } }
  • 39. Credential Locker MSA void SaveCredential(string username, string password) { PasswordVault vault = new PasswordVault(); PasswordCredential cred = new PasswordCredential("MyAppResource", username, password); vault.Add(cred); } IReadOnlyList<PasswordCredential> RetrieveCredential(string resource) { PasswordVault vault = new PasswordVault(); return vault.FindAllByResource(resource); }