안드로이드 기기 간에 Wifi Socket 통신하기(Kotlin)


 오랜만에 안드로이드를 다루어보는 기회가 생겼는데 생각보다 많은 변화가 있었습니다. 특히 올해부터는 구글에서 새로 만든 프로그래밍 언어인 Kotlin이 도입되면서 Java 위주로 설계된 안드로이드 생태계에 거대한 변화가 있을 것으로 보입니다. 이러한 안드로이드의 환경 변화에 맞추어 제가 기존에 다루었던 프로그램들을 Kotlin으로 다시 한 번 설계해보려고 합니다.


 이전에 안드로이드 기기간의 Wi-Fi 통신 프로그래밍을 설계하였던 적이 있었는데 Kotlin으로 다시 짜보는 김에 프로그램을 최적화 해서 다시 만들어보았습니다.


AndroidMenifest.xml

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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.elecs.interandroidcommunication">
 
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
 
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
 
</manifest>
cs


strings.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<resources>
    <string name="app_name">IAC</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="ip">IP</string>
    <string name="port">PORT</string>
    <string name="name">NAME</string>
    <string name="msg">MESSAGE</string>
    <string name="hint_port">PORT NUMBER</string>
    <string name="hint_ip">192.168.0.1</string>
    <string name="hint_msg">Hello, world!</string>
    <string name="button1">Connect</string>
    <string name="button2">Disconnect</string>
    <string name="button3">Set Server</string>
    <string name="button4">Close Server</string>
    <string name="button5">View my info</string>
    <string name="button6">Send Message</string>
</resources>
 
cs


activity_main.xml

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
 
            <TextView
                android:id="@+id/textView"
                android:layout_width="70dp"
                android:layout_height="wrap_content"
                android:text="@string/ip" />
 
            <EditText
                android:id="@+id/et_ip"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:hint="@string/hint_ip"
                android:importantForAccessibility="no"
                tools:ignore="Autofill"
                android:inputType="textUri"
                android:singleLine="true" />
        </LinearLayout>
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
 
            <TextView
                android:id="@+id/textView2"
                android:layout_width="70dp"
                android:layout_height="wrap_content"
                android:text="@string/port" />
 
            <EditText
                android:id="@+id/et_port"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:hint="@string/hint_port"
                android:importantForAccessibility="no"
                tools:ignore="Autofill"
                android:inputType="number"
                android:singleLine="true" />
        </LinearLayout>
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
 
            <TextView
                android:id="@+id/textView3"
                android:layout_width="70dp"
                android:layout_height="wrap_content"
                android:text="@string/msg" />
 
            <EditText
                android:id="@+id/et_msg"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:ems="10"
                android:hint="@string/hello_world"
                android:importantForAccessibility="no"
                tools:ignore="Autofill"
                android:inputType="textPersonName" />
        </LinearLayout>
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
 
            <Button
                android:id="@+id/button_connect"
                style="@style/Widget.AppCompat.Button.Small"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:minWidth="0dip"
                android:text="@string/button1"
                android:textSize="12sp" />
 
            <Button
                android:id="@+id/button_disconnect"
                style="@style/Widget.AppCompat.Button.Small"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:minWidth="0dip"
                android:text="@string/button2"
                android:textSize="12sp" />
 
            <Button
                android:id="@+id/button_msg"
                style="@style/Widget.AppCompat.Button.Small"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:minWidth="0dip"
                android:text="@string/button6"
                android:textSize="12sp" />
        </LinearLayout>
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
 
            <Button
                android:id="@+id/button_setserver"
                style="@style/Widget.AppCompat.Button.Small"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/button3"
                android:textSize="12sp" />
 
            <Button
                android:id="@+id/button_closeserver"
                style="@style/Widget.AppCompat.Button.Small"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/button4"
                android:textSize="12sp" />
 
            <Button
                android:id="@+id/button_info"
                style="@style/Widget.AppCompat.Button.Small"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/button5"
                android:textSize="12sp" />
 
        </LinearLayout>
 
        <TextView
            android:id="@+id/text_status"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
 
    </LinearLayout>
 
</androidx.constraintlayout.widget.ConstraintLayout>
cs


MainActivity.kt

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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
package com.elecs.interandroidcommunication
 
import android.content.Context
import android.net.ConnectivityManager
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import java.io.DataInputStream
import java.io.DataOutputStream
import java.net.*
 
class MainActivity : AppCompatActivity() {
 
    companion object{
        var socket = Socket()
        var server = ServerSocket()
        lateinit var writeSocket: DataOutputStream
        lateinit var readSocket: DataInputStream
        lateinit var cManager: ConnectivityManager
 
        var ip = "192.168.0.1"
        var port = 2222
        var mHandler = Handler()
        var closed = false
    }
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        cManager = applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        server.close()
        socket.close()
 
        button_connect.setOnClickListener {    //클라이언트 -> 서버 접속
            if(et_ip.text.isNotEmpty()) {
                ip = et_ip.text.toString()
                if(et_port.text.isNotEmpty()) {
                    port = et_port.text.toString().toInt()
                    if(port<0 || port>65535){
                        Toast.makeText(this@MainActivity, "PORT 번호는 0부터 65535까지만 가능합니다.", Toast.LENGTH_SHORT).show()
                    }else{
                        if(!socket.isClosed){
                            Toast.makeText(this@MainActivity, ip + "에 이미 연결되어 있습니다.", Toast.LENGTH_SHORT).show()
                        }else {
                            Connect().start()
                        }
                    }
 
                }else{
                    Toast.makeText(this@MainActivity, "PORT 번호를 입력해주세요.", Toast.LENGTH_SHORT).show()
                }
            }else{
                Toast.makeText(this@MainActivity, "IP 주소를 입력해주세요.", Toast.LENGTH_SHORT).show()
            }
        }
 
        button_disconnect.setOnClickListener {    //클라이언트 -> 서버 접속 끊기
            if(!socket.isClosed){
                Disconnect().start()
            }else{
                Toast.makeText(this@MainActivity, "서버와 연결이 되어있지 않습니다.", Toast.LENGTH_SHORT).show()
            }
        }
 
        button_setserver.setOnClickListener{    //서버 포트 열기
            if(et_port.text.isNotEmpty()) {
                val cport = et_port.text.toString().toInt()
                if(cport<0 || cport>65535){
                    Toast.makeText(this@MainActivity, "PORT 번호는 0부터 65535까지만 가능합니다.", Toast.LENGTH_SHORT).show()
                }else{
                    if(server.isClosed) {
                        port = cport
                        SetServer().start()
                    }else{
                        val tstr = port.toString() + "번 포트가 열려있습니다."
                        Toast.makeText(this@MainActivity, tstr, Toast.LENGTH_SHORT).show()
                    }
                }
            }else{
                Toast.makeText(this@MainActivity, "PORT 번호를 입력해주세요.", Toast.LENGTH_SHORT).show()
            }
        }
 
