1. imgur 사이트에서 open api 로 이미지 업로드 기능을 제공한다.


imgur api doc 사이트 접속 : https://apidocs.imgur.com/


하면 다음과 같은 사이트가 나온다.






2. API를 사용하기 위해서는 https://api.imgur.com/oauth2/addclient 경로로 들어간다.





다음 화면에서 application name, callback url, email을 작성해준다.

postman에서 사용할 callback url인 https://www.getpostman.com/oauth2/callback 을 입력해준다.


작성 후 submit을 누르면 


Client ID, Client secret을 제공해준다.





이제 계정을 테스트해봐야한다.



3. 구글에서 postman을 검색해 설치해준다.



크롬 확장프로그램이 아닌 postman application 프로그램으로 다운받아 설치한다.



4. postman을 통해 테스트 환경설정 하기



이후 Authorization 탭의 TYPE OAuth 2.0 을 선택하고 Get New Access Token을 누른다.







Callback URL :  https://www.getpostman.com/oauth2/callback 


Auth  https://api.imgur.com/oauth2/authorize


Access Token URL https://api.imgur.com/oauth2/token


Client ID : 애플리케이션 등록하며 받은 ID


Client secret : 애플리케이션 등록하며 받은 secret


입력하고 Request Token을 누른다.


그러면 imgur 로그인을 allow 할지 deny할지 물어본다.

당연히 allow하여 access하는것을 허용한다.


성공적이라면 다음과 같이 refresh_token을 제공해준다.





해당 내용을 메모장에 복사한 후 Use Token을 클릭한다.


오른족 상단 톱니바퀴를 클릭하여 add environment를 하여 환경설정에 다음과 같이 입력한다.


발급받은 refreshToken


애플리케이션 등록할때 발급받은  clientId, clientSecret


의 값을 넣어주고 환경설정을 변경해준다.







5. 테스트 Access Token 실행하기


이후 imgur API 에서 제공해주는 여러 테스트 코드의 Account > Generate Access Token을 실행해본다.

POST방식으로 send를 보내면 결과값이 잘 나타난것을 확인할 수 있다.






6. 업로드 해보기


위에 과정이 성공적으로 나타났다면 이미지 업로드를 해볼차례이다.


다음과 같은 index.html 파일을 생성한다.



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
<!DOCTYPE html>
<html>
<head>
    <script
  src="https://code.jquery.com/jquery-3.3.1.js"
  integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
  crossorigin="anonymous"></script>
</head>
<body>
    <button id="upload">upload image</button>
    <script type="text/javascript">
 
    $( document ).ready(function() {
        var form = new FormData();
        form.append("image""https://avatars0.githubusercontent.com/u/9919?s=280&v=4");
 
        var settings = {
          "url""https://api.imgur.com/3/image",
          "method""POST",
          "timeout"0,
          "headers": {
            "Authorization""Client-ID c1934aa57a01a08"
          },
          "processData"false,
          "mimeType""multipart/form-data",
          "contentType"false,
          "data": form
        };
 
        $("#upload").click(function() {
            $.ajax(settings).done(function (response) {
              console.log(response);
              alert(response);
            });
        });
    });
    </script>
</body>
</html>
cs



버튼을 눌렀을때 이미지를 imgur api 를 사용해 이미지 웹서버로 전송한다.

현재 이 코드에서 필요한 것은 


1. A binary file, base64 data, or a URL for an image (up to 10MB)

2. Client-ID 이다.


