안녕하세요, 윤진입니다.


EFL 포럼이 지난 10월 28일(수)에 SOSCON과 함께 열렸습니다.

오전 10시부터 오후 6시까지 총 10개의 세션이 빽빽하게 준비되어있었는데요,

10개 세션 모두 EFL 종사자들에게는 피가 되고 살이 될만한 내용이었습니다.

사실, 타이젠 네이티브앱 개발자들의 참여를 열심히 독려했습니다만,

격변하는 현실 속에 업무의 파도에 휩쓸려 대부분 참가하지 못해 개인적으로는 아쉽더군요. :)


EFL Agenda


10:00 ~ 10:30 "Tizen 2.4 EFL 소개", 박춘언

10:30 ~ 11:10 "EFL을 이용한 타이젠 게임 개발", 박진솔

11:10 ~ 11:40 "Tizen UI Builder", 서현수

11:50 ~ 12:20 "EFL circular UI-components in GearS2", 이우찬

12:20 ~ 14:00 점심식사

14:00 ~ 14:30 "EFL 앱 개발을 위한 팁 소개", 윤진

14:40 ~ 15:10 "이미지 마스킹 & 필터", Jean-Philippe ANDRE

15:20 ~ 15:50 "EFL 오브젝트 모델", 엄지용

16:00 ~ 16:30 "EFL 벡터 그래픽", Subhransu Sekhar Mohanty

16:40 ~ 17:10 "16살 된 EFL은 어떻게 관리하고 배포할까?", 서주영

17:20 ~ 17:50 "EFL 신규 디버깅 프로파일러", Carstein Heitzler


작년에는 EFL의 기본적인 기능에 대한 안내가 포럼의 큰 틀이었는데요,

올해는 EFL에 새로 탑재된 기능들 위주로 주제를 잡았습니다.

점심시간 전에 이뤄진 4개 세션은 타이젠 플랫폼과 연계하여 세션주제를 잡았네요.

제가 맡은 5번째 세션도 타이젠 앱개발을 통해 얻은 삽질의 결과물이니,

처음 5개 세션 모두가 타이젠 플랫폼과 긴밀한 관계가 있다고 볼 수 있습니다.


첫번째 세션 "Tizen 2.4 EFL 소개", 박춘언님


"EFL, 삼성이 주도하는 오픈소스 프로젝트"

"Tizen UIFW은 EFL입니다."


"Enlightenment 철학"

"저성능 디바이스를 위한 최적화"


"EFL 관련 정보"


최신 타이젠 2.4에 탑재된 EFL를 전체적으로 훑어보는 시간이었습니다.

Eo/Eolian
Evas Async Rendering
Vsync/Animator forced render slots
Evas Masking
Elm ATK Accessibility Support
Eldbus
Wayland
LazyEDC
SystemD Support
Eina Thread Queue
Elocation API

타이젠 2.3 이후 무려 2년간의 업데이트 항목이 타이젠 2.4에 올라갔습니다.

2.3에 비해 여러가지 면에서 진보했습니다.



두번째 세션 "EFL을 이용한 타이젠 게임 개발", 박진솔


박진솔님은 edc와 c로 만든 간단한 게임을 시연해주었습니다.

슈퍼마리오 캐릭터가 등장하는 캐쥬얼 게임이었는데요,

- between 기능을 사용하여 캐릭터의 움직임을 표현하였고,

- 키핸들링으로 캐릭터 오브젝트의 위치를 통제하였습니다.

- 애니메이터로 매프레임마다 적/보너스의 위치를 감지했네요.

최신의 enventor를 사용하여 어렵지 않게 구현할 수 있는 노하우를 공유해주었습니다.


세번째 세션은 사정상 듣지를 못했습니다.

다섯번째 발표준비를 위해 남들보다 한템포 먼저 점심식사를 먹으러 가서요.

서현수님이 Tizen 2.4 SDK UI Builder를 소개해주신 모양입니다.

UI Builder는 타이젠에서 뷰를 구성할때 사용하는 툴인데요,

상당히 공을 들여서 발표자료를 준비해주신 것으로 기억합니다.

발표자료는 다음 주에 소스콘 사이트를 통해 공유가 될 예정입니다.

네이티브 앱 뷰 구성에 어려움을 느끼는 분들께서 참고하시면 좋겠네요.


왼편부터 이우찬님, 박진솔님, 박춘언님


네번째 세션은 이우찬님의 "EFL circular UI-components in GearS2"였습니다.

이른 점심을 먹고 와서 이우찬 님의 발표 중간부분부터 들었습니다.

- 기어S2에 추가된 rotary 관련 API가 소개되었고,

- Circle Surface를 이용하여 다수의 오브젝트를 관리하는 기법이 언급되었으며,

- progressbar, slider, spinner, datetime, scroller 등의 예시를 보여주었습니다.

기어S2에서는 윈셋만 사용해도 흥미로운 User interaction 구성이 가능하겠네요.


 다섯번째 세션 "EFL 앱 개발을 위한 팁 소개", 윤진


EFL 앱을 짜며 재미난 팁들을 60~70개 정도 모아두었는데요,

그 중에서 10개를 추려서 발표준비를 했습니다.

준비를 하고 보니 60분 정도 분량이더군요.

하지만, 주어진 시간은 30분!

그래서 전반부 5개만 발표하겠다고 말씀드리고 딱 5개만 발표했습니다.

뒤의 5개는 내년 포럼에서 그대로 다시 써먹겠습니다...는 아니고,

조만간 블로그에서 다뤄볼 생각입니다.


이번에 다룬 내용은 아래와 같습니다.

- Manage Data with evas_object_data_set()

- Manage Memory with elm_object_content_set()

- Manage Performance with mainloop

- Manage Object Size with min & relative

- Manage Events between C & EDC


여섯번째 세션 "이미지 마스킹 & 필터", Jean-Philippe ANDRE


"GL Engine, Simple image object, Image size, No border, Only one mask"


Text Effects


"Text Effects"


"Grow > Blur > Blur > Blend"


"Blend, Blur, Color curves, Grow, Mask, Bump map, Displacement"


"Only Text & Image"


Sources


https://www.enlightenment.org/docs/efl/advanced/eflgfxfilters


장필립님이 발표하신 마스킹과 필터링은 앱단에서도 굉장히 유용하게 사용되겠네요.

안정화된 버전이 나오려면 내년까지 기다려야할지도 모르겠지만,

EFL만으로 포토샵에서나 사용하던 효과를 쓴다는 것이 흥미롭습니다.

점차적으로 재미난 필터들이 추가되리라 기대해봅니다.


일곱번째 세션 "EFL 오브젝트 모델", 엄지용님


"How to use Eo"


"To create Eo class manually, too Hard! Use Eolian!"


class sample


모든 EFL 라이브러리(Eina 제외)의 조상으로 Eo가 등장하였습니다.

C++에서 상속과 같이 필수적인 기능만을 추려서 별도의 syntax를 Eo로 만들었습니다.

EFL의 컴포넌트들은 Eo를 상속하여 기능을 정의하도록 변경되었습니다.

Eolian을 통해서 나오는 구현부를 C 외의 언어로도 짤 수 있습니다.

차후 다른 언어로 EFL을 확장하기 용이하게 기반을 닦아놓은 셈입니다.

다만, Eo로 한꺼풀 감싸므로 성능이 7% 정도 떨어진다고 합니다.

하지만, 최적화가 진행 중에 있으니 점차 나아지겠지요.


여덟번째 세션 "EFL 벡터 그래픽", Subhransu Sekhar Mohanty


Evas 블록 하단에 자리한 Ector


Vector 그래픽을 위한 캔버스와 Evas_Object_VG


Evas_VG 관련 함수


벡터그래픽은 그 동안 줄기차게 요구했던 기능이기도 한데요,