        button_closeserver.setOnClickListener {    //서버 포트 닫기
            if(!server.isClosed){
                CloseServer().start()
            }else{
                mHandler.obtainMessage(17).apply {
                    sendToTarget()
                }
            }
        }
 
        button_info.setOnClickListener {    //자기자신의 연결 정보(IP 주소)확인
            ShowInfo().start()
        }
 
        button_msg.setOnClickListener {    //상대에게 메시지 전송
            if(socket.isClosed){
                Toast.makeText(this@MainActivity, "연결이 되어있지 않습니다.", Toast.LENGTH_SHORT).show()
            }else {
                val mThread = SendMessage()
                mThread.setMsg(et_msg.text.toString())
                mThread.start()
            }
        }
 
        mHandler = object : Handler(Looper.getMainLooper()){  //Thread들로부터 Handler를 통해 메시지를 수신
            override fun handleMessage(msg: Message) {
                super.handleMessage(msg)
                when(msg.what){
                    1->Toast.makeText(this@MainActivity, "IP 주소가 잘못되었거나 서버의 포트가 개방되지 않았습니다.", Toast.LENGTH_SHORT).show()
                    2->Toast.makeText(this@MainActivity, "서버 포트 "+port +"가 준비되었습니다.", Toast.LENGTH_SHORT).show()
                    3->Toast.makeText(this@MainActivity, msg.obj.toString(), Toast.LENGTH_SHORT).show()
                    4->Toast.makeText(this@MainActivity, "연결이 종료되었습니다.", Toast.LENGTH_SHORT).show()
                    5->Toast.makeText(this@MainActivity, "이미 사용중인 포트입니다.", Toast.LENGTH_SHORT).show()
                    6->Toast.makeText(this@MainActivity, "서버 준비에 실패하였습니다.", Toast.LENGTH_SHORT).show()
                    7->Toast.makeText(this@MainActivity, "서버가 종료되었습니다.", Toast.LENGTH_SHORT).show()
                    8->Toast.makeText(this@MainActivity, "서버가 정상적으로 닫히는데 실패하였습니다.", Toast.LENGTH_SHORT).show()
                    9-> text_status.text = msg.obj as String
                    11->Toast.makeText(this@MainActivity, "서버에 접속하였습니다.", Toast.LENGTH_SHORT).show()
                    12->Toast.makeText(this@MainActivity, "메시지 전송에 실패하였습니다.", Toast.LENGTH_SHORT).show()
                    13->Toast.makeText(this@MainActivity, "클라이언트와 연결되었습니다.",Toast.LENGTH_SHORT).show()
                    14->Toast.makeText(this@MainActivity,"서버에서 응답이 없습니다.", Toast.LENGTH_SHORT).show()
                    15->Toast.makeText(this@MainActivity, "서버와의 연결을 종료합니다.", Toast.LENGTH_SHORT).show()
                    16->Toast.makeText(this@MainActivity, "클라이언트와의 연결을 종료합니다.", Toast.LENGTH_SHORT).show()
                    17->Toast.makeText(this@MainActivity, "포트가 이미 닫혀있습니다.", Toast.LENGTH_SHORT).show()
                    18->Toast.makeText(this@MainActivity, "서버와의 연결이 끊어졌습니다.", Toast.LENGTH_SHORT).show()
                }
            }
        }
    }
 
    class Connect:Thread(){
 
        override fun run(){
            try{
                socket = Socket(ip, port)
                writeSocket = DataOutputStream(socket.getOutputStream())
                readSocket = DataInputStream(socket.getInputStream())
                val b = readSocket.read()
                if(b==1){    //서버로부터 접속이 확인되었을 때
                    mHandler.obtainMessage(11).apply {
                        sendToTarget()
                    }
                    ClientSocket().start()
                }else{    //서버 접속에 성공하였으나 서버가 응답을 하지 않았을 때
                    mHandler.obtainMessage(14).apply {
                        sendToTarget()
                    }
                    socket.close()
                }
            }catch(e:Exception){    //연결 실패
                val state = 1
                mHandler.obtainMessage(state).apply {
                    sendToTarget()
                }
                socket.close()
            }
 
        }
    }
 
    class ClientSocket:Thread(){
        override fun run() {
            try{
                while (true) {
                    val ac = readSocket.read()
                    if(ac == 2) {    //서버로부터 메시지 수신 명령을 받았을 때
                        val bac = readSocket.readUTF()
                        val input = bac.toString()
                        val recvInput = input.trim()
 
                        val msg = mHandler.obtainMessage()
                        msg.what = 3
                        msg.obj = recvInput
                        mHandler.sendMessage(msg)
                    }else if(ac == 10){    //서버로부터 접속 종료 명령을 받았을 때
                        mHandler.obtainMessage(18).apply {
                            sendToTarget()
                        }
                        socket.close()
                        break
                    }
                }
            }catch(e:SocketException){    //소켓이 닫혔을 때
                mHandler.obtainMessage(15).apply {
                    sendToTarget()
                }
            }
        }
    }
 
    class Disconnect:Thread(){
        override fun run() {
            try{
                writeSocket.write(10)    //서버에게 접속 종료 명령 전송
                socket.close()
            }catch(e:Exception){
 
            }
        }
    }
 
    class SetServer:Thread(){
 
        override fun run(){
            try{
                server = ServerSocket(port)    //포트 개방
                mHandler.obtainMessage(2"").apply {
                    sendToTarget()
                }
 
                while(true) {
                    socket = server.accept()
                    writeSocket = DataOutputStream(socket.getOutputStream())
                    readSocket = DataInputStream(socket.getInputStream())
 
                    writeSocket.write(1)    //클라이언트에게 서버의 소켓 생성을 알림
                    mHandler.obtainMessage(13).apply {
                        sendToTarget()
                    }
                    while (true) {
                        val ac = readSocket.read()
                        if(ac==10){    //클라이언트로부터 소켓 종료 명령 수신
                            mHandler.obtainMessage(16).apply {
                                sendToTarget()
                            }
                            break
                        }else if(ac == 2){    //클라이언트로부터 메시지 전송 명령 수신
                            val bac = readSocket.readUTF()
                            val input = bac.toString()
                            val recvInput = input.trim()
 
                            val msg = mHandler.obtainMessage()
                            msg.what = 3
                            msg.obj = recvInput
                            mHandler.sendMessage(msg)    //핸들러에게 클라이언트로 전달받은 메시지 전송
                        }
                    }
                }
 
            }catch(e:BindException) {    //이미 개방된 포트를 개방하려 시도하였을때
                mHandler.obtainMessage(5).apply {
                    sendToTarget()
                }
            }catch(e:SocketException){    //소켓이 닫혔을 때
                mHandler.obtainMessage(7).apply {
                    sendToTarget()
                }
            }
            catch(e:Exception){
                if(!closed) {
                    mHandler.obtainMessage(6).apply {
                        sendToTarget()
                    }
                }else{
                    closed = false
                }
            }
        }
    }
 
    class CloseServer:Thread(){
        override fun run(){
            try{
                closed = true
                writeSocket.write(10)    //클라이언트에게 서버가 종료되었음을 알림
                socket.close()
                server.close()
            }catch(e:Exception){
                e.printStackTrace()
                mHandler.obtainMessage(8).apply {
                    sendToTarget()
                }
            }
        }
    }
 
    class SendMessage:Thread(){
        private lateinit var msg:String
 
        fun setMsg(m:String){
            msg = m
        }
 
        override fun run() {
            try{
                writeSocket.writeInt(2)    //메시지 전송 명령 전송
                writeSocket.writeUTF(msg)    //메시지 내용 
            }catch(e:Exception){
                e.printStackTrace()
                mHandler.obtainMessage(12).apply {
                    sendToTarget()
                }
            }
        }
    }
 
    class ShowInfo:Thread(){
 
        override fun run(){
            lateinit var ip:String
            var breakLoop = false
            val en = NetworkInterface.getNetworkInterfaces()
            while(en.hasMoreElements()){
                val intf = en.nextElement()
                val enumIpAddr = intf.inetAddresses
                while(enumIpAddr.hasMoreElements()){
                    val inetAddress = enumIpAddr.nextElement()
                    if(!inetAddress.isLoopbackAddress && inetAddress is Inet4Address){
                        ip = inetAddress.hostAddress.toString()
                        breakLoop = true
                        break
                    }
                }
                if(breakLoop){
                    break
                }
            }
 
            val msg = mHandler.obtainMessage()
            msg.what = 9
            msg.obj = ip
            mHandler.sendMessage(msg)
        }
    }
 
}
 
