이름 : 호피폴라, HOPPIPOLLA 
방문일시 : 2019.07.13 오전 11시 10분경 
위치 : 울산 울주군 서생면 나사해안길 6-5(울산 울주군 서생면 신암리 43-4) 
연락처 : 053-238-2425 
운영시간 : 매일 11:00~23:00 

출발하기 전에 날씨가 흐리고, 비가 온다는 예보도 있고, 가는 길에 비가 오기도 하였고, 도착해서 비가 오기도 하였지만 점차 날씨가 좋아져서 구름낀 바다, 비내리는 바다, 날씨 좋은 바다 다 볼 수 있어서 좋았네요. 

바다가 바로 코앞이고, 바로 옆은 나사해수욕장 이라서 커피 마시다 여차 하면 바다에 발 담글 수도 있는 곳입니다. 

카페라떼, 크로와상 등을 먹었는데, 크로와상을 시키면 빵을 데워주시는 것 같았어요. 오픈한지 얼마 안 되서 인지 빵이 너무 맛있더군요. 

1층 실내에 자리가 있고, 실외도 아주 넓고 여유롭습니다, 2층은 노키즈 존 입니다, 실내 자리가 있고 테라스도 있어요. 
3층은 루프탑이고 테이블 없이 그냥 뷰만 볼 수 있는 곳이에요. 

기장 쪽은 아직 많이 안 가봤고, 지금까지 가본 오션뷰 카페 중에는 포항에 네스트 카페와 여기 호피폴라 가 대구 근교 (인근) 오션뷰 카페 중에는 아주 인상적이고 좋네요. 둘 중에 하나만 꼽으라면.... 흠.... ㅜㅜ 저는 패스. ㅎㅎ;

 

2층에서 내려다 본 모습
2층 테라스 뷰
1층 구석에서 본 호피폴라 카페 건물 측면

 

1층 실내 안쪽

 

들어가는 길에 이렇게 거울이 있어요.

 

1층 건물 안에서 실외로 나가는 문을 열자마자 오른편에 있는 자리인데 꽤 편하고 아늑해 보였어요.

 

1층 실외 끝쪽으로 가보면 이렇게 바다로 바로 내려갈 수 있는 계단이 있습니다.
이런 의자가 1개인가 2개 있었던 거 같아요.

 

흐린 날씨에도, 비가 조금씩 오는데도, 오픈 한지 얼마 안 되었는데도, 실내에는 사람이 꽤나 많았답니다.

 

오픈한지 얼마 안 되서 가서 그랬는지, 크로와상 예술이에요. 바삭하고 부드럽고, 이런 크로와성 오랜만에 먹어봤네요. 역시 빵은 바로 구운 걸 먹어야 하나봐요.

 

 

3층 루프탑 전경

 

3층 루프탑에서 본 오션뷰 - 1

 

3층 루프탑에서 본 오션뷰 - 2

 

2층 테라스

 

호피폴라, HOPPIPOLLA 카페 입구

 

1층 실외에서 찍은 오션뷰

 

1층 실내 안쪽 전경

 

 

이름 : 스퀘어루트, SQUARE ROOT 
방문일시 : 2019.08.01 오후 1시경 
위치 : 강원도 고성군 죽왕면 가향길 2-7(강원도 고성군 죽왕면 가진리 275) 
연락처 : 033-681-0604 
운영시간 : 매일 09:00~21:00 

여름 휴가로 강원도를 다녀왔습니다. 8월 1일, 2일 1박 2일로 다녀왔는데, 역시 대구에서 강원도 멀긴 머네요. ㅜㅜ 
강릉, 속초, 고성 그리고 숙소가 있는 평창 등을 다녔는데, 고성 스퀘어 루트 앞에 바다가 너무 예쁘네요. 

강원도 바다 하면 수심 깊고, 높은 파도가 몰아치고 이런 것만 떠올렸는데, 스퀘어 루트 앞에 바다는 완전 잔잔하고, 얕고 바다색이 이렇게 예쁠 수가 없습니다. 제주도에서도 이렇게 잔잔하고, 얕고, 에머랄드 빛 나는 바다는 없었던 것 같은데 말이죠.  