이번에 탑재가 되었으니 여러가지 실험을 해보고 싶단 생각이 듭니다.

evas_object_vg_add()로 객체를 하나 생성한 후,

Efl_VG를 사용하여 shape, fill, stroke, transformantion을 지정하면 됩니다.

API set만 봐서는 간단하게 사용할 수 있어보입니다.


아홉번째 세션 "16살 된 EFL은 어떻게 관리하고 배포할까?", 서주영


역시 발표의 달인, 천재태지 서주영님.

발표하는 내내 재미난 퀴즈도 내주시고 여러차례 빅재미를 안겨주었습니다.

릴리즈를 하며 겪은 살아있는 체험담을 들려주었는데요,

오픈소스 릴리즈에 대해 살짝이나마 엿볼 수 있는 시간이었습니다.


마지막 세션 "EFL 신규 디버깅 프로파일러", Carstein Heitzler


짜잔, Eina DebugD가 나왔어요~


그 동안 제대로된 EFL 프로파일링 툴이 없었는데요,

드디어 쓸만한 프로파일링 툴이 나왔습니다.

아직은 초기 버전이라 실제 개발단에서 유용하게 쓰려면 좀 더 시간이 걸릴테지만,

하이츨러 마스터의 원대한 계획이 모두 달성되면,

gdb나 여타의 프로파일링 툴을 사용하지 않고도 대부분의 상황에서 유용하게 사용될 겁니다.


이번 EFL 포럼에서는 참가자들의 날카로운 질문도 많이 있었습니다.

날선 비판이나 애정어린 조언도 있었는데요,

모두 EFL이 무럭무럭 자라는데 도움이 될 거라 확신합니다.


오전에 커스터마이징된 edc를 사고 팔 수 있는 장터가 필요하단 참가자분의 아이디어에,

하이츨러가 바로 장터를 만들어 보여주기도 하였습니다.

EFL은 매일매일 발전하며 부족한 부분을 메꾸고 있습니다.

많은 질책과 격려 부탁드립니다.


끝_


안녕하세요, 타이젠 개발자 윤진입니다.


소스콘 행사가 10. 27(화) ~ 28(수)에 열렸습니다.

화요일에 열린 키노트부터 시작하여 콘래드 호텔에 이틀동안 줄창 있었습니다.

흥미로운 이야기도 많이 듣고,

다양한 생각을 가지고 있는 사람들과 만난 즐거운 자리였습니다.

어마어마한 이력을 가지고 있는 사람들도 있고,

번뜩이는 재치가 넘치는 사람들도 많이 만났습니다.

둘다 가지고 있는 분들도 많더군요. 하핫.

역시 세상은 넓고 좋은 개발자는 많습니다.


국내에서 열리는 행사 뿐만 아니라 해외에서 열리는 행사에도 참가하고 싶어집니다.

그러기 위해서는 역시 부단히 영어공부를...

아... 할 게 너무 많습니다.


행사장 진입로


참가자 등록대


키노트 행사장 입구 & 발표자 등록대


아침 9시부터 등록이 시작되었습니다.

9시 30분쯤 행사장에 도착하니 이미 많은 사람들로 꽤나 붐비고 있었습니다.

참가자 등록대가 줄을 서서 잠시 기다렸다가 안내원에게 이름을 말했더니

발표자 등록대로 가라고 하더군요.


발표자 등록대를 지키고 계신 분은 "유우영"님이었습니다.

국내외 유명 개발자들과 두터운 인맥을 쌓고 계시더군요.

작년까지 공개SW 개발자대회의 운영에도 참여하셨는데요.

앞으로도 좋은 행사 많이 만들어주세요~


IoTivity 부스


Unity 부스


Wayland 부스


EFL 부스


키노트 행사장 앞에는 여러 개의 부스가 마련되어 있었습니다.

Social Web App Platform, JerryScript, GearVRf, IoTivity, Wayland, EFL 등의 부스가 있었는데요,

부스 근처에 있던 요기거리에 정신이 팔려서 부스를 제대로 구경하지 못한게 아쉽네요.

부스를 구경하는 사람들도 꽤 되어서 다른 사람 뒷통수만 신나게 찍고 왔습니다.


키노트 행사장


키노트행사는 10시에 시작되었습니다.

10시부터 12시까지 2시간이 좀 넘게 계속되었습니다.

흥미로운 내용이 보일 때마다 사진으로 열심히 찍었는데요,

집에 돌아와 사진을 살펴보니,

사진만으로는 무슨 내용이었는지 기억이 안나는 것도 있더군요.

아... 이 몹쓸 기억력...


키노트 진행자, Brian Warner


키노트 "오픈소스,소프트웨어 생태계의 핵심", 김영윤 상무님


"공유를 통한 새로운 가치 생태계 창조"


"안드로이드 플랫폼 확산 시장점유율 82.8%"


"기업의 오픈소스 프로젝트 참여도 증가"

"리눅스 총 참여 기업 1,200개사"


"소프트웨어 생태계 확산을 위한 오픈소스 전문 조직 운영"


"Web기반 플랫폼을 통해 다양한 IoT 기기로의 연결 확대"

그렇습니다.

결국 타이젠이 나올 수밖에 없습니다. :)


"오픈소스 활성화 및 개발자 교류를 위한 기회의 장 마련, 컨퍼런스 및 해커톤 등"


"오픈소스 확산을 위한 국내외 대학 과목, 세미나 운영"


아파치 부의장, David Nalley


"비영리 법인 아파치 재단"


"Meritocracy(실력주의), 프로젝트에 참여하는 사람이 결정한다"


"아파치 계층도 : 일반 유저 - 컨트리뷰터 - 커미터 - 프로젝트 매니져 - 멤버"


"모든 결정은 메일링 리스트로 이뤄진다"

"멤버의 지역이 제각각이므로 최소 72시간의 유예를 두어 의사를 결정한다"

"다수결로 결정된 사항을 거부할 수 있다. 다만 대안이 있어야한다."


"관대한 아파치 라이센스"


"아파치의 길"


"아파치 내부 프로젝트 168개"


"The Art and Science of Livecoding", Andrew Sorensen


http://extempore.moso.com.au/

앤드류는 즉석에서 비트가 넘실대는 연주를 시연했습니다.

이미 오스콘때도 라이브코딩으로 연주를 했었는데요,

한국에서도 그럴싸한 재즈를 보여/들려 주었습니다.

하나의 완결된 곡을 만들기 위해 도입부터 결말까지 디테일하게 코딩하더군요.

코딩과 음악을 연결한 시도가 굉장히 흥미로웠습니다.


"Back to the Future : 2015", 신정규님


"공유해도 코드 가치는 안 떨어집니다."

"세상엔 비슷한 삽질을 하는 사람들이 수없이 많습니다"


"8대 2의 법칙"(똥코드 vs 좋은 코드)


"프로젝트의 소스코드를 맹신해서는 안됩니다"


"오픈소스는 생각만큼 기여자가 많지 않습니다."


"git 프로젝트의 85%는 혼자 사용합니다."


"그래도 안 망하고 2년정도 알려지면 다양한 경험을 하게 됩니다"


"공공재로서의 도구 개발"


"예술가가 될 필요는 있습니다."


"오픈소스 활동은 취미로 할 것인지 일로 할 것인지 선택의 순간이 옵니다"


"구글은 스카이넷이야."


신정규 님은 오픈소스를 만들며 겪은 경험을 이야기해주셨습니다.

역시 자신이 직접 겪은 이야기를 사실감있게 풀어내는 발표가 재미있습니다.

참가자들의 반응도 굉장히 좋아서 중간중간에 빅웃음이 있었습니다.


"함께하는 즐거움", 김혜나양


"바느질회로 - 달팽이 라이트(기초회로)"


"오픈소스로 배워요"


"Git 오픈소스 마스터 획득"