cs



위의 코드를 실행화면 다음과 같은 화면이 나타납니다.




※Sever 사용 방법

1. Port에 원하는 포트 번호를 입력합니다.

2. 'SET SERVER' 버튼을 클릭하면 포트를 열 수 있습니다. 만약 다른 프로세스에서 포트를 사용중일 경우 다른 포트 번호를 입력합니다.

3. 'VIEW MY INFO' 버튼을 클릭하면 현재 접속중인 IP주소를 알 수 있습니다. 이를 Client의 IP란에 입력해주세요.

4. Client와의 연결이 성공하면 Toast로 연결에 성공하였다는 알림이 나옵니다.


※Client 사용 방법

1. IP와 PORT에 서버의 IP주소와 설정 PORT 번호를 입력합니다.

2. 'CONNECT' 버튼을 클릭하여 서버에 접속합니다. 성공시 Toast로 접속에 성공하였다는 메시지를 확인하실 수 있습니다.

3. 'SEND MESSAGE' 버튼을 클릭하면 MESSAGE 칸에 입력한 텍스트 정보를 상대에게 전송할 수 있습니다.

4.  'DISCONNECT' 버튼을 눌러 서버와의 연결을 해제합니다.

Surrogate model(대체 모델)

공대생의 팁 2019. 11. 6. 12:56


 Surrogate model(대체 모델, 근사수학모델)이란 자동차 충돌 실험과 같이 제한된 계산 비용이 많이 드는 시뮬레이션을 기반으로 복잡한 시스템의 수많은 입출력 특성을 실제 모형과 유사하게 만드는 것을 목적으로 하는 소형 확장 분석 모델을 일컫는 말입니다.


 Surrogate model은 시뮬레이션 모델의 복잡한 동작을 흉내낼 수 있으며, 이러한 특성은 설계 자동화, 매개변수 분석, 우주 탐사에 관한 설계, 최적화 및 민감도 분석등에 사용될 수 있습니다.


 Surrogate model은 또한 meta model(메타 모델), response surface model(RSM, 반응표면분석법), 에뮬레이터, auxiliary model(보조 모델), repro-model(복제 모델)이라고도 부릅니다.


https://www.esteco.com/modefrontier/method-selecting-surrogate-models-crashworthiness-optimization


 교통사고와 같이 의도치 않은 상황에서 운전자가 생존할 수 있는 방법을 연구하기 위해서는 차량의 충돌을 분석하여 이를 통해 운전자의 생존률을 높이는 방법을 찾는 것은 매우 중요합니다. 그러나 차량 한 대의 가격은 매우 비싸기 때문에 수많은 차량들을 이용하여 충돌 실험을 하게 될 경우 엄청난 양의 비용이 필요합니다. 만약 Surrogate model을 설계하여 이를 활용한다면 해당 모델로 만들어진 차량을 시뮬레이션으로 반복적으로 사용할 수 있게 되고 실제 차량을 사용하여 발생하는 비용을 최소화 할 수 있습니다. 또한, surrogate model을 사용함으로서 얻게 되는 최적화된 솔루션을 개발하여 실제 차량에 적용한다면 더 좋은 결과를 얻을 수 있을 것입니다.


 

https://www.oreilly.com/radar/ideas-on-interpreting-machine-learning/


 인공지능을 해석함에 있어 surrogate model은 매우 중요한 모델입니다. 2019년 현재 시점에서 인공신경망을 해석하기에는 매우 어렵습니다. 너무나도 많은 매개변수(Parameter)들이 있고 이들의 변화를 사람의 눈으로 파악하기엔 변수가 너무나 많기 때문입니다.

 이러한 인공신경망 모델을 해석하기 위해 입력값을 의사결정트리 혹은 선형모델에 대입하여 surrogate model로 만들어 해당 인공신경망 모델의 특성을 최대한 이해하는 용도로 사용할 수 있습니다.

 



참고자료: http://sumo.intec.ugent.be/surrogates

VirtualBox에 안드로이드 설치 도중 부팅이 멈출 때 해결방법

공대생의 팁 2019. 10. 21. 14:42


 한동안 안드로이드와는 거리를 두고 지내던 도중 종종 관련 질문이 들어와서 최신 버전인 Oreo를 VirtualBox에 설치를 아래와 같은 방식으로 시도해 보았었습니다.


안드로이드 버추얼박스(VirtualBox)에 설치하기


 제가 안드로이드를 설치하려 하였던 환경은 아래와 같습니다.


Host OS버전: Ubuntu 16.04

VirtualBox 버전: 6.0.14

Android 버전: 8.1(Oreo)


 위와 같은 환경에서 링크에서 제공하는 설치 방법대롤 하였으나 아래와 같이 화면이 멈추면서 더이상 진행이 되지 않고 있었습니다.


 Trusted GRUB now loading 'Android-x86 8.1-r2'

 Progress: Detecting Android-x86... found at /dev/sda1

