이틀동안 Vue 설치와 Visual Studio Code(VSCode), Android Studio, Nativescript를 설치하고 간단한 Vue Web App을 만들어보고 Android 개발 환경까지 준비를 다 했다.
이제 간단한 Android용 앱을 하나 만들어 개발용 갤럭시탭에 띄워 보려고 한다.
C:\project\vue 폴더에 만든 vue-farm 폴더에서 계속 작업한다. vue-farm 폴더가 없으면 프로젝트를 만들려고 하는 폴더 ( \project\vue)에서 tns create vue-farm 이라고 치면 폴더가 만들어지고 vue-farm 프로젝트 기본 파일들이 생성된다. 이 vue-farm 폴더 내에서 npm install –save nativescript-vue 라고 명령을 내려 vue-farm 프로젝트에 nativescript-vue를 추가시켜 준다.
VSCode를 띄워서 메뉴의 파일 > 폴더열기를 선택해서 C:\project\vue\vue-farm 폴더를 선택한다.
대략 이런 폴더 구조가 보인다. 여기서 app 밑에 있는 app.js를 열어보면 간단한 정보를 보여주기 위한 페이지를 띄우는 스크립트가 보인다.
[app.js 파일] import Vue from 'nativescript-vue' import Home from './components/Home' new Vue({ render: (h) => h('frame', [h(Home)]), }).$start()
음…Vue.js 예제 파일에서 보던 App.js와는 좀 다른 모양이다. 대충 구조는 Vue() 에서 render 함수를 통해 프로그램이 시작되는 것을 알 수 있다.
이 파일을 약간 수정한다. components 폴더 아래에 App.vue를 만들어서 쓸 예정이므로 Home을 빼고 App를 추가한다.
import Vue from 'nativescript-vue' /* 삭제되는 라인 import Home from './components/Home' */ import App from './components/App' new Vue({ render: (h) => h('frame', [h(App)]), // Home이 App 로 바뀌었다. }).$start()
import Home 라인은 필요없으니까 삭제를 한다.
다음엔 components 폴더 아래에 App.vue와 Post.vue 두개의 파일을 만든다. 소스는 git의 Instagram-NativeScript-Vue 프로젝트를 참조하였다.
App.vue 파일은 git에서 다운로드 받은 App.vue 파일을 복붙한 다음 하나씩 수정을 하면서 구조를 파악했다.
[App.vue 파일] <template> <Page> <ActionBar> <StackLayout> <Image class="logo" src="~/assets/images/logo.png" /> </StackLayout> </ActionBar> <ScrollView> <StackLayout> <Post v-for="(item, index) in posts" :key="index" :Image="item.Image" :Favor="item.Favor" /> </StackLayout> </ScrollView> </Page> </template> <script> import Post from './Post' export default { data(){ return{ posts: [ { Image: 'https://cdn.pixabay.com/photo/2022/09/21/05/39/birds-7469509_960_720.jpg', Favor:0 }, { Image: 'https://cdn.pixabay.com/photo/2022/02/08/09/28/boats-7001054_960_720.jpg' , Favor:0}, { Image: 'https://nespy2aub3if2yow3fcm0t5y-wpengine.netdna-ssl.com/files/2013/11/conhe%C3%A7a-londres-635x359.jpg', Favor:0 }, { Image: '~/assets/images/1000454324980_i1_1200.jpg', Favor:0 } ] } }, components: { Post } } </script> <style lang="scss" scoped> ActionBar { background-color: #f5f5f5; color: #ffffff; } .logo{ width: 100; } .message { vertical-align: center; text-align: center; font-size: 20; color: #333333; } </style>
수정한 부분은 중간의 Image Url들을 실제 pixabay에 있는 이미지 주소들로 몇개 변경해 본거고 마지막 Image Url은 로컬에 있는 이미지도 되는지 샘플로 한번 넣어봤다. 그리고 각 Image에 Favor라고 하는 변수들을 초기값을 포함하여 지정해 두었다.
이 때 마지막 Image 파일의 주소에 해당하는 실제 파일은 app 폴더 아래의 asset 폴더에 images라고 하는 폴더를 생성하여 그 안에 넣어두어야 한다. 그 작업은 Windows 탐색기 상에서 작업을 하면 되겠다.
다음은 Post.vue 파일이다.
[ Post.vue 파일 ] <template web> <div class="post"> <div class="post__profile" @click="goTo('profile')"> <div class="post__imgProfile"> <img src="~/assets/images/1000486794501_i1_1200.jpg" style="width: 100%"> </div> <strong>홍길동</strong> </div> <img class="post__image" :src="Image"> <div class="post__desc"> <p>{{ Description }}</p> </div> </div> </template> <template native> <StackLayout class="post"> <FlexboxLayout class="post__profile" @tap="goTo('profile')"> <StackLayout class="post__imgProfile"> <Image src="~/assets/images/1000486794501_i1_1200.jpg" style="width: 100%" /> </StackLayout> <Label text="홍길동" /> </FlexboxLayout> <Image class="post__image" :src="Image" /> <FlexboxLayout class="post__desc"> <Label textWrap :text="Description" /> </FlexboxLayout> <WrapLayout> <Button text="좋아요" width="50%" @tap="increase()" /> <Label :text="Favor" width="30%" /> </WrapLayout> </StackLayout> </template> <script> const { VUE_APP_MODE } = process.env; export default { props: { Image: String, Description: String, Favor:Number }, methods: { goTo(route){ VUE_APP_MODE === 'web' ? this.$router.push(route) : this.$navigator.navigate(route) }, increase() { this.Favor++; } } } </script> <style lang="scss" scoped web> .post{ margin-top: 20px; width: 100%; &__profile{ display: flex; flex-direction: row; padding: 0 10px 10px 10px; align-items: center; strong{ margin-left: 10px; font-size: 13px; font-weight: 500; } } &__imgProfile{ width: 35px; height: 35px; border-radius: 50%; overflow: hidden; } &__image{ width: 100%; } &__desc{ padding: 10px; p{ font-size: 12px; } } } </style> <style lang="scss" scoped native> .post{ margin-top: 20; &__profile{ padding: 0 10 10 10; Label{ margin-left: 10; font-size: 13; font-weight: 500; } } &__imgProfile{ width: 35; height: 35; border-radius: 100; overflow: hidden; } &__desc{ padding: 10; Label{ font-size: 12; } } } </style>
여기서 수정한 부분은 <template native> 부붙과 <script>의 propts 부분이다. <template native>는 native 즉 Android 화면에서 뜰 때 참조하는 부분이고 <template web>은 웹브라우저에서 뜨는 환경에서 참조하는 부분이다. template web 부분을 아무리 고쳐도 Android에는 반영되지 않으니 조심해야 한다.
<script>의 props 부분에는 Favor라고하는 변수를 추가하고 버튼을 눌렀을 때 하나씩 증가하는 이벤트 함수를 정의해 주고 이를 <tepmplate native>에 있는 <Button>에 @tab 이벤트로 추가해 주었다.
전체적인 구조를 설명하자면 Post.vue에서 Image Element와 “좋아요” 버튼, 사용자 명 등을 레코드 형식으로 정의하고 App.vue는 이러한 Post.vue Object를 읽어서 data에서 공급받은 정보를 하나씩 대입해서 화면에 반복적으로 뿌려주는 역할을 하는 앱이다.
필요한 image 파일들은 app\asset\images 폴더에 저장해 주고 ( logo 파일, 사용자 프로파일용 사진, Image 리스트 중 로컬에서 보여질 파일 등) 모두 저장한다.
Command prompt 를 실행시켜 vue-parm project 폴더로 이동한다.
C:\> cd \project\vue\vue-farm C:\project\vue\vue-farm >
이제 Android 기계(핸드폰이나 갤탭 등)를 USB로 연결하고 다시 한번 Android 설정 화면의 가장 아래에 있는 개발자 옵션에서 USB 디버깅이 On 되어 있는지 확인한다. 만약 연결할 기계가 없으면 PC 상에서 그냥 가상기계가 뜨도록 하면 된다.
C:\project\vue\vue-farm> ns run android
특별히 에러가 나지않으면 Android 기계가 화면을 깜빡이다가 갑자기 앱 화면이 뜬다. 아직 본격적인 화면과는 거리가 멀지만 뭔가 프로그램의 느낌이 나는 화면이 뜬다.
좋아요 버튼을 누르면 숫자가 0에서 1씩 증가하는 것을 볼 수 있다. 화면의 다른 곳을 잘못 누르면 에러가 나고 화면이 에러 로그로 가득 차는데 이는 goTo(‘profile’)의 route가 지정은 되어 있으나 정의되어 있지 않아 쉽게말해 링크가 깨어져 있어서 발생하는 에러이다. route에 대해서는 아직 손대지 않았으니 조금 문서들을 들여다 보고 바꿀 예정이다.
이상으로 vue의 설치와 nativescript 설치를 통해 android App 개발의 첫발을 떼는 것 까지 해 봤다. 혹시 이것저것 자료 찾기 귀찮거나 해도 잘 안되는 사람들은 머리를 비우고 그냥 한번 쭉 따라해 보면 가볍게 성공하지 않을까 싶다.
단, 주의할 점은 시간이 지남에 따라 모든 프로그램들의 버전들이 약간씩 바뀌고 버전의 변경에 따라 소스 문법이나 컴포넌트 사용법들이 약간씩 달라지는 데 이런 점은 각 버전에 맞는 문법과 사용 방법을 다시 한번 참조해야 할 것이다.
끝.