김혜나양을 응원하고 싶다면 저 메일을 이용하시면 됩니다.

스팸방지를 위해 따로 적어놓진 않겠습니다. :)


Brian Warner, 김혜나양, Linus Torvalds


김혜나양이 리누스에게 8개 정도의 질문을 하였습니다.

리눅스에 대한 질문(펭귄 포함)도 있었고,

git에 대한 얘기도 있었습니다.

사실 리누스는 이런 류의 질문을 수천번은 족히 받았을텐데,

어린 소녀가 하는 질문이라 그런지 더 성의껏 대답해주더군요.


세 명의 좌담회를 끝으로 오전 행사가 마무리되었습니다.

소스콘 주최측에서 참가자들에게 무료점심식사 쿠폰을 주어 IFC몰에서 점심을 먹었습니다.

사람이 제일 붐빌 시간인데다가

소스콘 참가자들로 식당들은 인산인해로 붐볐습니다.


오후 첫번째 세션을 준비하고 계시는 박영주 수석연구원님


"Tizen Applications", 박영주 수석연구원님


"좋은 성능으로 다양한 프로파일에서 동작하는 웹앱"


"네이티브 웨어러블앱 개발, 4시간 / 개발자 한 명"


"흥미로운 프로토타이핑, 10시간 / 개발자 한 명"


"발표가 끝난 직후 인터뷰에 임하고 있는 박영주 수석연구원님"


"HTML5와 Tizen을 이용한 웨어러블 프로그래밍", 서영진님


"Tizen과 IoT"


"디바이스의 시대, 플랫폼의 시대 그리고 서비스의 시대"


"웨어러블의 역사와 현재"


"타이젠 2012년 1월 1.0 베타 발표"


"갤럭시 시리즈와 웨어러블 디바이스와의 연동"


"기어 개발자 사이트, http://developer.samsung.com/gear"


발표 중인 서영진님


"Cross-Device Convergence", 장경아 수석연구원님


"타이젠 영역 확장 중!"


"더 많은 디바이스에서 더 많은 태스크를 꿈꾼다"


"타이젠 패스"


"패스의 종류, Action PASS / Contents PASS / Identity PASS"


"작동원리, Toss > Stream > Act"


"Identity PASS, TV 채널 선택권"


"Tizen PASS의 시작은 Toss"


"Stream으로 데이터를 나누기"


"각각의 디바이스가 액션을 결정"


"Contents PASS로 미디어를 나누기"


장경아 수석연구원님의 발표를 끝으로 오후 세션이 끝났습니다.

타이젠과 IoT의 접점이 늘 궁금했었는데요,

오늘로서 그 의문이 상당수 풀렸습니다.

(타이젠 개발자라고 해서 플랫폼 전체를 다 아는 것은 아니라는...)

타이젠 3.0으로는 좀 더 재미난 것들을 해볼 수 있겠네요.



오후 세션이 끝나고 BoF가 진행되었습니다.

BoF는 발표자와  참가자들이 간단한 다과를 즐기면서 소통을 하는 자리인데요.

"Tizen 개발자와 함께 Tizen 수다 한 판!" BoF에는 박영주 수석연구원님과 제가 발표자로 참가하였습니다.

Tizen 테이블 참가신청이 빨리 마감되어 다행이었습니다(휴...).

아무도 신청을 안하면 어쩌나 걱정했었는데 타이젠에 대해 관심을 가져주신 분들이 계셨습니다. :)

양인환님, 신헌섭님, 이영종님, 이영호님, 박준철님, 김성원님, 이주완님.

함께 해주셔서 감사합니다.


간단하게 쓰려고 했는데 괜히 길어졌네요.

긴 글 읽느라 고생하셨어요.


감사합니다.

끝_


+ 추가 : 포스팅을 하고 나서 다시 읽어보니 온통 감사하다는 말뿐이네요. 근데... 정말 고생하신 분들이 많아서 감사하다는 말을 도저히 뺄 수가 없더군요. 이 부분 널리 양해부탁드립니다.


+ 추가 : DevLab 행사와 관련하여 궁금하신 사항이 있으신 분들(참석자 or not)은 언제든지 질문을 주세요.


안녕하세요, 윤진입니다.


10/26(월) 콘래드호텔에서 SOSCON의 사전행사로 Tizen DevLab을 개최하였습니다.

SOSCON Tizen DevLab에 대해서는 이전에 포스팅 한 번 했었는데요,

웹앱과 네이티브앱에 대한 세션을 오후 2시부터 6시까지 마련하였습니다.



발표 리허설을 위해 오전에 서둘러서 출발하였습니다.

9시 7분에 집 지하주차장에서 출발했는데 호텔 주차장에 도착하니 9시 15분이더군요.

평소에는 서울에서 수원으로 출퇴근했기에 출퇴근길이 항상 힘들었는데요,

오늘만큼은... 행복하네요.

호텔 지하주차장에 설치된 모니터에서 소스콘 행사 안내를 볼 수 있었습니다.

"Samsung Open Source Conference Grand Ballroom (3F)"



DevLab이 열린 곳은 콘래드 호텔 6층입니다.

밖이 훤히 보이는 투명한 엘리베이터를 타고 6층으로 올라왔습니다.

엘리베이터 유리창 너머로 파크원 타워 건설 현장이 보였습니다.

건설 현장의 규모만 봐도 굉장한 높이의 빌딩이 올라갈 거라 쉽게 예상할 수 있었습니다.



DevLab 행사장으로 가는 길에 배치된 쇼파입니다.

한 번 앉으면 일어나기 힘들 정도로 포근한 쇼파였습니다.

행사 시작 전에 많은 개발자 분들이 앉아서 담소를 나누고 계시더군요.

한국 개발자 뿐만 아니라 외국 개발자들도 눈에 많이 띄었습니다.



행사장으로 향하는 복도입니다.

전체적으로 구름이 짙게 낀 날씨여서 그런지 실내도 많이 어두웠습니다.

하지만, 내부 인테리어는 전체적으로 중후하고 모던한 분위기였습니다.



중간 공간에 간식과 음료도 마련되어 있었습니다.

간식으로는 쿠키와 빵이 있었습니다.

누구나 먹고 싶은 만큼 가져가 먹을 수 있어서요,

신나게 집어먹은 기억이 납니다.



발표장 앞에 입간판이 세워졌습니다.

SOSCON 삼성 오픈소스 컨퍼런스의 튜토리얼 세션 2개가 나오네요.

Studio7에서는 IoTivity로 재미있는 세션이 이어졌고,

Studio4에서는 Tizen DevLab이 개최되었습니다.



DevLab을 위한 안내 입간판입니다.

14:00~14:30 [강의] 누구나 쉽게 만드는 Tizen Web Application by 강석현 연구원

14:30~15:50 [실습] 누구나 쉽게 만드는 Tizen Web Application by 손보연 연구원

15:50~16:10 휴식

16:10~16:40 [강의] 정교하게 만드는 Tizen Native Application by 윤진 연구원

16:40~18:00 [실습] 정교하게 만드는 Tizen Native Application by 이은영 연구원

전체적으로 위의 순서대로 진행하였습니다.

물론 다양한 변수가 있어서 꼭 위의 시간대로 진행이 되지는 않았습니다. :)



발표장 입구에 들어가자마자 사진을 찍었습니다.

SOSCON 삼성 오픈소스 컨퍼런스 화면이 크게 보입니다.

Studio4에 천장에 내장된 프로젝터 화면이 작아서 큰 화면을 출력할 수 있게 따로 요청했었는데요,

새롭게 놓여진 프로젝트를 탁월한 선택이었단 생각이 듭니다.

DevLab은 코드가 주인공이기 때문에 저 정도가 아니면 소스가 제대로 안 보일 수 있거든요.