X86_64:/ #



정황상 안드로이드가 설치된 파티션을 찾아내어 이를 불러오는 것 까지는 성공한 것 같으나 현 상황에서 알 수 없는 이유로 화면이 더이상 나올 수 없는 상황으로 추정됩니다.


 이를 해결하기 위해 VirutlaBox에서 설정→디스플레이로 접근하신 다음 아래와 같이 나왔을 때 'VBoxVGA'를 선택해줍니다.



 위에 표시도니 VBoxVGA로 설정하신 후 다시 안드로이드를 실행해보시면 아래와 같이 부팅이 정상적으로 동작하고 있는 것을 확인하실 수 있습니다!



Canon MG2990 시리즈 USB 연결 설치방법

흔치않은일상 2019. 10. 11. 02:03


 이사를 하면서 통신사에서 제공하는 공유기를 사용하게 되었는데 호환이 잘 안되는 것 같아 USB로 연결하여 설치해 보았습니다. 이번에 공유기를 통해 무선으로 설치하는 방법을 다루어 본 적이 있었는데 혹시 무선 설치가 안되시는 분들을 위해 이렇게 USB 유선 연결 설치 방법도 소개해 드려볼까 합니다.


 혹시 공유기가 프린터 근처에 있고 무선으로 여러 대의 기기를 사용하고 계신 분이라면 제가 이전에 작성하였던 무선 설치 방법을 참고해 주시기 바랍니다.


    Canon MG2900 시리즈 무선 프린터 설치방법



※설치하시기 전에 반드시 프린터와 컴퓨터와 USB를 빼주세요.


1. 아래의 사이트에 접속하여 '드라이버 통합 설치파일'을 다운로드 받습니다.(Windows 기준)

http://www.canon-bs.co.kr/person/download.aspx?no=3588&category1=2



2. 다운로드 받은 파일을 실행하면 아래와 같은 화면이 나옵니다.



3. '다음' 버튼을 누르면 아래와 같이 드라이버 설치 준비를 합니다.



4. 프린터 연결 방법을 선택합니다. 여기서는 'USB 연결'을 선택해 보겠습니다.



5. 사용자의 거주지를 선택합니다.



6. 자신이 거주하는 국가를 선택해줍니다.



7. 맨 위에 있는 'MP Drivers'를 설치해줍니다.(기본으로 선택이 되어있음)



8. '예' 버튼을 클릭해주세요.



9. '예' 버튼을 클릭해 주세요.



10. 인터넷을 통해 설치 파일을 받는 과정입니다. 잠시 기다려줍니다.



11. 다음과 같은 화면이 나오면 이제 컴퓨터와 프린터를 USB로 연결해줍니다.



 MG2990 프린터의 경우 USB 꽃는 곳은 다음과 같이 뒷부분 오른쪽에 위치해 있습니다.

 프린터에 연결되는 USB는 TypeB 형식으로 일반적인 프린터에서 자주 사용하는 방식입니다.



12. 프린터를 연결하고 프린터의 전원을 키면 아래와 같이 컴퓨터와 프린터가 연결되었음을 확인하실 수 있습니다.



13. 기다리시면 컴퓨터에 드라이버가 자동으로 설정이 됩니다.



14. 프린트 헤드 정력 과정입니다. 만약 프린터를 처음 사용하는 경우라면 실행 버튼을 눌러 안내가 나오는 대로 진행하시면 됩니다.



15. '다음' 버튼을 누르시면 프린터의 설치가 완료됩니다! 이제 프린터를 자유롭게 사용하실 수 있게 되었습니다!



16. '끝내기' 버튼을 눌러 설치 프로그램을 종료합니다.




모노레일, 마을을 잇다 - 태백선 고한역[2019.08.30]


 강원도의 험한 산령을 굽이굽이 해체 나가면서 강릉으로 향하던 태백선 무궁화호는 남한에서 가장 높은 곳에 위치한 태백시의 추전역을 앞에 두고 정신군 고한읍에 위치한 고한역에 오게됩니다. 추전역이 운영되지 않고 있는 현재 우리나라에서 가장 높은 해발고도(705m)에 위치한 고한역은 높은 산이 많은 강원도의 특성을 잘 나타낸다고 할 수 있겠지요.



고한역은 마을에서 약간 높은 곳에 위치해 있습니다.



약간의 오르막길을 올라 고한역에 와보았습니다.



고한역 옆에는 객차를 가조한 시설이 위치해 있습니다.



고한역 앞에는 작은 맞이방이 마련되어 있습니다.



입구 한켠에 추리만화책들을 모아둔 책꽃이가 있습니다.



열차가 오지 않는 시간대의 고한역은 고요합니다.



열차는 하루에 10회 운행되고 있습니다.

청량리행은 오후 6시 39분이 막차입니다.



사북역에는 없던 고객대기실이 마련되어 있군요.



고한역의 오른쪽에 카페가 있군요.



고한역 앞에 있는 나무계단을 내려오면 마을사람들의 사진들이 붙어있습니다.



한산한 마을 안에 제법 큰 초등학교 건물이 보입니다.



과거 탄광촌이었던 고한읍에는 광부의 자녀들이 학교를 다녔겠지요.



고한시장의 입구



탄광촌이었던 마을의 특성을 시장에 잘 살려놓았습니다.



고한시장의 반대편에서 바라본 모습

마을을 돌아다니던 도중 배가고파 점심을 해결했습니다.








갈비탕이 상당히 맛이 좋았습니다.



고한읍내를 둘러 개천이 흐르고 있습니다.

탄광이 한창 운영될 때 이 천에는 검은 물이 흘렀다고 하더군요.



마을 인근에는 고한모노레일이 운행되고 있습니다.



모노레일은 생각보다 상당히 작아보입니다.

흔히 타는 엘리베이터 크기 정도랄까요?



모노레일에 직접 탑승해 보기로 하였습니다.



모노레일 차량 안에서 레일을 바라본 모습



차량 내부는 엘리베이터와 흡사하게 생겼습니다.

문을 열고 닫는 버튼이 엘리베이터의 그것과 똑같습니다.



오르막길을 올라갈때 생각보다 빠르더군요.



아랫쪽을 보니 상당히 가파른 언덕입니다.



읍내 너머를 자세히 보니 고한역이 보입니다.



모노레일은 다시 제가 탑승하였던 곳으로 이동합니다.



모노레일 바로 옆에 강원랜드 사무실이 있었군요.



마을 너머로 보이는 태백선



이제 다시 다리를 건어 고한역으로 돌아갑니다.


날이 어두워지자 카페 간판의 별에 불이 들어옵니다.



