ABOUT ME

-

Total
-
  • Wails: Go언어를 이용해 크로스 플랫폼 앱 만들기
    컴퓨터/Go language 2022. 6. 26. 12:38
    728x90
    반응형

    Wails

     

    The Wails Project | Wails

    Build beautiful cross-platform applications using Go

    wails.io

     

    소개

    Wails는 Go언어를 이용하여 크로스 플랫폼 앱을 만들게 도와준다. (MacOS/Windows/Linux)

    프런트엔드는 Svelete, React 등을 사용해서 할 수 있고, wails는 Go언어로 빌드나 함수 -> JS를 도와준다.

    설치는 쉬우니 공식 사이트를 확인하면 된다. @공식 문서

    지원 플랫폼

     

    만들면서 배운 것

    결과물

    Svelte랑 프런트엔드 쪽은 많이 안 해봐서 쉬운 것부터 시작했다.

    대학교 공지 홈페이지에서 각 카테고리별로 Go언어로 파싱하고 앱에 뿌리는 것이다.

     

    Go언어 Struct -> TypeScript

    우선 Go언어로 짠 struct를 TypeScript에서 불러오는 방법이다.

    각 공지를 아래 struct에 담을 것이다. 따라서 Parse란 함수를 부르면 []Notice를 return

    json을 표시해줘야 TS에서 JSON 함수로 인식할 수 있다.

    // Go언어 Notice ...
    type Notice struct {
    	ID       int64  `json:"id"`
    	Category string `json:"category"`
    	Title    string `json:"title"`
    	Date     string `json:"date"`
    	Link     string `json:"link"`
    	Writer   string `json:"writer"`
    }

    frontend/wailsjs/go/models/models.ts

    Go언어 struct들을 여기에 모을 것이다.

    위 Go에서 json 이름 설정한대로 맞춰주면 된다.

    export namespace main {
        export class Notice {
            id: number;
            category: string;
            title: string;
            date: string;
            link: string;
            writer: string;
    
            static createFrom(source: any = {}) {
                return new Notice(source);
            }
    
            constructor(source: any = {}) {
                if ('string' === typeof source) source = JSON.parse(source);
                this.id = source["id"];
                this.category = source["category"];
                this.title = source["title"];
                this.date = source["date"];
                this.link = source["link"];
                this.writer = source["writer"];
            }
        }
    }

     

    Go언어 함수 -> TypeScript

    Go언어를 함수를 만들고 TS로 만들어주기 위해 이름만 설정해주면 된다. (wailsjs가 함수는 convert)

    모든 Go언어 함수들은 Promise type으로 return 된다. 에러를 return 안 하면 reject가 안 불리는 방식이다.

     

    frontend/wailsjs/go/main에 아래 두 파일들을 수정한다.

    App.js

    export function Parse(arg1, arg2) {
        return window['go']['main']['App']['Parse'](arg1, arg2);
    }

    App.d.ts

    import {main} from "../models/models"
    
    export function Parse(url: string, length: number): Promise<Array<main.Notice>>;

    메인/app.go

    Go언어 파일이다. 앞에 (a *App)과 같이 작성해야 wails에서 인식해서 변환시킨다.

    /// Parse 공지 불러오는 함수 (url, length) -> Promise<Notice[]>
    func (a *App) Parse(url string, length int) ([]Notice, error) {
    	ajouHTML := url
    	if url == "" { // As default, use main link
    		ajouHTML = fmt.Sprintf("%v?mode=list&articleLimit=%v&article.offset=0", AjouLink, length)
    	}
    
    	notices := []Notice{}
    
    	resp, err := soup.Get(ajouHTML)
    	if err != nil {
    		fmt.Println("[Parser] Check your HTML connection.", err)
    		return notices, err
    	}
    	doc := soup.HTMLParse(resp)
    
    	ids := doc.FindAll("td", "class", "b-num-box")
    	if len(ids) == 0 {
    		fmt.Println("[Parser] Check your parser.")
    		return notices, err
    	}
    
    	titles := doc.FindAll("div", "class", "b-title-box")
    	dates := doc.FindAll("span", "class", "b-date")
    	categories := doc.FindAll("span", "class", "b-cate")
    	//links := doc.FindAll("div", "class", "b-title-box")
    	writers := doc.FindAll("span", "class", "b-writer")
    	for i := 0; i < len(ids); i++ {
    		id, err := strconv.ParseInt(strings.TrimSpace(ids[i].Text()), 10, 64)
    		if err != nil {
    			continue // 최상위 공지
    		}
    		title := strings.TrimSpace(titles[i].Find("a").Text())
    		link := titles[i].Find("a").Attrs()["href"]
    		category := strings.TrimSpace(categories[i].Text())
    		date := strings.TrimSpace(dates[i].Text())
    		writer := writers[i].Text()
    
    		duplicate := "[" + writer + "]"
    		if strings.Contains(title, duplicate) {
    			title = strings.TrimSpace(strings.Replace(title, duplicate, "", 1))
    		}
    
    		notice := Notice{ID: id, Category: category, Title: title, Date: date, Link: AjouLink + link, Writer: writer}
    		notices = append(notices, notice)
    	}
    
    	return notices, nil
    }

    App.svelte

    위에서 설정한대로 Go언어의 Parse 함수를 불러왔다.

    <script lang="ts">
        import NoticeList from "./components/NoticeList.svelte";
        import { Parse } from "../wailsjs/go/main/App";
        
        let notices_promise = Parse("", 7);
    </script>
    
    <main>
        {#await notices_promise}
            <p>💌 공지 불러오는 중...</p>
        {:then notices}
            <NoticeList {notices} />
        {:catch _}
            <p>공지 불러오는 중 에러 발생!</p>
        {/await}
    </main>

    NoticeList.svelte

    <script>
        import NoticeItem from "./NoticeItem.svelte";
    
        export let notices;
    </script>
    
    <ul>
        {#each notices as notice (notice.id)}
            <NoticeItem {notice} />
            <br/>
        {/each}
    </ul>
    
    <style>
        ul {
            display: table;
            margin-left: auto;
            margin-right: auto;
            list-style-type: decimal;
        }
    </style>

    NoticeItem.svelte

    <script>
        export let notice;
    </script>
    
    <li>
        <a target="_blank" rel="noopener" href={notice.link}>{notice.title}</a><br
        />({notice.category}) {notice.writer} - {notice.date}
    </li>
    
    <style>
        a {
            color: inherit;
            font-weight: bold;
            text-decoration: none;
        }
    </style>

     

    728x90

    댓글