(DevLab 행사를 원활히 진행해주신 조재민 연구원님께 감사의 말씀을 드립니다.)



DevLab 행사를 위해 많은 분들이 고생해주셨습니다.

발표장 뒷편에는 원활한 행사진행을 위해 스탭분들이 대기해주셨습니다.

행사를 위해 묵묵히 고생하신 스탭분들께 감사의 마음을 전하고 싶습니다.



각 자리에는 콘래드 호텔에서 준비한 연습장과 볼펜이 놓여 있었습니다.

호텔에서는 종이와 연필을 챙기는 재미가 쏠쏠한지라 '몰래' 가방에 넣어왔습니다.



DevLab 행사 진행을 맡은 박문경 연구원입니다.

전체 행사진행 뿐만 아니라 Native Application의 튜터로도 활약했습니다.

매끄러운 진행을 위해 스크립트도 손으로 한땀한땀 써왔던데요,

공개적이고 형식적인 자리에 어울리는 진행을 해줘서 고맙습니다.

다음에도 진행을 부탁해야겠네요. :)



전체 트랙을 진행하기에 앞서,

타이젠 아키텍트이신 박영주 수석 연구원님께서 모두발언을 해주셨습니다.

타이젠 앱에 대해 간략하게 맥을 짚어주셨는데요,

더 자세한 내용이 궁금하시다면 내일 오후 소스콘 첫 세션(박영주 수석연구원, "Tizen Applications")을 들으시면 됩니다.



타이젠 웹앱 세션에서 강의를 진행하신 강석현 연구원님입니다.

발표장 앞에 있는 입간판에서 포즈를 부탁드렸는데요,

저런 익살스런 포즈를 취하신걸 제 손가락이 놓치지 않았습니다. 우후후.

강석현 연구원께서는 왜 웹앱을 해야하는지 충분히 납득가능한 설명을 해주셨습니다.

중간에 네이티브앱에 대해서도 살짝 언급해주셨는데요,

'개발자가 불에 타고 있는 이미지'를 재미난 이모티콘 이미지를 보여주시며,

제 3의 플랫폼이 개발자를 힘들게 한다는 충격요법으로 포문을 여셨습니다.

그리고 타이젠 플랫폼 뿐만 아니라 다른 플랫폼에도 바로 이식하여 사용할 수 있는 웹앱을 강조해주셨지요.



웹앱 실습은 손보연 연구원께서 진행해주셨습니다.

맥북과 미리 나눠드린 TM1시료가 붙지 않아 여러 참가자 분들이 고생하셨습니다.

최신 OS X 버전 11에서 삼성 USB 통합 드라이버가 제대로 동작하지 않아 생긴 이슈입니다.

통합 드라이버를 빠른 시일내로 업데이트하여 맥북에서도 원활히 테스트할 수 있도록 준비하겠습니다.

타이젠 버전이 업그레이드될수록 IDE도 진화하고 있습니다.

아직 부족한 점이 눈에 띄실 수도 있습니다.

저희가 더 노력해서 더 쉽고 편하고 빠르게 사용할 수 있도록 하겠습니다.



웹앱 튜터로 활약해주신 김용국 연구원입니다.

웹앱 세션에서 여기저기 종횡무진 누비고 다니던데요,

고생 많으셨어요.

함께 고생한 김수필 연구원 독사진이 없어서 그 사진은 최하단의 단체사진으로 대체합니다.

(미안해요, 술필)



그리고 네이티브 세션을 진행했습니다.

(위의 사진은 윈도우 지존 문관경 연구원께서 찍어주셨습니다)

웹앱세션을 진행하며 참가자 분들이 SDK 설정 및 타겟 연결을 완료하셨기 때문에,

네이티브 세션은 상대적으로 SDK와 관련된 이슈가 적었습니다.


그리고 더불어 소스콘 주최측에서 여분의 노트북도 준비해주셨습니다.

노트북을 가져오지 않으신 분들

- 자신의 노트북에서 원활히 SDK가 돌아가지 않는 분들

20대가 넘는 노트북을 준비해서 모두 제대로 실습할 수 있도록 하였습니다.

이 자리를 빌어 노트북을 준비해준 임지혜 연구원님과 SDK와 관련하여 여러가지로 도움주신 이남기 연구원님 외 한 분(이름이 갑자기 생각이 안나네요)께 감사를 전합니다.


이번 네이티브앱 발표에서 다룬 주제는,

- Life cycle

- View (elm_naviframe APIs)

- Component (EDC)

- Launch (app_control APIs)

위처럼 구성되어 있었습니다.


네이티브 앱 세션이 아무래도 웹앱보다는 어려웠을 것이라 생각하는데요,

세션을 더욱 쉽게 준비하지 못한 부분은 모두 제 책임입니다.

타이젠 네이티브앱을 구성하는 핵심요소를 모두 보여드리겠다는 욕심이 과했을지도 모르겠네요.

다음 행사에서는 개발자분들께서 더 쉽게 네이티브앱을 경험하실 수 있도록 준비하겠습니다.



네이티브앱 실습을 진행한 이은영 연구원님입니다.

샘플앱을 직접 작성하고 간결하게 설명하기 위해 바쁜 시간 쪼개가며 준비해주었습니다.

일정상 여러가지 많은 일거리가 있었는데,

불평없이 즐겁게 준비해주어 고마운 마음이 듭니다.



이번 데브랩을 준비한 멤버 모두입니다.

왼쪽부터 박문경 연구원 - 손보연 연구원 - 강석현 연구원 - 박영주 수석연구원 - 이근선 연구원 - 이은영 연구원 - 김수필 연구원 - 하이츨러 마스터 - 윤진 연구원입니다.

데브랩 네이티브 세션에 하이츨러 마스터님도 참석해주셨습니다.

하이츨러 마스터님께서는 세션발표 후 여러가지 실질적인 조언도 아끼지 않고 해주셨습니다.


구글러 서주영 연구원께서도 DevLab에 참석해주셨습니다.

서주영 연구원께서는 모레 있을 EFL 포럼에서 릴리즈와 관련된 세션을 진행할 예정입니다.

EFL 포럼에는 여러가지 재미난 이야기거리가 많이 준비되어 있습니다.

기대하셔도 좋습니다. :)


참가자 분들도 고생 많으셨습니다.

네 시간동안 웹앱도 하고 네이티브앱도 개발하느라 정신없으셨을 것 같네요.

발표하는 입장에서 봤을때는 모두 또렷또렷한 눈으로 따라와주셨는데요,

실제로는 어떠셨을지 궁금하네요.

어쨌든 부족한 발표 따라와 주셔서 감사합니다.


그리고 내일부터 소스콘 본행사가 시작됩니다.

이틀동안 알찬 세션이 많이 준비되어 있습니다.


개발자분들의 관심과 참여 부탁드립니다.

감사합니다.



안녕하세요, 윤진입니다.


어제는 소스콘 튜토리얼 트랙으로 타이젠 데브랩 행사에 대해 소개했었는데요,

오늘은 소스콘 컨퍼런스 트랙 중 하나인 EFL 포럼을 소개해볼까 합니다.



EFL 포럼은 소스콘 마지막 날인 10월 28일(수)에 열립니다.

오전 10시 30분부터 오후 5시 50분까지 총 10개 세션이 준비되어 있습니다.

처음 두 개 세션만 40분이고 나머지 세션은 30분 단위로 되어 있습니다.

다양한 주제가 모두 다뤄지는 만큼 30분 내지는 40분이 길게 느껴지지 않을겁니다.



EFL 한국커뮤니티에 올라와 있는 포스터입니다.

그동안 EFL은 독자적으로 세미나를 진행해왔고 올해로 3년이 되었습니다.

올해는 소스콘과 함께 개최되는 만큼 여느때보다 더 북적될 거라 기대하고 있습니다.