방금전에 보았던 그 객차의 뒷모습

다른데로 이동할 예정이 없는지 체인으로 꽁꽁 묶어놓고 있습니다.



이제 우리는 고한역을 떠납니다.



열차가 오기를 기다리며...



잠시후 청량리행 무궁화호 열차가 고한역으로 들어옵니다.



이제 기차에 몸을 싣고 집으로 돌아갑니다.

이 장소를 Daum지도에서 확인해보세요.
강원 정선군 고한읍 고한리 97-11 | 한쇼
도움말 Daum 지도

탄광의 마을에서 리조트의 마을로 - 태백선 사북역[2019.08.30]


 청량리를 출발하여 제천을 거쳐 강릉으로 가는 무궁화호는 우리나라가 산업화가 한창이던 시절 석탄을 수송하기 위한 목적으로 건설한 태선을 지나갑니다. 태백선은 1974년 전철화가 완료되어 힘 좋은 전기기관차가 석탄을 나르던 곳이기도 하지요. 그러나 석탄이 사양 사업이 되면서 수많은 사람들이 일자리를 잃게 되었고 특히 정선군 내에 대표적인 탄광촌이었던 사북과 고한은 활기를 잃고 맙니다.

 몰락하는 탄광촌을 막기 위해 정부는 인근에 리조트를 건설하고 한국인이 유일하게 출입이 허가된 카지노인 강원랜드를 만들게 되면서 사람들은 다시 마을로 몰려들었습니다. 리조트의 건설로 마을의 수입원이 다시 생기게 되었지만 도박중독 등의 사회적인 문제를 떠안게 되었습니다.



제천역에서 강릉행 무궁화호를 타고 사북역에 도착합니다.



예전에 새마을호가 다녔던 적이 있었는데 아직까지 타는곳에 표시가 되있네요.



역에서 내리자마자 호텔촌이 보입니다.



어느새 열차는 출발하기 위해 출입문을 닫습니다.



열차는 그렇게 고한역을 향해 달려갑니다.



고한역을 유유히 빠져나가는 무궁화호



사북역 안에는 탄광열차의 모형이 전시되어 있었습니다.



불과 몇십년전만 해도 이 동네에는 이러한 탄광열차가 돌아다니고 있었습니다.



이제 사북역사 내로 이동합니다.



역내에는 분식집이 있습니다.

콤프도 사용할 수 있었나보군요.



흔한 매표소의 모습



열차를 타러 가는 방향에서 바라본 모습



사북역 인근에는 주 수입원인 하이원 리조트가 위치해 있습니다.



역 밖을 나오자마자 마주친 대출광고를 보고 이 동네의 분위기를 짐작할 수 있었습니다.



마을 안은 호텔들이 잔뜩 늘어서 있었습니다.



주변이 호텔촌인 것에 비해 한적한 사북역



안그래도 좁은 마을에 폐건물이 역앞에 있으니 더 처량해 보입니다.



사북역 삼거리



좀 더 걸어가다 보면 사북시장이 보입니다.



사북역에서 가장 많이 보이는 가게는 전당사입니다.

그 다음으로 많이 보이는 가게는 마사지샵...



도박에 빠진 사람들을 위해 기도하는 교회도 있나봅니다.



강원랜드가 위치한 하이원리조트로 들어가는 입구



강원랜드의 현실을 보여주는 씁쓸한 사진

번호판을 떼인 차량이 주인을 하염없이 기다리고 있습니다.



정선군 또한 평창올림픽 개최지로 알파인 스키 경기가 개최되었습니다.

이 곳 사북에서는 거리가 어느정도 됩니다만

이 곳에서도 수호랑과 반다비가 있군요.



잠시 마을을 한 바퀴 돌다온 사이에 대출 명함들이 덕지덕지 붙어있습니다.



세상에나, 서울 면허의 택시가 이 외딴동네까지 와있습니다.

소문에 의하면 서울에서 강원랜드까지 10만원 이상을 주고 여기까지 온다는 분들이 계시더군요.


마을을 둘러본 후 또다른 탄광촌이었던 고한역으로 이동합니다.





환골탈태(換骨奪胎)를 위해여 - 제천임시역(4)[2019.08.30]


  중앙선과 충북선, 태백선을 달려온 모든 열차가 모이는 제천역은 전국의 여행객들이 한 번쯤은 거쳐가는 곳이라 할 수 있겠지요. 자신이 가고자 하는 방향에 따라서 이 곳에서 열차를 갈아타야 하기 때문이지요. 청량리에서 안동이나 태백으로 가시는 분이라면 열차에서 내릴 필요 없이 바로 갈 수 있지만 충북선을 이용해야 하는 경우 제천역이 충북선의 시종착역 역할을 하고 있기에 이 곳에서 자연스레 갈아타게 됩니다.


 충북선을 타고 제천역에서 정선으로 향하는 열차를 갈아타기 위해 이번에도 제천역을 방문하게 되었습니다. 지금까지 제천역을 방문하였던 이야기들은 아래의 글들을 보아주시길 바랍니다.



환골탈태(換骨奪胎)를 위해여 - 제천임시역(1)[2010.02.04]


환골탈태(換骨奪胎)를 위해여 - 제천임시역(2)[2018.10.28]


환골탈태(換骨奪胎)를 위해여 - 제천임시역(3)[2018.12.16]




지난번에 충북선 제천행 열차를 타고 왔을 땐 임시승강장에서 내렸었는데

이번에는 새로 개조한 승강장에 승객들을 내려줍니다.



마침 강릉행 무궁화호가 잠시후 도착하는데

환승하는 승객들의 편의를 위해 이곳에 내려준 것일까요?



물론 제천역이 목적지인 분들은 나가는곳으로 향합니다.



가만보니 제가 내린 승강장은 작년 12월까지만 해도 공사를 하느라 막아둔 곳이었습니다.



한동안 이 승강장을 쓸 예정인지 안내판에 '임시'라는 글씨까지 써두었습니다.



보아하니 기존의 승강장은 고상홈으로 탈바꿈 하였습니다.



임시승강장도 아직은 운영되고 있습니다.



승강장 공사는 완료되었지만 아직 계단 공사는 끝내지 못한듯 합니다.



작년까지 홀로 쓰이던 승강장도 벌써 고상홈 공사가 한창입니다.



고상홈 개량 공사가 끝나면 철거될 줄 알았던 지하통로가 아직도 사용되고 있습니다.



바로 옆 승강장 또한 고상홈으로 개량하고는 있으나 지하통로는 막아두지 않고 있습니다.



고상홈 승강장에 올라갈 수 있도록 나무계단으로 연결되어 있습니다.

신역사 계단 공사가 끝날 때 까지는 계속 사용될 듯 보입니다.