ajax 통신을 통해 image 정보와, client id를 넣어 data를 보내면 response로 json을 반환한다.



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
{
  "data": {
    "id": "lnX1JMq",
    "title": null,
    "description": null,
    "datetime": 1553655107,
    "type": "image/png",
    "animated": false,
    "width": 280,
    "height": 280,
    "size": 13959,
    "views": 0,
    "bandwidth": 0,
    "vote": null,
    "favorite": false,
    "nsfw": null,
    "section": null,
    "account_url": null,
    "account_id": 0,
    "is_ad": false,
    "in_most_viral": false,
    "has_sound": false,
    "tags": [],
    "ad_type": 0,
    "ad_url": "",
    "edited": "0",
    "in_gallery": false,
    "deletehash": "HQF1cQmsRB1lHsa",
    "name": "",
    "link": "https://i.imgur.com/lnX1JMq.png"
  },
  "success": true,
  "status": 200
}
cs



반환한 데이터의 업로드된 이미지 url로 접속하면


https://i.imgur.com/lnX1JMq.png


업로드가 잘 된 것을 확인 할 수 있다.



  1. 남갯 2019.03.27 14:05 신고

    개발블로그시네요 자주방문하겠습니다!



택배 배송조회 API인 스윗트래커(https://tracking.sweettracker.co.kr/)를 사용하여 배송정보를 받아오는 테스트를 해보겠다.



1. 먼저 https://tracking.sweettracker.co.kr/ 이동하여 회원가입을 한다.







2. 자신의 API 키를 발급받는다. 테스트이므로 무료키를 받겠다.









3. http://info.sweettracker.co.kr/apidoc API 문서를 본다.





4. 택배 배송정보를 RESTful 형태로 제공하므로 Base Url 에 자신이 필요로하는 api를 사용하면 된다.



5. 본인은 운송장 번호를 조회하기 위해 택배사목록을 조회하고 택배사목록과 운송장 번호를 통해 배송조회를 할 것이다.



6. 크롬 확장프로그램에서 POSTMAN을 설치 후 company-api와 tracking-api의 파람값을 알아본다.




company-api에서는 다음과 같이 코드와 택배회사명을 가져올 수 있고


tracking-api에서는 배송정보와 배송추적에 대한 정보를 가져올 수 있었다.




테스트를 위해 웹프로젝트를 생성하고 Jquery Ajax를 통해 해당 정보를 받아오겠다.



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
<script>
$(document).ready(function(){
    var myKey = "JUI5lF7RHlbZHdNPCjhfYw"// sweet tracker에서 발급받은 자신의 키 넣는다.
    
        // 택배사 목록 조회 company-api
        $.ajax({
            type:"GET",
            dataType : "json",
            url:"http://info.sweettracker.co.kr/api/v1/companylist?t_key="+myKey,
            success:function(data){
                    
                    // 방법 1. JSON.parse 이용하기
                    var parseData = JSON.parse(JSON.stringify(data));
                     console.log(parseData.Company); // 그중 Json Array에 접근하기 위해 Array명 Company 입력
                    
                    // 방법 2. Json으로 가져온 데이터에 Array로 바로 접근하기
                    var CompanyArray = data.Company; // Json Array에 접근하기 위해 Array명 Company 입력
                    console.log(CompanyArray); 
                    
                    var myData="";
                    $.each(CompanyArray,function(key,value) {
                            myData += ('<option value='+value.Code+'>' +'key:'+key+', Code:'+value.Code+',Name:'+value.Name + '</option>');                        
                    });
                    $("#tekbeCompnayList").html(myData);
            }
        });
        // 배송정보와 배송추적 tracking-api
        $("#myButton1").click(function() {
            var t_code = $('#tekbeCompnayList option:selected').attr('value');
            var t_invoice = $('#invoiceNumberText').val();
            $.ajax({
                type:"GET",
                dataType : "json",
                url:"http://info.sweettracker.co.kr/api/v1/trackingInfo?t_key="+myKey+"&t_code="+t_code+"&t_invoice="+t_invoice,
                success:function(data){
                    console.log(data);
                    var myInvoiceData = "";
                    if(data.status == false){
                        myInvoiceData += ('<p>'+data.msg+'<p>');
                    }else{
                        myInvoiceData += ('<tr>');                
                        myInvoiceData += ('<th>'+"보내는사람"+'</td>');                     
                        myInvoiceData += ('<th>'+data.senderName+'</td>');                     
                        myInvoiceData += ('</tr>');     
                        myInvoiceData += ('<tr>');                
                        myInvoiceData += ('<th>'+"제품정보"+'</td>');                     
                        myInvoiceData += ('<th>'+data.itemName+'</td>');                     
                        myInvoiceData += ('</tr>');     
                        myInvoiceData += ('<tr>');                
                        myInvoiceData += ('<th>'+"송장번호"+'</td>');                     
                        myInvoiceData += ('<th>'+data.invoiceNo+'</td>');                     
                        myInvoiceData += ('</tr>');     
                        myInvoiceData += ('<tr>');                
                        myInvoiceData += ('<th>'+"송장번호"+'</td>');                     
                        myInvoiceData += ('<th>'+data.receiverAddr+'</td>');                     
                        myInvoiceData += ('</tr>');                                       
                    }
                    
                    
                    $("#myPtag").html(myInvoiceData)
                    
                    var trackingDetails = data.trackingDetails;
                    
                    
                    var myTracking="";
                    var header ="";
                    header += ('<tr>');                
                    header += ('<th>'+"시간"+'</th>');
                    header += ('<th>'+"장소"+'</th>');
                    header += ('<th>'+"유형"+'</th>');
                    header += ('<th>'+"전화번호"+'</th>');                     
                    header += ('</tr>');     
                    
                    $.each(trackingDetails,function(key,value) {
                        myTracking += ('<tr>');                
                        myTracking += ('<td>'+value.timeString+'</td>');
                        myTracking += ('<td>'+value.where+'</td>');
                        myTracking += ('<td>'+value.kind+'</td>');
                        myTracking += ('<td>'+value.telno+'</td>');                     
                        myTracking += ('</tr>');                                    
                    });
                    
                    $("#myPtag2").html(header+myTracking);
                    
                }
            });
        });
        
});
</script>
cs


AJAX를 통해 해당 정보를 잘 받아 출력되는 것을 확인하였다.





마지막으로 해당 전체소스를 첨부한다.


다운로드:


openAPI활용.zip





  1. 궁금합니다... 2019.06.04 19:43

    택배정보 직접입력(이름, 주소, 송장번호, 배송완료등 ) 할때는 어떻게 하셨나요? 전체소스zip에는없네요... ㅠ

    • effortDev 2019.06.06 14:53 신고

      테스트 목적 코드로 오래전에 작성한 거라
      필요한 컨텐츠가 포함되지 않을수 있습니다. 감사합니다.

  2. 테스터 2019.07.04 15:54

    감사합니다. 잘 참고해서 사용하겠습니다 !!

  3. 악덕뮤지션 2019.08.30 00:22 신고

    크흑...감사합니다 센세

  4. windows6587 2019.12.17 17:18

    php에 적용 못하던가요 ㅠㅠ php로 하니까 이상하네여...

    • effortDev 2019.12.21 15:09 신고

      키값이 만료되어 그럴수도 있습니다. js와 jquery를 쓸수있다면 작동 가능할 것 같습니다.

  5. 붸엑 2020.01.28 04:54

    url부분에 http를 https로 바꾸시면 자물쇠표시 잘 뜨면서 사용가능합니다!!

  6. 익명 2021.08.15 21:26

    비밀댓글입니다


구글 로그인 api 웹 인증하기



웹 프로젝트를 간단히 생성한다.


나는 test1의 이름을 가진 프로젝트를 만들고 NewFile.html 파일을 만들었다.




그리고 html 파일의 내용은 구글 api에서 나온 소스를 모두 가져와서 사용했다.

참고 : (https://developers.google.com/identity/sign-in/web/





그리고 서버를 생성해 실행시켜본다.






google-signin-client_id가 맞지 않아 실행이 되지 않을 것이다.


client_id를 받기 위해 구글 개발자 콘솔로 가자.


1. https://console.developers.google.com 이동


2. 사용자 인증정보로 이동


3. 사용자 인증정보 만들기



4. 클라이언트ID가 생성됨을 확인할 수 있다.


5. OAuth 클라이언트 ID > 웹 어플리케이션 > 승인된 자바스크립트원본 http://localhost:8080 입력 

> 승인된 리디렉션 URI > http://localhost:8080/test1/NewFile.html 를 입력한다.


이 ID값을  NewFile.html 의 <meta name="google-signin-client_id" content="">

content값으로 넣어주고 실행한다.



이후 구글 로그인을 하게 되면 로그인한 이메일 주소와 이름, 사진, ID 토큰 값이 저장된다.




구글 로그인 api를 사용해 로그인이 잘 되는 것을 확인했다.






  1. 라이젠 2020.09.27 11:01

    안녕하세요 혹시 개발의뢰도 받으시나요? 안드로이드 폰에서 구글계정 무한생성 및 자동변경이 가능한 프로그램이 필요한데 가계정이든 실계정이든 구글서버에는 접속이 되고, 특정 어플 로그인만 가능한 계정이면 됩니다 이미 기존에 개발된 프로그램(파이썬)도 있는데, 서버에서 계정을 내려 받는 방식이구요 여기서 생성된 계정은 실제로 사용이 되진 않지만 구글계정이 필요한 특정 어플에서는 해당 구글계정으로 로그인이 됩니다.
    사례는 충분히 할테니 혹시 동일하게 개발이 가능하시면 https://open.kakao.com/o/sU6oEutc 여기로 연락 좀 꼭 부탁드릴게요~!

    • effortDev 2020.09.27 23:02 신고

      죄송합니다. 저는 개발의뢰를 받지 않습니다. 블로그 방문해주셔서 감사합니다.


공공데이터 포털의 오픈API 활용해 XML / JSON 형식의 데이터를 Jquery의 ajax를 활용하여 파싱해 데이터를 가져오는 작업을 해보겠습니다.


1. https://www.data.go.kr/ 접속 OPEN API 클릭



2.  저는 활용신청 건순이 가장 많은 국내 관광정보 서비스를 쓰려고 합니다.




3. 국내 관광정보 서비스 오픈 API를 신청하고 인증키를 받습니다. 


참고문서에 TourAPI_Guide.zip 파일을 다운받습니다.


zip 파일 안에는 API활용메뉴얼이 있고 자신이 필요한 데이터를 호출하면 됩니다.


저는 행사/공연/축제 에 대한 정보를 받아오려고 합니다.


형식의 http://api.visitkorea.or.kr/openapi/service/rest/KorService/searchFestival?ServiceKey=자신의키값&Request Parameter 항목명=값

형태로 요청하면 됩니다.

Request Parameter 에 필수 항목은 꼭 들어가야하는 파라미터항목입니다.







4. 자료실에 공유서비스 활용자 클라이언트 가이드 문서 등 여러 개발에 필요한 문서를 찾아 다운로드합니다.


5. 저는 웹서비스를 호출하는 방식으로 REST방식을 선택하겠습니다.


또한 서블릿과 자바스크립트를 이용해 XML과 JSON 형태의 데이터를 jquery의 ajax를 이용 파싱해 가져오려고 합니다.


6. 먼저 이클립스로 새 프로젝트 생성 후,  서블릿 파일 PublicData.java 생성, index.jsp 생성, 간단히 테스트 해보겠습니다.




7. index.jsp 안 스크립트 소스


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script>
 
      $.ajax({          
            url: 'PublicData.do',
            type: 'get',
            dataType: 'json',
            success: function(msg){
                console.log(msg.response.body.items.item);
                var myItem = msg.response.body.items.item;
                
                for(var i=0; myItem.length; i++){
                    var output = '';
                    console.log(myItem.length);
                    output += '<h3>'+ i + '번째 서울 축제 데이터' +'</h3>';
                    output += '<h4>'+myItem[i].addr1+'</h4>';
                    output += '<h4>'+myItem[i].title+'</h4>';
                    output += '<h4>'+myItem[i].tel+'</h4>';
                     document.body.innerHTML += output;
                }
            }
        });    
 
</script>
 
cs



8. PublicData.java 소스


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
package com;
 
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
 
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import org.apache.cxf.helpers.IOUtils;
import org.apache.cxf.io.CachedOutputStream;
import org.json.simple.JSONObject;
 
/**
 * Servlet implementation class test
 */
@WebServlet("/PublicData.do")
public class PublicData extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public PublicData() {
        super();
        // TODO Auto-generated constructor stub
    }
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        
        String addr = "http://api.visitkorea.or.kr/openapi/service/rest/KorService/searchFestival?ServiceKey=";
        String serviceKey = "자신의 키값 입력";
        String parameter = "";
//        serviceKey = URLEncoder.encode(serviceKey,"utf-8");
        PrintWriter out = response.getWriter();
        parameter = parameter + "&" + "areaCode=1";
        parameter = parameter + "&" + "eventStartDate=20170401";
        parameter = parameter + "&" + "eventEndDate=20171231";
        parameter = parameter + "&" + "pageNo=1&numOfRows=10";
        parameter = parameter + "&" + "MobileOS=ETC";
        parameter = parameter + "&" + "MobileApp=aa";
        parameter = parameter + "&" + "_type=json";
        
        
        addr = addr + serviceKey + parameter;
        URL url = new URL(addr);
        
        InputStream in = url.openStream(); 
        CachedOutputStream bos = new CachedOutputStream();
        IOUtils.copy(in, bos);
        in.close();
        bos.close();
        
//        out.println(addr);
        
        String data = bos.getOut().toString();        
        out.println(data);
        
        JSONObject json = new JSONObject();
        json.put("data", data);
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // TODO Auto-generated method stub
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html; charset=utf-8");
        
        String addr = "http://api.visitkorea.or.kr/openapi/service/rest/KorService/searchFestival?ServiceKey=";
        String serviceKey = "429e9l%2BRPBvvMYSqI0TIu0JgvFl1vio2dcUfXj7d66%2F%2B2glco1EDs1HDHJBssw9U7HAt1A11Cy6N0Hbk2INDfQ%3D%3D";
        String parameter = "";
//        serviceKey = URLEncoder.encode(serviceKey,"utf-8");
        PrintWriter out = response.getWriter();
        parameter = parameter + "&" + "areaCode=1";
        parameter = parameter + "&" + "eventStartDate=20170401";
        parameter = parameter + "&" + "eventEndDate=20171231";
        parameter = parameter + "&" + "pageNo=1&numOfRows=10";
        parameter = parameter + "&" + "MobileOS=ETC";
        parameter = parameter + "&" + "MobileApp=aa";
        parameter = parameter + "&" + "_type=json";
        
        
        addr = addr + serviceKey + parameter;
        URL url = new URL(addr);
        
        InputStream in = url.openStream(); 
        CachedOutputStream bos = new CachedOutputStream();
        IOUtils.copy(in, bos);
        in.close();
        bos.close();
        
//        out.println(addr);
        
        String data = bos.getOut().toString();        
        out.println(data);
        
        JSONObject json = new JSONObject();
        json.put("data", data);
        
    }
}
cs