타이젠 플랫폼은 UIFW으로 EFL을 사용하고 있기 때문에,

타이젠 플랫폼 개발 혹은 타이젠 네이티브앱 개발에 관심있는 분들은,

EFL 트랙 하나하나를 놓쳐선 안됩니다. :)


첫 세션을 맡은 박춘언 책임 연구원께서는,

곧 배포될 Tizen 2.4 SDK에 올라간 EFL의 신규기능을 전체적으로 짚어주실 겁니다.

신규기능이란 것이 결국 더 편리하고 더 유려한 기능일테니,

잘 들어두면 개발에 직접적인 도움이 될 겁니다.


박진솔 연구원께서는,

Enventor를 '주'로 사용하여 만든 게임개발방법을 소개해주실 예정입니다.

Enventor의 업그레이드된 모습을 기대해주세요.


서현수 연구원께서는,

타이젠 SDK에 탑재된 UI Builder를 소개해주실 예정입니다.

UI Builder를 사용하여 WYSIWYG으로 소스코드를 생성할 수 있습니다.


이우찬 연구원께서는,

Elementary 위젯에 대해 포괄적인 정보를 공유해주실 예정입니다.

Elementary의 구성을 알아두면,

위젯의 스타일을 손쉽게 변경할 수 있습니다.

커스터마이징에 관심이 있다면 이 세션이 도움이 될겁니다.


그리고 다음 14:00 세션이 메인이죠(네네, 그러려니 해주세요;).

제 세션에서는 EFL 앱 개발에 사용하고 있는 여러가지 테크닉을 공유해드릴 예정입니다.

총 10개의 팁을 준비해두었고,

5개의 메인팁에 대해 집중적으로 발표할 예정입니다.

대략의 꼭지는 아래와 같습니다.


- Manage Data

- Manage Memory

- Manage Performance

- Manage Object Size with min & relative

- Manage Event


- Use Recalculate

- Use Offset

- Use Border for Nine Patch

- Use Repeat Events

- Use Color Class


위의 10개의 꼭지 중 Manage 항목이 중요하다고 여겨져서,

Manage 항목 5개 위주로 발표할 예정입니다.

정말 만에 하나 시간이 허락한다면,

Use 항목에서도 하나둘 발표할 예정입니다.

네이티브앱을 개발하시려면 꼭 들어주세요(굽신굽신).


점심시간 직후라 자칫 잘못하면 숙면실이 될 수도 있겠네요.

뭔가 재미난 얘기를 많이 넣어야겠어요!


Jean Phillippe Andre 연구원께서는,

이미지 마스킹과 필터에 대해 발표하실 예정입니다.

이전 EFL에서는 Rectangle로만 마스킹을 해야했었는데요,

Gear S2 등이 나오면서 이미지로도 마스킹을 할 필요가 생겼죠.

그래서 이미지 마스킹 기능이 새로 추가되었습니다.


엄지용 연구원께서는,

EFL에 도입된 OOP 개념에 대해 발표해주실 예정입니다.

EO가 아직 개발자단까지 피부로 와닿는 개념은 아닌데요,

Elementary 소스에는 굉장히 광범위하게 사용되고 있습니다.

EFL 소스를 분석하고자 한다면 EO에 대해 필히 알아두어야 합니다.


SubhransuSekhar Mohanty 연구원께서는,

벡터 그래픽에 대해 발표해주실 예정입니다.

보다 동적이고 자유로운 Visual Interaction을 위해 Ector를 사용할 수 있습니다.


서주영 구글러께서는,

EFL 릴리스를 하며 겪은 시행착오를 발표해주실 예정입니다.

오픈소스 배포에 대한 어려움을 직접 들을 수 있습니다.


하이츨러 EFL 창시자께서는,

EFL 신규로 도입된 디버깅 프로파일러에 대해 공유해주신다고 합니다.

디버깅 프로파일러의 부재가 항상 아쉬웠었는데요,

이번 세션을 열심히 듣고 장차 열심히 써먹어야겠습니다.


이상 총 10개 세션에 대한 개인적인 의견을 언급해보았습니다.

여러분이 놓치지 말아야할 세션은,

점심시간 이후 오후 2시에 열리는 세션이란 것만 기억해주세요;


포럼에 참석하시는 분들께,

박춘언 책임 연구원께서 직접 디자인한 티셔츠도 받으실 수 있습니다.


그럼 그 날 뵙겠습니다.

끝_










edc파일로 문자열을 출력할 수도 있습니다.

문자열은 edc 파일에서 직접 입력할 수도 있고,

C파일에서 elm_object_part_text_set() 함수를 사용하여,

필요할 때마다 문자열을 입력할 수 있습니다.


문자열이 전혀 없는 앱은 거의 없을 겁니다.

복잡다단한 문자표현의 세계에 첫 발을 text 블록으로 내딛어 보겠습니다.



안녕하세요, Tizen 개발자 윤진입니다.


edc에 문자열을 지원하는 타입은 2가지가 있습니다.

- TEXT

- TEXTBLOCK

위의 두 가지 중에 TEXT 타입을 먼저 살펴보겠습니다.

TEXT는 TEXTBLOCK에 비하여 간단한 문자열을 표시하는데 사용하지요.

TEXT 타입이 TEXTBLOCK 타입에 비해 multiline이라든가 기능에는 제한은 있지만,

간단한 연산만 필요하기에 훨씬 빠릅니다.



- text {}

텍스트 파트에는 텍스트에 대한 추가정보를 기술하기 위한 text 블록이 필요합니다.

text {}는 part - description 내에 위치하지요.

description에 위치한다는 것은,

각 상태(state)에 따라 text의 설정값을 변경할 수 있다는 것이겠죠.

곧, program으로 텍스트의 모양새를 여러가지로 바꿀 수 있습니다.



- text: "문자열";

text 블록 내에 블록과 동일한 이름의 필드인 text를 사용할 수 있습니다.

text 필드에 명시한 문자열은 default로 사용되는 문자열입니다.

default는 외부에서 해당 텍스트 파트에 아무 것도 set하지 않으면 나타납니다.

edc에서 문자열을 확정할 수 있다면 text 필드를 사용하면 됩니다.



- font: "폰트명";

텍스트에 폰트를 지정할 수 있습니다.

font를 지정하려면 플랫폼에서 지정한 값을 넣어줘야 하겠지요.

"Sans"나 "Arial"과 같은 글꼴 이름을 적어주면 됩니다.

물론 해당 글꼴이 플랫폼에 탑재가 되어 있어야겠지요?



- size: [폰트사이즈];

폰트 사이즈를 입력할 수 있습니다.

양수를 적어넣으면 됩니다.



- align: [x축, 0.0~1.0] [y축, 0.0~1.0];

텍스트 파트에서 정렬을 하기 위해서 align을 사용합니다.

두 개의 인자를 적어주면 되는데 각각 x축/y축 기준입니다.

텍스트 파트에서 rel1/rel2로 지정한 파트의 영역 내에서,

텍스트의 배열을 어떻게 설정할지를 align으로 정하게 됩니다.