공사중인 승강장으로 가는 길은 현재 출입을 금지하고 있습니다.



휠체어 리프트가 있는데 과연 사용은 되고 있긴 할까요



역내 안내는 현재 공사 상황까지 반영하여 놓았습니다.

대전방면의 임시승강장까지 가는 길 또한 안내되고 있습니다.



잠시 쉬는 곳



제천역의 새로운 역사를 건설한지 벌써 1년반이 지났습니다.



이제 창문도 붙이고 생각보다 공사 속도는 빨라보입니다.

마음만 먹으면 2019년이 끝나기 전에는 개통될 것 같습니다만

언제나 그랬듯이 2020년에 개통되겠지요.



며칠전까지 휑하던 임시역사 뒷편도 건물이 올라가고 있습니다.



다시 승강장으로 돌아가 강릉행 열차를 타러 갑니다.



승강장까지 이동하는 통로도 골조는 모두 완성되었습니다. 이제 붙이기만 하면 될 듯!



어느새 강릉행 열차가 승강장으로 들어오고 있습니다.

저상흠 승강장은 지하통로에서 고상흠 끝까지 걸어가야 하기 때문에 역 내에도 열차 출발 15분 전까지는 도착하기를 권하고 있습니다.

실제로 나이 많으신 분들은 고상홈 승강장을 모두 건너오시는데 많이 힘들어 하십니다.



작년까지만 해도 특실로 운행되었던 1호차입니다.

이젠 무궁화호 특실이 사라졌지만 운이 좋다면 기존의 특실을 이용할 수 있습니다.


이제 다음 여행지인 사북역으로 향합니다.





Windows 10 Internet Explorer 11 에서 Adobe flash가 샐행되지 않을때 해결방법

공대생의 팁 2019. 8. 26. 13:31


 2020년 말부터 Chrome 웹브라우저가 Adobe에서 제공하는 Flash Player 지원을 종료한다고 하였습니다. 인터넷 초창기에 벡터 방식을 사용하여 저용량으로 고용량의 동영상보다도 고화질로 화면에 표현할 수 있다는 점 때문에 Flash는 상당히 많이 사용되었습니다.

 그러나 인터넷 속도가 점점 향상되면서 2019년 오늘날에는 유튜브와 같은 고화질 동영상을 무리없이 다운로드 받아 실시간으로 재생할 수 있는 환경이 만들어지면서 고도의 연산을 필요로 하는 Flash는 오늘날의 인터넷 환경에서는 빠른 속도를 요구하는 웹브라우저에도 어울리지 않게 되면서 점차 사용이 줄어들고 있는 상황입니다. 최근에 제작되는 사이트들도 다양한 디바이스 환경에서 접속되는 것을 대비하기 위해 반응형 사이트를 제작하기에 Flash를 사용하는 것은 더더욱 어려워졌습니다.


 그럼에도 아직까지 우리나라에서는 Flash가 사용되는 사이트들이 아직까지 존재하고 있습니다. Flash가 점점 퇴출되어가는 과정에서도 우리나라의 환경에서는 웹브라우저의 Flash 지원 종료는 조금은 불편하게 느껴지는 것은 사실입니다. 티스토리 또한 Flash를 사용하지 않는 새로운 웹에디터를 제공함으로서 (비록 새로운 에디터의 장단점을 떠나서) Flash의 의존에서 점차 멀어져 가고 있는 상황에서 말이지요. 이러한 우리나라의 인터넷 환경에서 Flash가 실행되지 않을 때 이를 해결하는 방법에 대해 다루어보겠습니다.


 먼저 아래의 링크를 클릭하셔서 Flash Player를 활성화합니다.



IE(Internet Explorer) 어도비플래시플레이어 설치 및 활성화 방법 안내