서울 사는 분들은 여름에는 스퀘어 루트 한 군데만 찍어서 와도 괜찮다 싶네요. 카페 있으시면서 바다로 나가시는 분들 꽤 많고 어떤 분들은 텐트나 수영복 튜브 등을 준비하고 와서 아예 거기서 물놀이 하시는 분들도 있더라구요. 
저희도 다음에 갈 때는 그렇게 놀아볼까 싶네요. ㅋㅋ 

포항 네스트 카페나 울산 호피폴라 처럼 카페에 있으면서 파도 치는 소리를 들을 수 있는 카페는 아니지만 바다색이 워낙 예뻐서 그냥 마냥 좋으네요. 


4층 루프탑에서 보는 뷰가 참 좋은데 엘레베이터가 없다는 점은 정말 아쉽네요. ㅜㅜ 

그리고 남자화장실은 외부에 있는데, 정말로 화장실 냄새가 물씬 풍기는 곳이었어요. 간만에 화장실에서 코로 숨 안 쉬고, 입으로 숨 셨네요. ㅎㅎ 

주문 후 별관으로도 이동 가능합니다. 별관 2층 구석에도 뷰가 나름 괜찮으니 참고하세요.

 

스퀘어루트 진입 직전 언덕배기에서 찍은 전경. 무슨 성 같으네요. ㅎㅎ

 

별관 루프탑에서 찍은 오션뷰
별관 루프탑에서 찍은 오션뷰

 

별관 루프탑에서 찍은 스퀘어루트 카페 본관 측면 모습, 사진 아래에 보이는 곳이 본관 들어가는 입구에요.

 

바다로 나가서 찍은 가진롱비치 해변. 바다 색깔 정말 예술이에요. 당장 뛰어들어가고 싶어져요. >.<

 

본관 루프탑에는 이런 자리가 있구요. 이 자리에 앉아서 사진 대충 찍어도 인생샷 한 두장 쯤은 건질 수 있을 거 같네요. 근데, 4층까지 걸어올라가야 한다는.... ㅜㅜ

 

못 먹은 빵은 여기서 포장해서 가져가면 되요. 본관 입구 바로 옆에 있어요.

 

문제의 남자 화장실.... 청소를 전혀 안하는지 화장실 냄새가 정말 많이 나더라구요. ㅜㅜ

 

저 밑에 텐트 친거 보이시죠. 튜브 들고 해수욕 하시는 분들도 몇 분 계셨어요. 저도 다음엔 그렇게 해야겠어요. ㅋㅋ. 바다가 예술이네요.

 

본관 루프탑에도 이렇게 자리가 마련되어 있어요.

 

본관과 별관 사이에 이런 자리도 있고,

 

별관 건물입니다. 본관에서 주문 후 이동 가능해요.

 

2층 안쪽 구석에 이런 자리가 마련되어 있습니다. 뷰가 나름 괜찮아요.

 

본관 들어가는 입구 입니다. 건물 측면에 있네요.

 

 

 

다시 봐도 바다색 참 예쁘네요. 애들과 놀기 정말 딱인 해변이에요. 가까운 곳에 샤워시설이나 부대시설이 없는게 단점이긴 하지만요. 

 

 

 

이름 : 카페산, CAFE SANN
방문일시 : 2019.08.10 오후 2시경
위치 : 충청북도 단양군 가곡면 두산길 196-86(충청북도 단양군 가곡면 사평리 246-33)
연락처 : 1644-4674
운영시간 : 
평일 09:30 - 19:30
토요일 08:30 - 19:30
일요일 08:30 - 18:30
공휴일 08:30 - 19:30
RAST ORDER : 마감30분전, 연중무휴

대구에서 빨리가면 2시간에 갈 수 있습니다. 1시간 30분 넘어가면 시간적으로, 거리적으로 조금 멀다는 느낌이 들긴 하네요. 그래도 가보면 뷰도 좋고, 바람불면 시원하고 좋아요. >.< 

네비찍고 가다보면 마지막 20분 정도는 포장인듯 포장아닌 살짝 비포장 도로 입니다. 길이 좁아서 운전 조심해야 하구요. 마지막 진입 구간은 일방통행이고, 안내해주시는 분이 있어서 안내해주시는대로 가면 됩니다. 도착하면 왠 건물이 하나 있는데 그 건물이 카페산 건물이구요, 그 건물 지나가도 뒤쪽으로 큰 공터가 있고, 주차 가능하지만, 차에서 건물까지 살짝 멀고, 길 상태가 흙먼지 날리니 아이들 데리고 가시는 분들은 왠만하면 건물 앞에 바로 주차하시는 것이 좋을 거 같아요. 근데 사람 많을 때는 자리가.... 