collections {
   group {
     name: "main";
   parts {
      part {
         name: "label";
         type: TEXT;
         scale: 1;
         description {
            state: "default" 0.0;
            color: 255 0 0 255;
            text {
               text: "TEXT";
               font: "Sans";
               size: 24;
               align: 0.5 0.5;
            }
         }
      }
   }
}

위의 코드에서는 화면 한가운데에 "TEXT"라는 문자열을 표시하지요.

폰트는 "Sans"이고 폰트사이즈는 24입니다.




- effect: [EFFECT];

폰트에 이펙트를 추가할 수 있습니다.

effect 필드는 description이 아닌 part에 넣어주어야 합니다.

그 말은 state에 따라 effect를 바꿀 수 없다는 것이겠지요.

이펙트는 종류가 많아보이긴 하지만 따지고 보면 윤곽선, 그림자로 귀결됩니다


•    PLAIN : effect가 없습니다.
•    OUTLINE  : 윤곽선
•    SOFT_OUTLINE : 부드러운 윤곽선
•    SHADOW : 그림자
•    SOFT_SHADOW : 부드러운 그림자
•    OUTLINE_SHADOW : 윤곽선 + 그림자
•    OUTLINE_SOFT_SHADOW : 윤곽선 + 부드러운 그림자
•    FAR_SHADOW : 멀리 떨어진 그림자
•    FAR_SOFT_SHADOW : 멀리 떨어진 부드러운 그림자
•    GLOW : 발광윤곽선


눈으로 직접 보는게 이해가 빠르겠네요.

아래처럼 9개의 이펙트를 위한 그룹을 만들어보겠습니다.


예시에 보면 color3가 쓰였는데요,

color3는 윤곽선이나 그림자 색상을 의미합니다.

color3는 color와 함께 description에 쓰이므로 state에 따라 바꿀 수 있습니다.


collections {
   group {
     name: "main";
     parts {
       part {
         name: "bg";
         type: RECT;
         description {
           state: "default" 0.0;
           color: 255 255 255 255;
         }
       }

       part {
         name: "PLAIN";
         type: TEXT;
         effect: PLAIN;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           text {
             text: "PLAIN EFFECT";
             font: "Sans";
             size: 20;
             align: 0.5 0.0;
            }
         }
      }
     
      part {
         name: "OUTLINE";
         type: TEXT;
         effect: OUTLINE;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
           text {
              text: "OUTLINE EFFECT";
              font: "Sans";
              size: 20;
              align: 0.5 0.1;
            }
         }
      }
       part {
         name: "SOFT_OUTLINE";
         type: TEXT;
         effect: SOFT_OUTLINE;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
           text {
              text: "SOFT_OUTLINE EFFECT";
              font: "Sans";
              size: 20;
              align: 0.5 0.2;
            }
         }
      }
 
      part {
         name: "SHADOW";
         type: TEXT;
         effect: SHADOW;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
            text {
               text: "SHADOW EFFECT";
               font: "Sans";
               size: 20;
               align: 0.5 0.3;
            }
         }
      }
     
      part {
         name: "SOFT_SHADOW";
         type: TEXT;
         effect: SOFT_SHADOW;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
            text {
               text: "SOFT_SHADOW EFFECT";
               font: "Sans";
               size: 20;
               align: 0.5 0.4;
            }
         }
      }
 
      part {
         name: "OUTLINE_SHADOW";
         type: TEXT;
         effect: OUTLINE_SHADOW;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
            text {
               text: "OUTLINE_SHADOW EFFECT";
               font: "Sans";
               size: 20;
               align: 0.5 0.5;
            }
         }
      }
 
      part {
         name: "OUTLINE_SOFT_SHADOW";
         type: TEXT;
         effect: OUTLINE_SOFT_SHADOW;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
           text {
               text: "OUTLINE_SOFT_SHADOW EFFECT";
               font: "Sans";
               size: 20;
               align: 0.5 0.6;
            }
         }
      }
 
      part {
         name: "FAR_SHADOW";
         type: TEXT;
         effect: FAR_SHADOW;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
            text {
               text: "FAR_SHADOW EFFECT";
               font: "Sans";
               size: 20;
               align: 0.5 0.7;
            }
         }
      }
 
      part {
         name: "FAR_SOFT_SHADOW";
         type: TEXT;
         effect: FAR_SOFT_SHADOW;
         description {
            state: "default" 0.0;
            color: 255 0 255 255;
            color3: 0 0 0 255;
            text {
               text: "FAR_SOFT_SHADOW EFFECT";
               font: "Sans";
               size: 20;
               align: 0.5 0.8;
            }
         }
      }
 
      part {
         name: "GLOW";
         type: TEXT;
         effect: GLOW;
         description {
           state: "default" 0.0;
           color: 255 0 255 255;
           color3: 0 0 0 255;
            text {
               text: "GLOW EFFECT";
               font: "Sans";
              size: 20;
               align: 0.5 0.9;
            }
         }
      }
   }
}



오늘은 여기까지 하겠습니다.

그럼 좋은 하루 보내세요~

끝_

 
 
 
 

  1. YOhoho 2015.11.23 14:58

    color2는 윤곽선
    color3는 그림자 색상이군요

    • 안녕하세요, YOhoho님. 또 오셨군요. 감사합니다 :) 컬러 뒤에 붙는 숫자가 커질수록 텍스트에서 멀어지죠~ 근데 솔직히 필드이름에 숫자가 들어간게 맞는지는 모르겠네요 :)

이펙트가 전무한 평면적인 앱을 개발할 때는 성능에 민감하지 않아도 됩니다.

하지만, 사용자의 동작마다 유려한 반응이 연결되어 있다면,

성능에 민감하게 반응할 수밖에 없습니다.


부드러운 효과를 위해서는,

단위시간당 화면이 많이 갱신될수록 좋지요.

한 오브젝트가 1초에 60px을 움직일 때,

화면이 10번 갱신되는 것과 60번 갱신되는 것은 당연히 차이가 있겠지요.



EFL에서는 개발자가 윈도우 단위로 가속화 방식을 선택할 수 있게 하였습니다.

Elementary config에서 제공하는 함수 하나만으로 가속방식을 선택할 수 있지요.

먼저 elm_config.h에서 elm_config_accel_preference_set() 함수 선언을 살펴보시지요.


/**
 * @brief Set Elementary's acceleration preferences for new windows.
 *
 * @param[in] pref The preference desired as a normal C string
 *
 * @details  Note that it will take effect only to Elementary windows created after
 *           this is called. The @p pref string is a freeform C string that indicates
 *           what kind of acceleration is preferred. Here "acceleration" majorly
 *           means to rendering and which hardware unit application renders guis with.
 *           This may or may not be honored, but a best attempt will
 *           be made. Known strings are as follows:
 *
 * @li "gl", "opengl" - try use opengl.
 * @li "3d" - try and use a 3d acceleration unit.
 * @li "hw", "hardware", "accel" - try any acceleration unit (best possible)
 *
 * @note This takes precedence over engine preferences set with
 *       @ref elm_config_preferred_engine_set().
 *
 * @see elm_config_accel_preference_set()
 *
 * @since_tizen 2.3
 *
 * @see elm_win_add()
 * @see elm_config_accel_preference_override_set()
 *
 * @since 1.10
 */
EAPI void        elm_config_accel_preference_set(const char *pref);


가속방식으로 gl / opengl / 3d / hw / hardware / accel 등을 사용할 수 있습니다.

사용시 주의할 점이 하나 있습니다.

elm_config_accel_preference_set()은 elm_win_add()를 사용하기 전에 사용해야 합니다.

elm_win_add() 이후에 사용한다면 소용이 없습니다.

elm_win_add() 함수 내에서,

elm_config_accel_preference_set()에서 설정한 값을 참조하여 윈도우를 생성하기 때문입니다.


elementary 소스를 찾아보지요.

"git://review.tizen.org/framework/uifw/elementary"의 tizen_2.3 브랜치입니다.

elementary/src/lib/elm_win.c 파일에서 elm_win_add() 정의부를 찾아보세요.