↑↑위 링크를 클릭해주세요



 만약 위의 링크대로 하였지만 여전히 실행이 되지 않을 경우 아래의 방법을 참고해주시길 바랍니다.





 2019년 8월 현재 Flash Player로 서비스를 제공하는 사이트들 중 하나인 더존 세금계산서(https://www.bill36524.com)를 Windows 10 운영체제에서 Internet Explorer 11로 접속한 후 로그인을 하게 되면







 위의 화면과 같이 '어도비 플래시 플레이어 꼭 설치 하셔야 합니다!'라는 경고문구와 함께 플래시를 설치할 것을 요구하고 있습니다.








 그러나 Windows 10에서 부터는 Internet Explorer 11에는 이미 Flash Player가 포함이 되어있기 때문에 별도의 설치를 하지 않더라도 Flash Player를 실행할 수 잇어야 합니다. 이는 Flash Player를 사용하려는 사이트에서 호환성에 문제가 발생히여 실행이 되지 않는 것으로 추측됩니다.






 혹시 인터넷 익스플로러의 버전 문제 때문일 가능성이 있어 Internet Explorer를 다른 버전으로 설치하려고 시도하였으나 Windows 10에서는 Internet Explorer가 기본프로그램으로 설정되어 있기 때문에 삭제할 수 없으며 게다가 이전 버전으로 다운그레이드를 시키는 것도 사실상 불가능합니다.


 그렇다면 Windows 10에서 Internet Explorer의 이전 버전을 실행할 수 있는 방법은 없을까요? Internet Explorer 11에서는 이전 버전의 환경에서 사이트에 접속할 수 있도록 하는 에물레이션 모드가 존재하여 11 이하의 버전의 환경에서 웹브라우저를 사용할 수 있습니다.


 Internet Explorer 11을 실행하신 다음 'F12'버튼을 누르시면 아래의 화면과 같이 개발자도구창이 나타납니다.





개발자도구창이 나타나면 메뉴에서 '에뮬레이션'을 클릭합니다.





에뮬레이션 창을 클릭하면 다음과 같은 창을 보실 수 있습니다. 위의 메뉴 중 '문서 모드'를 보시면 11(기본값)이라 적혀있는 부분을 보실 수 있습니다. 이는 해당 사이트를 Internet Explorer 11 모드에서 접속중이라는 의미입니다.





문서 모드에서 버전이 적혀있는 부분을 클릭하시면 11 이외의 모드를 선택할 수 있습니다. Internet Explorer 10 버전 모드에서 해당 사이트에 접속하고 싶다면 '10'을 선택해줍니다.






에뮬레이션 모드로 문서 모드를 11 이하의 버전으로 설정하여 접속하게 되면 이전과 같이 Flash Player를 설치해달라는 창이 나오지 않고 곧바로 플래시가 실행된 창이 나타나는 것을 확인하실 수 있습니다.





기차가 스쳐가는 아름다운 바닷가가 있는 곳 - 영동선 안인역과 안인해변[2019.08.20]


 영동선 동해 - 강릉 구간은 바닷가에 근접하여 열차가 달리는 구간입니다. 그 덕에 열차안에서 푸르른 바닷가가 차창 너머로 펼쳐집니다. 이러한 광경이 아름답고 멋지기에 관광 상품으로 바다열차가 만들어져 운행되고 있지요.


 평소 무궁화호 안에서 풍경으로만 보아왔던 안인역 인근의 해변을 직접 보기 위해 차를 타고 직접 찾아가 보았습니다.





정동진역과 강릉역 사이에 위치한 안인역입니다.

평범한 간이역처럼 보이지만 매우 중요한 역할을 하고 있는 역입니다.



현재 여객 업무를 취급하고 있지 않지만 아직 승강장은 남아있습니다.



그럼에도 이 역이 중유한 이유는 이 역의 바로 뒷편에 위치한 시설 때문입니다.



역 뒷편에 위치한 영동화력발전소의 발전을 위한 물자를 수송하기 위해 이 역이 매우 중요한 것이지요.

그러나 역 주변에서 바다를 보기 위해서는 다소 멀리 떨어진 마을로 이동해야 합니다.





안인진리에 위치한 안인해변에는 철길이 마을의 한중간을 지나가고 있습니다.



철로 바로 옆에 바닷가를 볼 수 있어 상당히 좋은 뷰포인트입니다.



마을 사이에는 철길을 건널 수 있는 육교가 설치되어 있습니다.



바닷가를 마주보고 물회를 판매하는 가게가 위치해 있습니다.



철길 바로 옆에는 고양이들이 횟집에서 버려진 물고기를 가져와 먹고 있습니다.



보아하니 이제 한달 정도 된 어린 고양이들이로군요.



철길은 이 곳을 지나 바닷가를 유유히 떠나 강릉역을 향합니다.



철길 옆에 강아지 한마리가 꼬리를 흔들며 낮선이를 반깁니다.



이 곳을 지나 정등진역까지 열차 옆으로 동해의 아름다운 바다가 훤히 보입니다.



이제 한 번 바닷가를 걸어보겠습니다.



이제 막 해수욕장이 폐장되어 사람들은 많이 보이지 않습니다.

그리도 바닷가에는 한 가족일행이 물놀이를 하고 있습니다.



이제 올해 말이면 KTX를 타고 이 멋진 경관을 볼 수 있게 될 것입니다.

다음에는 KTX를 타고 이 곳을 방문하고자 합니다.






이 장소를 Daum지도에서 확인해보세요.
강원 강릉시 강동면 안인리 165-1 | 안인역
도움말 Daum 지도

KTX 타고 동해바다로! - 남강릉삼각선[2019.08.20]


 2017년 평창 동계올림픽 개최를 대비하여 경강선이 강릉역까지 개통되어 강릉에서 KTX를 탈 수 있게 되었습니다. 이어 올해 진부에서 강릉으로 이어지는 선로에 삼각선을 새로 추가하여 KTX가 동해역까지 어이질 수 있도록 남강릉삼각선을 건설하여 앞으로는 서울역에서 정동진역까지 KTX로 한 번에 갈 수 있게 됩니다.


 올해 12월에 개통될 남강릉삼각선 구간을 안인해변을 들리는 도중에 둘러보았습니다.





현재 무궁화호만 운행되고 있는 비행장건널목입니다.

건널목 너머에는 강릉선KTX가 운행되고 있는 경강선 고가가 있습니다.



이 두 노선은 강릉역에 도착하기 전 합류한 후 지하로 이어집니다.



건널목 이름의 유래는 인근의 군부대에서 따온 듯 합니다.

횡단보도 옆에는 해당 부대의 이름이 적혀 있습니다.



안인역(정동진역 방향)에서 바라본 모습

오른쪽에 살짝 보이는 고가가 남강릉삼각선입니다.



강릉역 방향

여기서 얼마 안가 경강선과 합류합니다.



강릉역 구간이 지하화 되는 동안 이 곳도 약간의 개량을 거친 듯 합니다.



기존에는 없던 철조망을 설치하여 안전도를 높였습니다.


이번에는 남강릉삼각선이 영동선과 합류하는 부분으로 이동하였습니다.





사동3건널목



이곳 건널목에서 길이 두 갈래로 나뉘어집니다.

왼쪽은 진부역, 오른쪽은 강릉역



KTX의 종착역이 될 동해역 방향입니다.



건널목 바로 앞이 급곡선으로 되어있어 경보기가 건널목에서 떨어진 위치에 있습니다.



이런식으로 두 대의 경보기가 설치되어 있습니다.



분기점이 의외로 가까운 곳에 있었습니다.



나중에 이 곳으로 KTX가 지나다니겠군요.



버스정류장 이름이 매우 적절합니다.



2차선이던 도로가 여기서부터는 좁아집니다.

건널목이 좁아서 차량이 한대가 지나갈 공간만 있습니다.



차량이 그렇게 많이 지나다니지는 않아서 굳이 2차선으로 확장할 필요는 없어보입니다.



갑자기 경보기가 울리다너 차단기가 내려옵니다.

곧 열차가 통과할 모양입니다.



안인역 방향에서 기관차가 울리는 경보음이 들립니다.



강릉까지 운행되는 무궁화호 열차였습니다



열차는 순식간에 지나 뒷꽁무니만 보인 채고 강릉역으로 향합니다.



남강릉삼각선을 설치하는 과정에서 주민들의 반발이 컸나봅니다.



남강릉삼각선이 경강선과 합류하는 지점입니다.

아직은 공사가 한창인 모양입니다.



KTX가 지나다니게 된다면 이 마을은 이제 고요하지는 않을 것 같네요.



남강릉삼각선이 마을을 관통하는 구간으로 와보았습니다.



고가로 설계되어 통행 자체는 큰 문제는 없을것 같아 보입니다.



확실히 고가는 마을을 관통하는 위치에 있습니다.



마을 안의 산을 깎은 부분이 보입니다.



지금은 공사중이지만 마무리만 하면 금방 완성될 만큼 진척도는 빠릅니다.



공사중인 철길 위에 희안한 이동체가 보입니다.

설마 사람의 힘으로 움직이는 걸까요?



공사가 끝난 후 서울역에서 KTX를 타고 정동진에 갈 수 있는 날을 고대해봅니다!


이 장소를 Daum지도에서 확인해보세요.
강원 강릉시 월호평동 | 비행장교차로
도움말 Daum 지도

시내를 관통하던 철길이 공원으로 변신하다 - 강릉 월화거리[2019.08.20]


 동해선의 강릉 시내구간이 지하화되면서 철길로 단절되었던 공간이 사람들이 돌아다닐 수 있는 공간이 되면서 월화거리는 많은 사람들이 왕래할 수 있는 산책로가 되었습니다. 특히 평창동계올림픽을 치루고 난 이후에는 강릉을 찾아오는 관광객들이 걸어다닐 수 있는 관광지로 부상하였죠.



  남대천 인근에 있는 월화정 인근에서 부터 월화거리를 걸어보았습니다.



철길로 단절되었던 마을이 통행로가 되면서 길이 아름답게 꾸며졌습니다.



야간에 방문한다면 꽤 좋은 경치가 될 것 같습니다.



터널 내부는 특별히 조명시설을 갖추고 있지는 않았습니다.

짧은 구간이어서 굳이 조명이 크게 필요하지는 않은 듯 합니다.



터널을 통과한 후 나와보니 생각보다는 어두워보이네요.



과거에 건널목이 있을법한 부분에서는 이렇게 횡단보도를 철길처럼 그려놨습니다.



공원 인근에 위치한 O Chair와 월화정



남대천을 건널 수 있도록 기존의 철교를 보강하여 보행이 가능하게 만들어졌습니다.



철고 위에서 바라본 강원도의 풍경



그 반대편의 모습



바닥에는 마치 철도를 형상화한 듯 남겨둔 것 같아 보입니다.



바로 옆부분에는 바닥을 투명하게 하여 남대천을 직접 볼 수 있도록 만들어 놓았습니다.



철교 위에서 월화정을 바라보고서...




이 장소를 Daum지도에서 확인해보세요.
강원 강릉시 노암동 275-2 | 월화정
도움말 Daum 지도

하나된 열정, 뜨거운 열정! 평창 동계올림픽(5) - 1년후 이야기 [2019.08.20]


  평창올림픽이 개최된지 벌써 1년이 지났습니다. 올림픽의 열기는 아직까지 느껴지는것 같지만 기억속의 모습들은 서서히 옅어져가고 있습니다. 지난 겨울 환호성이 울려퍼졌던 평창올림픽 경기장에 방문하여 그 때의 함성을 기억해보았습니다.



가톨릭관동대학교에 위치한 하키경기장입니다.

남북단일팀이 이 곳에서 경기를 하였을 때 엄청난 인파가 줄을 이었던 기억이 나네요.



하키장 인근은 공원으로 잘 꾸며져 있습니다. 작년에도 이 정도로 만들었던 것으로 기억하고 있습니다.



시설이 사용되고 있지 않는지 관계자 외에는 출입을 하지 못하게 하고 있습니다.

1988년 서울올림픽이 개최되었던 한양대학교 올림픽체육관이 지금도 활용되고 있는 걸 생각하면 참으로 아쉬운 부분입니다.

비록 하키경기장으로 설계되었지만 사후 활용 방안을 만든다면 학생들이 사용할 수 있지 않을까 싶지만

방법을 찾아보기 어려운가봅니다.



이번에는 강릉역 너머에 위치한 올림픽파크에 도착하였습니다.



이곳에 있는 강릉 하키 센터는 당시 사용했던 안내판을 그대로 사용하고 있었습니다.



올림픽 당시에 이 곳에 많은 사람들이 있었다는게 한편으론 믿어지지가 않는군요.



이번에는 강릉종합운동장으로 이동해봅니다.

작년 이 곳에 방문했던 기록은 아래의 링크로 확인해봅니다.


하나된 열정, 뜨거운 열정! 평창 동계올림픽(1) - 남북단일팀[2018.02.14]

https://elecs.tistory.com/249



올림픽이 개최되었던 곳임을 이 스케이트 한 짝의 모형이 나타내고 있습니다.



모형 옆에는 수많은 원형 모형들 사이 오륜기가 그려져 있습니다.



비록 올림픽은 끝났지만 오륜기는 남아있습니다.



실내 로울러스케이트장



경기장 한컨에는 암벽등반장이 마련되어 있습니다.

며칠전 영화 '엑시트'를 보았었는데 암벽등반이 결코 쉬운 액티비티는 아니더군요.



경기장 내부의 모습입니다.

올림픽 당시에 이 곳을 보지 못한건 참으로 아쉽습니다.



동네 축구동호회 회원들이 경기 준비를 하는 듯한 모습이 보입니다.



오륜마크만이 덩그러니...



강릉스피드스케이팅경기장



이곳도 외부인은 출입을 제한하고 있습니다.



2019년 11월에 강릉커피축제를 한다는군요.


이번에는 올림픽 개폐회식이 진행되었던 평창 대관령으로 이동해봅니다.



평창올림픽의 시작을 알린 성화는 이 곳에 있습니다.

작년 이 곳에서 성화에 불이 활활 타던 모습은 아래의 포스팅에서 확인해봅니다.


하나된 열정, 뜨거운 열정! 평창 동계올림픽(3) - 성화

https://elecs.tistory.com/251



2019년 현재 평창올림픽 성화대는 이렇게 황량하게 서있습니다.



정말 성화 주변은 그 어떤 건물도 하나 없습니다.



성화대 근처에 가까이 가보니 안으로 들어갈 수 있게 되어 있습니다.



성화가 서있던 곳에서 올림픽스터디움이 있던 곳으 바라본 모습입니다.

대관령답게 험준한 산령이 펼쳐져 있습니다.



평창 올림픽 및 패럴림픽 로고

처음 발표되었을 땐 한글 가지고 유치하게 만든거같아 보였는데

지금 다시 보니 정말 잘 만들어진 로고입니다.



성화 내부 벽에는 각종 경기 기록들을 기록하고 있었습니다.



양쪽 벽에 각각 올림픽과 패럴림픽 기록을 걸어두었더군요.



평창올림픽의 기록이 이렇게나마 남아있는건 그나마 다행이라 볼 수 있겠지요?

서울올림픽 시설들처럼 남아있을 것이라 기대하고 어렵게 오신 분들께는 조금은 아쉬울 수도 있겠네요.



정말 놀랍게도 성화대 너머에는 비닐하우스 철골들이 줄지어 있습니다.



성화대 너머로 보이는 마을의 모습들입니다.

올림픽이 끝난 지금은 관광객도 많이 줄어들었다고 하네요.



영동고속도로를 힘차게 차를 몰고 여기까지 올라왔습니다.

올림픽이 개최되었던 곳이지만 택시 구하기도 마땅치 않아 차를 몰고 돌아다니는게 오히려 편한 동네였습니다.


부디 내년에도 지금보다 더 나은 모습으로 시설들이 남아있었으면 하는 마음입니다.

올림픽을 성공적으로 치루었던 만큼 남은 시설들이 애물단지가 되지 않도록 활용된다면

앞으로 우리나라도 동계올림픽 강국이 될 수 있지 않을까요?






이 장소를 Daum지도에서 확인해보세요.
강원도 평창군 대관령면 |
도움말 Daum 지도