원래있던 건물 바로 옆에 새로 건물 짓는 중입니다. 그러면 자리 잡기가 조금 수월해지겠죠.

 

건물 바로 옆에 패러글라이딩 하는 곳입니다. 테라스쪽에서 보면 비행하는 모습 바로 볼 수 있습니다. 낙하산이 바로 앞에서 쫙 펴지는데 사진을 제대로 찍진 못했네요.ㅜㅜ

 

건물 앞 테라스에 앉아서 찍은 사진 이에요. 사진만 봐도 상쾌해지네요.

 

건물 외관입니다. 이 건물 오른쪽으로 2층짜리 새 건물을 짓고 있습니다.

 

건물 앞 마당(?) 주위로 이렇게 천막 처진 자리들이 있는데, 에어컨 틀어놓은 건물 만큼 시원하진 않지만 바람 불면 이 자리들도 시원하고 괜찮아요.

 

건물 앞 테라스의 테이블들, 건물 유리에 비친 모습.

 

빵 종류 다양하고, 먹을만 해요.
이 의자들이 총 4개 정도 있었던 거 같은데, 인기 많더군요. ㅋㅋ

 

건물 옥상(?) 입니다. 매장 내부의 계단으로 계속 올라가면 나갈 수 있어요.

 

건물 옥상에서 찍은 마당 사진.
카페산 건물 바로 옆 패러글라이딩 출발하는 곳.
2층짜리 건물이 원래 있던 건물 바로 옆에 붙어서 지어지는 중입니다.

 

카페산 갔다가 내려오는 길에 보이는 다리.

 

덮쳐오는 손길을 미처 막지 못했네요. >.<

 

 

패러글라이딩 출발 모습

 

카페산(CAFE SANN) 건물 앞 테라스에서 찍은 영상

 

 

육아에 지친 분들은 산으로 들로 바다로 많이 놀러 다녀야죠. 주말에는. ㅎㅎ; 
한번쯤은 가볼만한 카페산(CAFE SANN) 입니다. 

Reference : https://developer.android.com/google/play/billing/billing_library_overview

 

1. app 수준 build.gradle 에 dependencies 추가

 

1
2
3
4
dependencies {
   ...
implementation 'com.android.billingclient:billing:1.2'
}
cs

 

 

 

2. 소스코드

결제기능을 구현하고자 하는 화면에 아래 구문 추가.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
public class BuyPointActivity extends AppCompatActivity implements PurchasesUpdatedListener {
    Context mContext;
 
    // create new Person
    private BillingClient mBillingClient;
 