EAPI Evas_Object *
elm_win_add(Evas_Object *parent,
            const char *name,
            Elm_Win_Type type)
{
   Evas *e;
   Evas_Object *obj;
   const Eina_List *l;
   const char *fontpath, *fallback = NULL;

   Elm_Win_Smart_Data tmp_sd;

   // 중략

   switch (type)
     {
      case ELM_WIN_DYNAMIC_BOX:
        // 중략
        break;
      case ELM_WIN_INLINED_IMAGE:
        // 중략
        break;
      case ELM_WIN_SOCKET_IMAGE:
        // 중략
        break;
      default:
        if (ENGINE_COMPARE(ELM_SOFTWARE_X11))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_FB))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_DIRECTFB))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_16_X11))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_8_X11))
           // 중략
        else if (ENGINE_COMPARE(ELM_OPENGL_X11))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_WIN32))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_16_WINCE))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_PSL1GHT))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_SDL))
           // 중략
        else if (ENGINE_COMPARE(ELM_SOFTWARE_16_SDL))
           // 중략
        else if (ENGINE_COMPARE(ELM_OPENGL_SDL))
           // 중략
        else if (ENGINE_COMPARE(ELM_OPENGL_COCOA))
           // 중략
        else if (ENGINE_COMPARE(ELM_BUFFER))
           // 중략
        else if (ENGINE_COMPARE(ELM_EWS))
           // 중략
        else if (ENGINE_COMPARE(ELM_WAYLAND_SHM))
           // 중략
        else if (ENGINE_COMPARE(ELM_WAYLAND_EGL))
           // 중략
        else if (!strncmp(ENGINE_GET(), "shot:", 5))
           // 중략
        break;
}


ELM_WIN_DYNAMIC_BOX, ELM_WIN_INLINED_IMAGE, ELM_WIN_SOCKET_IMAGE 타입의 윈도우를 생성하는 경우는 가속화 엔진을 사용하지 않습니다.

위의 타입은 엄밀히 얘기하면 윈도우가 아닙니다.

switch문 내의 default 케이스가 윈도우를 생성하는 부분입니다.

default 케이스 내의 if / else if / else 문으로 가속화를 위한 엔진을 고르지요.

ENGINE_COMPARE()를 통해,

- 사용자가 elm_config_accel_preference_set()에서 입력한 string과

- 내장되어 있는 엔진의 string을 비교하여,

그에 맞는 가속화 방법을 결정하게 되는 것입니다.


타이젠 오픈소스에 있는 모든 앱들을 대상으로 elm_config_accel_preference_set()을 사용하는 앱을 찾아보았습니다.

Tizen 2.3 기준으로 딱 하나의 앱이 나오네요.

git://review.tizen.org/apps/home/menu-screen


menu-screen 앱을 보면,

윈도우를 생성하기 직전에 가속방법을 설정하고 있습니다.

Emulator 환경에서는 opengl을 사용하고,

그 외의 환경에서는 vconf로 설정된 값을 사용하게 되어 있습니다.

menu-screen은 플랫폼의 첫 화면이니만큼,

성능에 신경을 쓸 수 밖에 없겠지요.


static menu_screen_error_e _create_canvas(char *name, char *title)
{
    char *buf;

    if (_is_emulator_on()) {
        elm_config_accel_preference_set("opengl");
    } else {
        buf = vconf_get_str(MENU_SCREEN_ENGINE);
        if (buf) {
            _D("ELM_ENGINE is set as [%s]", buf);
            elm_config_accel_preference_set(buf);
            free(buf);
        } else {
            _D("ELM_ENGINE is set as [gl]");
            elm_config_accel_preference_set("gl");
        }
    }   

    menu_screen_info.win = elm_win_add(NULL, name, ELM_WIN_BASIC);
    retv_if(NULL == menu_screen_info.win, MENU_SCREEN_ERROR_FAIL);

    if (title) {
        elm_win_title_set(menu_screen_info.win, title);
    }   
    elm_win_borderless_set(menu_screen_info.win, EINA_TRUE);
    elm_win_screen_size_get(menu_screen_info.win, NULL, NULL, &menu_screen_info.root_width, &menu_screen_info.root_height);
   // 생략
}


가속으로 CPU/메모리 사용이 증가하게 되면,

소모전류도 덩달이 늘어날 수 있습니다.

(하지만, 비례한다고 말할 수 있을지는 모르겠습니다)

상황에 맞게 사용하는게 좋겠지요.


끝_

  1. 초보개발자 2016.03.15 18:26

    좋은 강의 감사합니다 : ) 많이 도움 받고 있습니다.

아직 추위가 가시지 않은 어느 봄날,

다수의 앱에서 사용할 수 있는 라이브러리를 하나 개발해달라는 요청을 받았습니다.

라이브러리는 화면을 구성하는 컴포넌트를 포함하고 있었기 때문에

EFL 라이브러리로 컴포넌트를 구성하기로 하였습니다.


라이브러리 설계를 위한 고민이 시작되었습니다.

라이브러리를 사용하는 개발자의 '자유도'를 고려하여 설계할 것인지,

라이브러리를 쉽게 사용할 수 있게 '접근성'을 고려하여 설계할 것인지,

몇 명의 개발자와 머리를 맞대고 방향을 고민했습니다.


'자유도'를 제공하기 위해 사용한 방식은,

Smart object를 interface로 사용하여 함수를 제공하는 것이었습니다.




안녕하세요, Tizen 개발자 윤진입니다.


자유도.

자유도가 높으면 그만큼 많은 함수를 숙지해야할 책임이 생깁니다.

대신 이 많은 함수들을 절묘하게 조합하면,

제법 재미난 결과물을 도출해낼 수도 있습니다.


하지만, 간단한 컴포넌트를 하나 그리려고 하는데,

함수를 수십개씩 사용해야 한다는 단점도 있겠죠.

개발자가 익혀야 하는 함수의 갯수만큼 진입장벽은 높아집니다.


이에 반해 자유는 최대한 제한하지만,

단 한두개의 함수로 컴포넌트를 구성하는 방법도 있습니다.

개발자가 세부적인 설정을 할 수는 없지만,

기본적으로 제공하는 몇 개의 함수만으로도 컴포넌트를 사용할 수 있습니다.


넓은 자유도 안겨줄 것인가.

낮은 진입장벽을 제공할 것인가.


라이브러리를 사용하는 최종 소비층이 누구인지에 따라 함수 프로토타이핑을 달리 해야합니다.


만약 라이브러리의 주사용계층이 앱개발자라면?

간단한 함수 몇 개만으로 앱을 짤 수 있는 방법을 제공해야합니다.

쉽고- 간단하고- 빠르게- 사용할 수 있는 함수군을 만들어두고,

필요하다면 자유도를 위한 함수군도 부가적으로 제공하는 편이 낫습니다.


플랫폼 간에 치열한 경쟁에서,

플랫폼의 고객, 앱개발자'님'들을 모셔오기 위해서는,

앱개발자가 손쉽게 접근할 수 있는 환경을 갖춰두는 것이 필요합니다.


이런 맥락에서,

우리는 Smart object를 갖다버리기로 하였습니다.

앱개발자의 '자유'는 다음 정권때 갖는 걸로.


하지만,

그럼에도 불구하고 Smart object로 프로토타이핑하며 얻은 몇 가지 정보를 공유하고자 합니다.


EFL은 Evas에서 기본적으로 제공하는 오브젝트인 rectangle, image, text, textblock, line, ... 외에,

새로운 형태의 object를 생성하도록 지원합니다.


개발자는 Smart object로 작성된 오브젝트를-

evas_object_del, evas_object_move, evas_object_resize, evas_object_show, evas_object_hide와 같은-

기본 Evas 함수들과 함께 사용할 수 있습니다.


이 말을 다시 풀면,

Smart object를 만드려면 기본 Evas 함수들에도 동작하게 준비를 해야 한다는 것입니다.


static struct {
Evas_Smart_Class smart_class;
Evas_Smart *smart;
} story_compiler_class_info = {
.smart_class = EVAS_SMART_CLASS_INIT_NAME_VERSION(STORY_COMPILER_CLASS_NAME),
.smart = NULL,
};