서블릿인 PublicData.java 코드를 보면 요청할 api주소

http://api.visitkorea.or.kr/openapi/service/rest/KorService/searchFestival?

URI 다음에 발급받은 자신의 고유한 서비스 키값과 필요한 파라미터 값을 &로 붙여 주소를 만들고 있습니다. 



http://api.visitkorea.or.kr/openapi/service/rest/KorService/searchFestival?ServiceKey=키값&areaCode=1&eventStartDate=20170401&eventEndDate=20171231&pageNo=1&numOfRows=10 ... 생략


요청 파라미터값은 api doc에 자세히 나와있으니 자신이 필요한 요청값을 서비스키값 뒤로 적절히 붙여 요청하면 됩니다.



9. 요청한 주소를 브라우저를 통해 들어가면 xml형식 or json형식의 데이터 포맷으로 나타나게 됩니다.



10. 저는 20170401 ~ 20171231 까지 서울에서 실시하는 축제 정보의 주소, 제목, 전화번호의 키 밸류 형식의 JSON 데이터를 파싱해 가져온 결과입니다.




11. pom.xml 에서 받아온 메이븐 저장소파일 목록입니다.






12. 마지막으로 소스 추가합니다.


첨부파일 :


public_171213.zip


17년 12월 13일 기준으로 최신소스 등록하였습니다.

  1. 익명 2017.11.20 16:40

    비밀댓글입니다

    • effortDev 2017.12.13 15:18 신고

      tomcat 8.5 에 jdk8입니다.
      소스 확인해보니
      문제가 있는 것으로 확인되어 수정 한뒤 zip 파일 다시 올렸습니다. 감사합니다.

  2. 익명 2018.09.26 18:46

    비밀댓글입니다

    • effortDev 2018.09.29 19:56 신고

      부족한 블로그 방문해주셔서 정말 감사합니다. 항상 화이팅 하시구 모든 일 잘 되시길 바라겠습니다. 감사합니다.

  3. 익명 2019.02.19 10:03

    비밀댓글입니다

    • effortDev 2019.02.20 12:12 신고

      작성한 소스코드에 적용한 메이븐으로 부터 불러오는 라이브러리 파일이 어떤것인지 스크린샷 추가하여 올려놓았습니다. pom.xml 없이 추가하시려면 저 많은 파일들을 다운받아서 일일히 외부 라이브러리로 추가해주셔야 합니다. 감사합니다.

  4. 김태진 2020.07.01 19:04

    블로그 글 너무 잘봤습니다. 제가 빌드에 익숙하지 않은데 위에 pom.xml은 무슨 기능을 하는 건지 알 수 있을까요?

    • effortDev 2020.07.01 20:41 신고

      pom.xml은 maven을 사용할때 사용하는 xml입니다.
      maven은 프로젝트 빌드 툴 이구
      프로젝트 기본 정보, 빌드 설정, dependency 설정 등을 할수 있습니다.
      자세한 것은 pom.xml이나 maven에 대해 구글링하시면 될 것 같습니다.
      방문 해주셔서 감사합니다.

  5. 김태진 2020.07.01 22:03

    안녕하세요. 방금 댓글 남긴 사람인데 제가 메이븐도 바로 공부해서 실행하니 xml,json 를 출력하니 한글이 깨져서 그런데 tomcat도 utf-8로 세팅하고 response객체를 이용하여 utf-8로 setContentType까지 설정했습니다. 아 덧붙여 프로젝트 파일 전부 properties에서 utf-8로 바꿔줬는데 왜 한글이 깨지는 걸까요?ㅠㅠ 혹시 공공데이터 불러올때 한글 깨짐 관련 이슈를 해결해 보신 적 있으신가요?

    • 김태진 2020.07.01 22:04

      급하게 쓰느라 맞춤법이 좀 틀렸네요..

    • 김태진 2020.07.01 22:14

      이상하게 프로젝트를 다시 만드니까 제대로 되네요...이게 2년전 쯤 포스팅 같은데 정말 잘봤습니다. 깃허브 follow도 했습니다!!!

    • effortDev 2020.07.02 15:37 신고

      아 잘 되셨다니 다행이네요. 블로그 방문해주셔서 감사합니다.

  6. 닭붕어 2020.12.16 12:40

    형 사랑함 형아니엇음 교수님한테 암살당할뻔함

+ Recent posts