    SkuDetails skuDetails700, skuDetails2100;
    String skuID700 = "point_700", skuID2100 = "point_2100";  //제품 ID
    ...
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_buy_point);
        mContext = BuyPointActivity.this;
        ...
        mBillingClient = BillingClient.newBuilder(mContext).setListener(this).build();
        mBillingClient.startConnection(new BillingClientStateListener() {
            @Override
            public void onBillingSetupFinished(@BillingResponse int billingResponseCode) {
                if (billingResponseCode == BillingResponse.OK) {
                    // The billing client is ready. You can query purchases here.
                    List<String> skuList = new ArrayList<> ();
                    skuList.add(skuID700);
                    skuList.add(skuID2100);
                    SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
                    params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP);
                    mBillingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
                        @Override
                        public void onSkuDetailsResponse(int responseCode, List<SkuDetails> skuDetailsList) {
                            // Process the result.
                            if (responseCode == BillingClient.BillingResponse.OK && skuDetailsList != null) {
                                for (SkuDetails skuDetails : skuDetailsList) {
                                    String sku = skuDetails.getSku();
                                    String price = skuDetails.getPrice();
 
                                    if(skuID700.equals(sku)) {
                                        skuDetails700 = skuDetails;
                                    } else if(skuID2100.equals(sku)) {
                                        skuDetails2100 = skuDetails;
                                    } 
                                }
                            }
                        }});
                }
            }
 
            @Override
            public void onBillingServiceDisconnected() {
                // Try to restart the connection on the next request to
                // Google Play by calling the startConnection() method.
            }
        });
    }
 
    /**
     * Handle a callback that purchases were updated from the Billing library
     */
    @Override
    public void onPurchasesUpdated(int responseCode, @Nullable List<Purchase> purchases) {
        if (responseCode == BillingClient.BillingResponse.OK
                && purchases != null) {
            for (Purchase purchase : purchases) {
                handlePurchase(purchase);
            }
        } else if (responseCode == BillingClient.BillingResponse.USER_CANCELED) {
            // Handle an error caused by a user cancelling the purchase flow.
        } else {
            // Handle any other error codes.
        }
    }
 
    private void doBillingFlow(SkuDetails skuDetails) {
        BillingFlowParams flowParams;
        int responseCode;
 
        // Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
        flowParams = BillingFlowParams.newBuilder().setSkuDetails(skuDetails).build();
        responseCode = mBillingClient.launchBillingFlow(BuyPointActivity.this, flowParams);
 
        /*if(responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED) {
            Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(BillingClient.SkuType.INAPP);
            onPurchasesUpdated(BillingClient.BillingResponse.OK, purchasesResult.getPurchasesList());
        }*/
    }
 
    private void handlePurchase(Purchase purchase) {
        String purchaseToken;
        purchaseToken = purchase.getPurchaseToken();
        mBillingClient.consumeAsync(purchaseToken, consumeListener);
    }
 
    ConsumeResponseListener consumeListener = new ConsumeResponseListener() {
        @Override
        public void onConsumeResponse(@BillingClient.BillingResponse int responseCode, String outToken) {
            if (responseCode == BillingClient.BillingResponse.OK) {
                // Handle the success of the consume operation.
                // For example, increase the number of coins inside the user's basket.
            }
        }
    };
 
    Button.OnClickListener mClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            int id = v.getId();
 
            switch (id) {
                case R.id.btn700:
                    doBillingFlow(skuDetails700);
                    break;
 
                case R.id.btn2100:
                    doBillingFlow(skuDetails2100);
                    break;
                ...
            }
        }
    };
    ...
}
cs

 

 

 

 

doBillingFlow 안에 if(responseCode == BillingClient.BillingResponse.ITEM_ALREADY_OWNED)

코드는 처음에 테스트 구매 하다가 구매성공 후에 consume 처리를 안해서 다시 구매가 안 된 경우에 consume 시키려고 놔둔 코드 입니다. 구매 완료후 consume 를 제대로 하지 못한 경우 등에 이 코드를 쓰면 될 것 같습니다.

TrivialDrive v2 sample app 은 너무 복잡해서 잘 이해가 안 되고, anjlab 의 android-inapp-billing-v3 는 왠지 안내켜서 Google Play 결제 라이브러리 사용하여 구현해보았습니다. 인앱 결제 구현 구글 문서는 최신 내용이 아닌 듯 합니다. 업무에 참고 하시기 바랍니다.

ps.

-. 이 방법을 사용하면 Google 마켓 개발자 콘솔 설정에 있는 '서비스 및 API' 의 Base64 인코딩 RSA 공개 키 인 애플리케이션용 라이선스 키 를 입력하지 않아도 됩니다.

-. Manifest 에 <uses-permission android:name="com.android.vending.BILLING" /> 도 추가하지 않아도 됩니다. 다만 앱 등록시 인앱상품 생성을 위해 이 권한을 요구하긴 합니다.

-. 인앱 결제 테스트 및 디버깅(참고 : https://developer.android.com/google/play/billing/billing_testing?hl=ko)*인앱결제를 디버깅 모드에서도 테스트 하려면 알파 또는 베타 채널에 앱을 게시해야 하고, 게시하면 생기는 테스트 주소 https://play.google.com/apps/testing/com.android.test 와 같은 주소를 인터넷 앱등을 통해 접속한 후

테스트 참여 대상 관리 에 등록된

계정 주소를 입력해야 합니다. 이렇게 하고 나면 개발하는 앱의 디버깅 모드에서도 결제 테스트가 가능합니다. 테스트 참여 대상 관리 에 등록된 사용자만 테스트 주소(https://play.google.com/apps/testing/com.android.test)에 등록되는지는 확인해보지 못했습니다.
1. Google Play Console 접속2. 좌측 하단 '설정' 클릭3. 라이선스 테스트 추가테스트 하고자 하는 계정을 추가합니다. (구글 플레이에 설정된 계정 등)

 

 

 

 

 

 

 

+ Recent posts