Evas_Object *story_compiler_add(Evas_Object *parent)
{
Evas_Object *story_compiler = NULL;
Evas *e = NULL;

retv_if(!parent, NULL);

e = evas_object_evas_get(parent);
retv_if(!e, NULL);

/* We need only one story compiler class even if there are many story compilers */
if (!story_compiler_class_info.smart) {
story_compiler_class_info.smart_class.add = __story_compiler_add;
story_compiler_class_info.smart_class.del = __story_compiler_del;
story_compiler_class_info.smart_class.move = __story_compiler_move;
story_compiler_class_info.smart_class.resize = __story_compiler_resize;
story_compiler_class_info.smart_class.show = __story_compiler_show;
story_compiler_class_info.smart_class.hide = __story_compiler_hide;
story_compiler_class_info.smart_class.color_set = __story_compiler_color_set;
story_compiler_class_info.smart_class.clip_set = __story_compiler_clip_set;
story_compiler_class_info.smart_class.clip_unset = __story_compiler_clip_unset;
story_compiler_class_info.smart = evas_smart_class_new(&story_compiler_class_info.smart_class);
retv_if(!story_compiler_class_info.smart, NULL);
}

story_compiler = evas_object_smart_add(e, story_compiler_class_info.smart);
retv_if(!story_compiler, NULL);

return story_compiler;
}


위의 코드를 보면,

우선 Evas_Smart_Class 구조체를 EVAS_SMART_CLASS_INIT_NAME_VERSION를 사용하여 초기화합니다.

그리고 Evas_Smart_Class 구조체에 Evas의 기본 함수 역할을 수행할 내부함수를 아래와 같이 매핑해둡니다.


.del

 evas_object_del

 .move

 evas_object_move

 .resize

 evas_object_resize

 .show

 evas_object_show

 .hide

 evas_object_hide

 .color_set

 evas_object_color_set

 .clip_set

 evas_object_clip_set

 .clip_unset

 evas_object_clip_unset


그리고 위처럼 만들어놓은 class 구조체는 아래 함수를 사용하여 EFL에서 '보증하는' class가 됩니다.

EAPI Evas_Smart                       *evas_smart_class_new(const Evas_Smart_Class *sc)

위의 함수는 유효한 Smart Class인지 체크하기 위해 매직넘버를 설정하고,

callback 함수를 효율적으로 관리하기 위해 내부정리를 합니다.

이 과정을 거쳐서, Smart Object를 생성할 때 사용할 수 있는-

진정한 의미의 클래스 Evas_Smart가 비로소 생성됩니다.


위에서 생성한 Evas_Smart를 인자로 아래 함수를 이용하여 Evas_Object 객체를 만듭니다.

EAPI Evas_Object *evas_object_smart_add(Evas *e, Evas_Smart *s)

위의 함수에서 리턴되어 나온 Evas_Object 객체는,

Evas 기본 함수들과 함께 사용할 수 있습니다.

Evas 기본 함수들과 함께 사용하기 위해 만든 Smart Object이므로,

위의 함수가 이번 장의 핵심이라 볼 수 있습니다.


각각의 매핑함수들은 아래와 같이 정의할 수 있습니다.

매핑함수의 내용을 보면 알겠지만,

내부적으로 관리하는 object들에 직접 Evas 기본함수들을 사용하여 동작하게 합니다.


static void __story_compiler_add(Evas_Object *story_compiler)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = calloc(1, sizeof(story_compiler_s));
ret_if(!story_compiler_info);
evas_object_smart_data_set(story_compiler, story_compiler_info);

story_compiler_info->story_compiler = story_compiler;
story_compiler_info->layout = evas_object_rectangle_add(evas_object_evas_get(story_compiler));
if (story_compiler_info->layout) {
evas_object_smart_member_add(story_compiler_info->layout, story_compiler);
} else {
free(story_compiler_info);
}
}



static void __story_compiler_del(Evas_Object *story_compiler)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);

evas_object_smart_member_del(story_compiler_info->layout);
evas_object_del(story_compiler_info->layout);
free(story_compiler_info);
}



static void __story_compiler_move(Evas_Object *story_compiler, Evas_Coord x, Evas_Coord y)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);
ret_if(!story_compiler_info->layout);

evas_object_move(story_compiler_info->layout, x, y);
}



static void __story_compiler_resize(Evas_Object *story_compiler, Evas_Coord w, Evas_Coord h)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);
ret_if(!story_compiler_info->layout);

evas_object_resize(story_compiler_info->layout, w, h);
}



static void __story_compiler_show(Evas_Object *story_compiler)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);
ret_if(!story_compiler_info->layout);

evas_object_show(story_compiler_info->layout);
}



static void __story_compiler_hide(Evas_Object *story_compiler)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);
ret_if(!story_compiler_info->layout);

evas_object_hide(story_compiler_info->layout);
}



static void __story_compiler_color_set(Evas_Object *story_compiler, int r, int g, int b, int a)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);
ret_if(!story_compiler_info->layout);

evas_object_color_set(story_compiler_info->layout, r, g, b, a);
}



static void __story_compiler_clip_set(Evas_Object *story_compiler, Evas_Object *clip)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);
ret_if(!story_compiler_info->layout);

evas_object_clip_set(story_compiler_info->layout, clip);
}



static void __story_compiler_clip_unset(Evas_Object *story_compiler)
{
story_compiler_s *story_compiler_info = NULL;

ret_if(!story_compiler);

story_compiler_info = evas_object_smart_data_get(story_compiler);
ret_if(!story_compiler_info);
ret_if(!story_compiler_info->layout);

evas_object_clip_unset(story_compiler_info->layout);
}

위의 함수군에서 일괄적으로 사용하는 함수가 있습니다.

위의 함수는 smart object 내부에서 관리할 data를 설정(set)하고, 가져올 수 있게(get) 해줍니다.

evas_object_smart_data_del과 같은 함수는 없기 때문에,

외부에서 smart object에서 관리하는 데이터를 삭제할 수 없습니다.

smart object 자체가 사라지지 않는한 data도 생명력을 유지합니다.


위의 예제에서는 내부적으로 관리할 story_compiler_s 구조체를,

evas_object_smart_data_set으로 선언해두고,

다른 매핑함수에서 evas_object_smart_data_get으로 꺼내서 재사용하고 있습니다.



위의 함수를 사용하여 smart object에 내에서 함께 layering이 될 수 있도록 다수의 오브젝트를 하나도 묶을 수 있습니다.

_story_compiler_add() 내에서 evas_object_smart_member_add()를 이용하여,

새롭게 생성한 layout 객체를 smart object와 함께 layering 혹은 stacking될 수 있도록 처리하였습니다.

예제에서는 하나의 Evas_Object 객체만 있지만,

다수의 Evas_Object 객체를 함께 관리하는 경우에도,

모두 evas_object_smart_member_add()를 이용하여 함께 layering 되도록 처리할 필요가 있습니다.


이렇게 하여 생성한 story_compiler_add()로 얻는 Evas_Object 객체는,

과연 다른 part에 elm_object_part_content_set()이 될까요?

결론부터 말하자면,

content_set은 안됩니다.


EFL에서 elm_object_part_content_set() 함수의 소스를 쭈욱 따라 내려가다 보면,

아래 함수를 마주치게 됩니다.


EAPI void 
elm_widget_content_part_set(Evas_Object *obj,
                            const char *part,
                            Evas_Object *content)
{
   ELM_WIDGET_CHECK(obj);
   eo_do(obj, elm_obj_container_content_set(part, content));
}


함수 정의 첫번째 줄에서,

content_set 하려는 오브젝트가 ELM_WIDGET인지 여부를 체크합니다.

하지만 안타깝게도,

smart object는 widget이 아니기 때문에 content_set을 수행하기 전에 return 됩니다.


smart object는 evas_object_move로 위치를 잡아주는 수밖에 없습니다.


별로...

Smart 해보이지 않네요.


_끝

+ Recent posts