[작성자:] d_dive

  • Apache와 Nginx에서 SSL 파일 형식 통합하기

    Apache와 Nginx에서 SSL 파일 형식 통합하기

    apache와 nginx에서 쓰는 SSL 파일형식이 다름. 각각 만들어줘야 하지만, 통합해서 쓸 수 있는 방법이 있다.

    인증서와 체인 파일을 하나로 합친 파일을 생성하고, 이를 웹 서버에서 공통적으로 사용하도록 설정하면 된다.

    cat star_crt.pem ChainCA.crt RootCA.crt > fullchain.pem

    fullchain.pem 파일과 Private.key 파일을 웹 서버 설정

    apache 설정

    <VirtualHost *:443>
        ServerName example.com
    
        SSLEngine on
        SSLCertificateFile /path/to/fullchain.pem
        SSLCertificateKeyFile /path/to/Private.key
    </VirtualHost>

    nginx 설정

    server {
        listen 443 ssl;
        server_name example.com;
    
        ssl_certificate /path/to/fullchain.pem;
        ssl_certificate_key /path/to/Private.key;
    }

    ✅ AWS SSL 인증서 등록하기

    1. SSL 인증서(AWS 콘솔에서 “Certificate body”):

    star_newssalad_com_crt.pem 파일의 내용을 사용합니다. 이 파일은 기본 인증서 파일입니다.

    2. 중간 인증서 (AWS 콘솔에서 “Certificate chain”):

    ChainCA.crt와 RootCA.crt 파일을 결합한 내용을 사용해야 합니다. 이 두 파일을 합쳐서 중간 인증서로 등록하면 됩니다.

    cat ChainCA.crt RootCA.crt > certificate_chain.pem

    3. 개인 키 (AWS 콘솔에서 “Certificate private key”):

    Private.key 파일의 내용을 사용합니다.


    • Certificate body: star_newssalad_com_crt.pem의 내용
    • Certificate chain: certificate_chain.pem의 내용 (위에서 생성한 파일)
    • Certificate private key: Private.key의 내용

    암호화된 개인 키 복호화

    만약 .key 파일이 암호화되어 있다면, AWS에서는 복호화된 개인 키가 필요합니다. 개인 키가 암호화된 경우 openssl 명령을 사용해 암호를 제거할 수 있습니다.

    openssl rsa -in Private.key -out Private_unencrypted.key
  • NHN Cloud에서 인증서 설정하기

    NHN Cloud에서 인증서 설정하기

    📄 인증서 파일 결합 및 적용 방법

    지금 보유한 파일을 활용해 단일 .pem 파일을 생성하고 Certificate Manager에 적용하는 방법을 설명합니다.


    📂 파일 확인 및 준비

    | 파일명                         | 설명                               |
    |--------------------------------|----------------------------------|
    | star_example_com_crt.pem     | 메인 인증서 파일                  |
    | certificate_chain.pem          | 체인 인증서 파일 (Intermediate CA) |
    | ChainCA.crt                    | 대체 체인 인증서 파일             |
    | Private.key                    | 개인 키 파일                      |
    | Private_unencrypted.key        | 암호화되지 않은 개인 키 파일       |
    | RootCA.crt                     | 루트 인증서 파일 (선택 사항)       |

    📌 개인키 암호화 변경

    후이즈(whois) 에서 제공하는 개인키는 PKCS8 암호화로 되어 있어, 아래와 같이 RSA 암호화로 변경해야 한다.

    openssl rsa -des3 -in *.key -out *_pass.key

    생성한 RSA 암호화 개인키를 아래 명령어로 RSA 비암호화 개인키로 변환.

    openssl rsa -in *_pass.key -out *_nopass.key

    📌 NHN Cloud에 맞게 .pem 파일 제작

    • NHN에 외부인증서 등록시 들어가야하는 파일순서

    보안서버인증서 — 루트인증서 — 체인인증서 — 개인키

    (도메인명_crt.pem - RootCA.crt - ChainCA.crt - *.key)

    🚀 Certificate Manager에 적용

    1. 위에서 만든 bundle.pem파일을 Certificate Manager에 업로드합니다
    2. 업로드 후 정상적으로 적용되었는지 테스트
  • 최적화된 AWS MariaDB 성능 튜닝 전략

    최적화된 AWS MariaDB 성능 튜닝 전략

    AWS | mariaDB RDS 튜닝

    튜닝을 해야 하는 것만 기록했다.

    마리아 디비 [10.3.30 버전]

    파라미터현재 설정값개념
    character_set_clientutf8mb4클라이언트가 서버로 데이터를 보낼 때 사용하는 문자 인코딩 설정입니다.
    character_set_connectionutf8mb4클라이언트가 서버에 보낸 쿼리의 문자셋을 서버 내부에서 변환할 때 사용됩니다.
    character_set_databaseutf8mb4데이터베이스가 생성될 때 적용되는 기본 문자셋입니다.
    character_set_filesystemutf8mb4파일 시스템에서 사용하는 문자셋입니다.
    character_set_resultsutf8mb4서버가 클라이언트에 결과 데이터를 보낼 때 사용하는 문자셋입니다.
    character_set_serverutf8mb4서버의 기본 문자셋으로 새 데이터베이스나 테이블에 적용됩니다.
    collation_connectionutf8mb4_unicode_ci클라이언트와 서버 간 문자셋 비교 및 정렬 방법 설정입니다.
    collation_serverutf8mb4_unicode_ci서버의 기본 문자 비교 및 정렬 방법 설정입니다.
    event_schedulerONMySQL 이벤트 스케줄러를 활성화/비활성화하는 설정입니다.
    general_log0모든 쿼리를 기록하는 일반 로그 설정입니다.
    log_queries_not_using_indexes0인덱스를 사용하지 않는 쿼리를 기록하는 설정입니다.
    long_query_time2느린 쿼리 로그에 기록될 기준 시간을 초 단위로 설정합니다.
    slow_query_log0느린 쿼리를 기록하는 설정입니다.
    time_zoneAsia/Seoul데이터베이스 서버의 시간대(Time Zone)를 설정합니다.
    tx_isolationREAD-COMMITTED트랜잭션의 격리 수준 설정으로 일관성 있는 커밋된 데이터만 읽게 됩니다.
    lock_wait_timeout86400

    마리아 디비 [10.6.30 버전]

    파라미터현재 설정값설명
    character_set_clientutf8mb4클라이언트에서 사용하는 문자셋
    character_set_connectionutf8mb4연결 시 문자셋 변환에 사용되는 설정
    character_set_databaseutf8mb4데이터베이스의 기본 문자셋
    character_set_filesystemutf8mb4파일 시스템에서 사용하는 문자셋
    character_set_resultsutf8mb4서버가 결과를 반환할 때의 문자셋
    character_set_serverutf8mb4서버의 기본 문자셋
    collation_connectionutf8mb4_unicode_ci문자 정렬 및 비교 방법 설정
    collation_serverutf8mb4_unicode_ci서버의 기본 문자 정렬 및 비교 규칙
    log_bin_trust_function_creators1저장 함수 생성 시 권한 설정
    time_zoneAsia/Seoul서버의 시간대 설정
    tx_isolationREAD-COMMITTED트랜잭션의 격리 수준 설정으로 일관성 있는 커밋된 데이터만 읽게 됩니다
    lock_wait_timeout86400

    ✅ 공통사항 (확인해봐야 할 사항)

    SQL_BIG_SELECTS 튜닝

    SQL_BIG_SELECTS=1
    ---
    # NHN에서는
    max_join_size 값을 최대값으로 변경하면 SQL_BIG_SELECTS=1로 변경됨.

    📌 binlog 관련 튜닝(데이터베이스 이관 시, 지속적 복제 사용할 시)

    파라미터설명옵션*RDS 기본값
    binlog_format바이너리 로그의 형식`ROW`, `STATEMENT`, `MIXED`ROW
    log_bin바이너리 로그 활성화 여부`ON`, `OFF``ON` (고정)
    `log_bin_trust_function_creators`저장 함수 생성 시 권한 설정`0` (OFF), `1` (ON)`0`
    sync_binlog로그 동기화 빈도`0`, `1`, `1`1
    binlog_row_imageROW 포맷 이미지 범위`FULL`, `MINIMAL`, `NOBLOB`FULL
    max_binlog_size하나의 로그 파일 최대 크기숫자 (Bytes)1GB
    expire_logs_days바이너리 로그 보관 기간숫자(일), `0`7
    binlog_cache_size바이너리 로그 캐시 크기숫자 (Bytes)32KB
    binlog_checksum로그 무결성 체크섬 설정`NONE`, `CRC32`CRC32

    innoDB 메모리 관련 튜닝

    innodb_buffer_pool_size: {DBInstanceClassMemory*3/4}

    🛠️ mariaDB 메모리 관련 튜닝

    AWS 파라미터 기준.
    ----
    
    thread_stack: 262144
    net_buffer_length: 16384
    read_buffer_size: 262144
    sort_buffer_size: 2097152 -> 1048576
    join_buffer_size: 262144
    max_heap_table_size: 16777216
    tmp_table_size: 16777216
    binlog_cache_size: 32768
    read_rnd_buffer_size: 16777216(16MB)[변경 전] -> 524288(512KB)[변경 후]

    🛠️ max_connection 튜닝

    AWS 파라미터 기준.
    ----
    {DBInstanceClassMemory/12582880}
    
    nhn.
    ----
    ramSizeByte / 12582880

    🛠️ connection 튜닝

    바꾸려는 이유

    특정시간 DB가 클라이언트의 연결을 끊어버리는 현상이 일어남

    1. 파라미터 값 확인
    
    - net_read_timeout  : 서버가 클라이언트로부터 데이터를 읽어들이는 것을 중단하기까지 대기하는 시간
    - connect_timeout : 서버 접속시에 접속실패 메세지를 보내기까지 대기하는 시간
    - max_allowed_packet : 서버로 질의하거나 받게되는 패킷의 최대 길이
    
    ---
    net_read_timeout: 30 -> 60
    connect_timeout: 10 -> 30
    max_allowed_packet: 이미 최댓값. -> X
    
    으로 바꿔 봄.
    
    ---
    
    interactive_timeout 28800 => 7200 -> 3600
    wait_timeout 28800 => 7200 -> 3600

    🔖 MySQL 8.0.40 Version 추가 파라미터 튜닝

    sql_mode: 
    STRICT_TRANS_TABLES, NO_ZERO_IN_DATE, NO_ZERO_DATE, ERROR_FOR_DIVISION_BY_ZERO, NO_ENGINE_SUBSTITUTION

  • EC2 인스턴스 스토리지 확장 가이드

    EC2 인스턴스 스토리지 확장 가이드

    aws instance EC2의 스토리지를 확장하기 위해서는 따로 instance를 다운시키거나 할 필요가 없다.

    먼저 AWS 콘솔에서 내가 늘리고 싶은 스토리지를 볼륨 수정을 해준다.

    볼륨 수정이 되었다면, 서버에 접속해서 몇가지 작업을 해줘야 한다.

    lsblk
    
    ---
    NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
    xvda    202:0    0  20G  0 disk
    └─xvda1 202:1    0  10G  0 part /

    확장된 스토리지를 확인 한 후,

    • growpart로 파티션 크기 확장
    sudo growpart /dev/vda 1
    • 파일 시스템 크기 확장
    • ext4 파일 시스템:
    sudo resize2fs /dev/xvdf1
    • xfs 파일 시스템:
    sudo xfs_growfs /dev/xvdf1
    • 확장 확인
    df -h

    ✅ 파일 시스템 종류를 알아보려면..

    lsblk -f

    이렇게 치면 파일 시스템 종류가 나온다.

    📌 NHN Cloud 스토리지 확장하는 법

    growpart 명령어로 파티션 확장

    # Example.
    
    growpart 디바이스 이름 example -> /dev/vda 5

    참고 : growpart는 cloud-utils-growpart 패키지에 포함. 설치 필요할 수도 있음.

    yum install cloud-utils-growpart -y

    파일 시스템 확장

    # file system check
    lsblk -f
    
    # ext4 파일 시스템.
    
    resize2fs 디바이스 이름 example -> /dev/vda5
    
    # xfs 파일 시스템.
    
    xfs_growfs /

    변경 확인

    lsblk
    df -h
  • Streamlit을 이용한 관광지 데이터 분석

    Streamlit을 이용한 관광지 데이터 분석

    Streamlit share.

    streamlit share 사이트.

    URL: https://share.streamlit.


    프로젝트 명

    우리나라의 관광지 분석을 통한 신규 관광객 유입


    프로젝트 개요.

    1. 주제
    2. 주제 선정이유.
    3. 우리나라의 코로나19 방역 완화, 엔데믹과 원화 가치 급락 등의 이유로 외국인 관광객의 방한이 많아지고 있다. 우리나라의 관광지 분석을 통해 기존의 사람들이 잘 몰랐었던 숨어있는 관광지를 알려주고, 관광객이 줄어들고 있는 관광지는 새로운 마케팅을 통해 관광객을 끌어들일 수 있는 기회를 만듦.
    4. b. 장점 & 보완점
    5. 프로그램.
    6. 프로그램의 구성도
    7. 인기 TOP 10을 만들어서 해당 지역 주변의 편의시설 등을 알려주는 것을 만듦

    프로젝트 주요 내용 및 기능.

    • 관광지역의 관광객들의 유입 분석기능
    • 인기 많은 관광지역 주변의 편의시설 및 맛집 추천 기능
    • 현재 위치 기반으로 가까운 관광지 추천?

    개발 내용.

    💡 기준연월 2019.11~2022.10 데이터 날짜 기준

    1. 서울시 주요 관광지점 입장객 방문 수 분석
    [주요관광지점 입장객(2004.07 이후)_221203075929.xls](%25EC%25A3%25BC%25EC%259A%2594%25EA%25B4%2580%25EA%25B4%2591%25EC%25A7%2580%25EC%25A0%2590_%25EC%259E%2585%25EC%259E%25A5%25EA%25B0%259D(2004.07_%25EC%259D%25B4%25ED%259B%2584)_221203075929.xls)
    
    
    import numpy as np
    import pandas as pd
    
    visitors = pd.read_excel('../Users/chohyunjun/Downloads/visitor.xls', thousands=',')
    visitors
    visitors_total = visitors.loc[visitors['내/외국인'] == '합계']
    visitors_total = visitors_total.iloc[:,0:31]
    
    import googlemaps
    
    gmaps_key = "AIzaSyCpqSO-mFH36wjjiqUlQPJHhwYkLE9WWns"
    gmaps = googlemaps.Client(key = gmaps_key)
    
    visit_name = []
    
    for name in visitors_total['관광지']:
        visit_name.append('서울'+ str(name))
    
    visit_name
    
    visit_address = []
    visit_lat = []
    visit_lng = []
    
        print(name + '-->' + tmp[0].get("formatted_address"))
    
    visit_lat
    
    visit_lng
    
    visitors_total['lat'] = visit_lat
    visitors_total['lng'] = visit_lng
    
    visitors_total1 = pd.pivot_table(visitors_total, index = ['관광지'])
    
    import folium
    
    map = folium.Map(location=[37.5502, 126.982], zoom_start= 11)
    
    for n in visitors_total1.index:
        folium.Marker([visitors_total1['lat'][n],
                    visitors_total1['lng'][n]]).add_to(map)
    
    map

    streamlit

    import urllib.request
    import numpy as np
    import pandas as pd
    import plotly.express as px
    import requests
    import streamlit as st
    import xmltodict
    from pandas import json_normalize
    from streamlit_extras.add_vertical_space import add_vertical_space
    from streamlit_lottie import st_lottie
    import folium
    import googlemaps
    from streamlit_folium import st_folium
    from folium import plugins
    from folium.plugins import MarkerCluster
    from folium import Map, Popup, Marker, Icon, IFrame
    st.set_page_config(page_title="파이썬응용 데이터분석 기말 프로젝트", layout="wide")
    row0_spacer1, row0_1, row0_spacer2, row0_2, row0_spacer3 = st.columns(
        (0.1, 6, 0.2, 2, 0.1)
    )
    row0_1.title("파이썬응용 데이터분석 기말 프로젝트.")
    with row0_2:
        add_vertical_space()
        st.markdown("###### 2017E8129 통계데이터과학과 조현준")
    def visitor_area():
            st.subheader("방문자 거주지 분포.")
            st.markdown("###### 방문자 거주지 분포 시각화를 통해 경기도, 인천광역시, 강원도등 순으로 방문객 비율을 보이고 있다.")
            visitorArea = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/visitor_area.csv', encoding = 'CP949')
            fig3 = px.treemap(visitorArea, path = [px.Constant('대한민국'),'광역지자체명','기초지자체명'], values = '방문자 수(합)',
                                color = '방문자 수(합)',
                                color_continuous_scale = 'GnBu')
            fig3.update_layout(margin = dict(t=50, l=25, r=25, b=25))
            st.plotly_chart(fig3, theme = "streamlit", use_container_width = True)
    def visitor_seoul():
        line1_spacer1, line1_1, line1_spacer2 = st.columns((0.1, 3.2, 0.1))
        with line1_1:
            st.header("Analysis of Seoul Data.")
            st.markdown("###### 서울은 대한민국의 수도이자 많은 관광객들이 몰려 있는 곳이다. 한국을 찾는 많은 관광객들이 주로 서울을 방문하는 경우들이 많다. 서울관광지 Top10 데이터를 분석하여 관광지를 추천해주고자 한다.") 
        row3_space1, row3_1, row3_space2, row3_2, row3_space3 = st.columns(
            (0.1, 1, 0.1, 1, 0.1)
        )
        with row3_1:
            st.subheader("서울 방문자 수")
            st.markdown("###### 코로나19 유행 기간 서울 방문자 수가 급격히 줄어 들었지만, 거리두기가 풀린 뒤 서울 방문객들이 점차 증가하는 추세를 보이고 있다.")
            visitorData = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/visitorData_seoul.csv', encoding='CP949')
            visitorData.columns = ["기준연월","지역명","방문자 수"]
            fig = px.line(
                visitorData,
                x = '기준연월',
                y = '방문자 수',
                color_discrete_sequence = ["lightgoldenrodyellow"]
            )
            st.plotly_chart(fig, theme = "streamlit", use_container_width = True)
        with row3_2:
            visitor_area()      
    visitor_seoul()
    def inflow_ouflow_chart():
        row4_spacer1, row4_1, row4_spacer2 = st.columns((0.1, 5, 0.1))
        with row4_1:
            st.subheader("유입 유출 분석")
            st.markdown("###### 서울의 유입 유출 방문객의 분석을 통해 첫 번째로 많이 나타는 경기도 유입은 86.9% ,유출은 85.5%, 두 번째는 인천광역시 유입9.9% ,유출8.2%, 세 번째는 강원도 유입1.1% ,유출3.7%를 나타내고 있음.")
            flowData = pd.read_csv("https://raw.githubusercontent.com/CHJun47/Data/main/inflow_outflow.csv", encoding = 'CP949')
            fig1 = px.parallel_categories(
                flowData,
                color = "유입 비율",
                color_continuous_scale = "GnBu"
                )
            st.plotly_chart(fig1, theme = "streamlit", use_container_width = True)
    inflow_ouflow_chart()
    def touristDest():
        row5_space1, row5_1, row5_space2, row5_2, row5_space3 = st.columns(
            (0.1, 1, 0.1, 1, 0.1)
        )
        with row5_1:
            st.subheader("관광소비 유형.")
            st.markdown("###### 관광소비 유형으로 1위가 식음료이다. 음식은 그 나라의 문화와 전통을 가장 잘 나타낼 수 있는 관광 자원이다.") 
            st.markdown("###### 한 지역을 대표하는 음식은 때로는 그 자체만으로도 여행의 목적이 되기도 한다.")
            st.markdown("###### 2위로 쇼핑업을 볼 수 있다. 유행하는 옷이나 우리나라를 대표하는 한복을 입고 문화를 즐기고 향유하려는 것을 볼 수 있다.")
            st.markdown("###### 나머지는 운송업, 숙박업, 여가서비스등을 볼 수 있다.")
            tourrist_dest = pd.read_csv("https://raw.githubusercontent.com/CHJun47/Data/main/tourrist_dest.csv", encoding='CP949')
            fig4 = px.treemap(tourrist_dest, path = [px.Constant('점포'),'업종대분류명','업종중분류명'], values = '중분류 소비액(합)',
                                color = '중분류 소비액(합)',
                                color_continuous_scale = "GnBu")
            fig4.update_layout(margin = dict(t=50, l=25, r=25, b=25))
            st.plotly_chart(fig4, theme = "streamlit", use_container_width = True)
        with row5_2:
            st.subheader("SNS언급량.")
            st.markdown("###### 코로나19 거리두기로 여행이나 놀러갈 수 없는 상황이였지만,")
            st.markdown("###### 거리두기가 풀리고 나서부터 SNS에서도 여행, 놀러가는 사진을 SNS에서의 언급량이 점점 증가하고있다.")
            st.markdown("###### ")
            seoul_SNS = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/seoul_SNS.csv', encoding = 'CP949')
            fig5 = px.bar(
                seoul_SNS,
                x = '기준연월',
                y = '검색량(건)',
                color_discrete_sequence = ["lightgoldenrodyellow"]
            )
            st.plotly_chart(fig5, theme = "streamlit", use_container_width = True)
    touristDest()
    def Folium_visit():
        row6_spacer1, row6_1, row6_spacer2, row6_2, row_spacer3 = st.columns((0.1, 30, 0.1,5,0.1))
        with row6_1:
            gmaps_key = "AIzaSyCpqSO-mFH36wjjiqUlQPJHhwYkLE9WWns"
            gmaps = googlemaps.Client(key = gmaps_key)
            visitors = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/visitor(2).csv', encoding='CP949')
            visitors_total = visitors.loc[visitors['내/외국인'] == '합계']
            visitors_total = visitors_total.iloc[:,0:31]
            visit_name = []
            visit_url = []
            for name in visitors.iloc[:,-1]:
                visit_url.append(name)
            
            for name in visitors_total['관광지']:
                visit_name.append('서울'+ str(name))
            visit_address = []
            visit_lat = []
            visit_lng = []
            for name in visit_name:
                tmp = gmaps.geocode(name, language='ko')
                tmp_loc = tmp[0].get("geometry")
                visit_lat.append(tmp_loc['location']['lat'])
                visit_lng.append(tmp_loc['location']['lng'])
            # food.
            food = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/food(1).csv')
            food_address = []
            food_lat = []
            food_lng = []
            food_name = []
            food_info = []
            food1_info = []
            food2_info = []
            food3_info = []
            food4_info = []
            food5_info = []
            food6_info = []
            food1_name = []
            food2_name = []
            food3_name = []
            food4_name = []
            food5_name = []
            food6_name = []
            for name in food.iloc[:,1]:
                food_name.append(name)
            for add in food.iloc[:,2]:
                food_address.append(str('서울')+add)
            for name in food_address:
                tmp = gmaps.geocode(name, language='ko')
                tmp_loc = tmp[0].get("geometry")
                food_lat.append((tmp_loc['location']['lat']))
                food_lng.append(tmp_loc['location']['lng'])
            food['lat'] = food_lat
            food['lng'] = food_lng
            food1 = food[food['분류'] == '음식점기타']
            for name in food1.iloc[:,5]:
                food1_info.append(name)
            food2 = food[food['분류'] == '한식']
            for name in food2.iloc[:,5]:
                food2_info.append(name)
            food3 = food[food['분류'] == '카페/찻집']
            for name in food3.iloc[:,5]:
                food3_info.append(name)
            food4 = food[food['분류'] == '간이음식']
            for name in food4.iloc[:,5]:
                food4_info.append(name)
            food5 = food[food['분류'] == '전문음식']
            for name in food5.iloc[:,5]:
                food5_info.append(name)
            food6 = food[food['분류'] == '외국식']
            for name in food6.iloc[:,5]:
                food6_info.append(name)
            for name in food1.iloc[:,1]:
                food1_name.append(name)
            for name in food2.iloc[:,1]:
                food2_name.append(name)
            for name in food3.iloc[:,1]:
                food3_name.append(name)
            for name in food4.iloc[:,1]:
                food4_name.append(name)
            for name in food5.iloc[:,1]:
                food5_name.append(name)
            for name in food6.iloc[:,1]:
                food6_name.append(name)
            food1 = pd.pivot_table(food1, index = ['주소'])
            food2 = pd.pivot_table(food2, index = ['주소'])
            food3 = pd.pivot_table(food3, index = ['주소'])
            food4 = pd.pivot_table(food4, index = ['주소'])
            food5 = pd.pivot_table(food5, index = ['주소'])
            food6 = pd.pivot_table(food6, index = ['주소'])
            visitors_total['lat'] = visit_lat
            visitors_total['lng'] = visit_lng
            visitors_total1 = pd.pivot_table(visitors_total, index = ['관광지'])
            map = folium.Map(location=[37.566535, 126.9779692],
            tiles = "stamen Terrain",
            zoom_start= 11)
            marker_cluster = MarkerCluster().add_to(map)
            ######################### 수정.
            if st.checkbox('관광지'):
                for n in range(int(len(visitors_total1))):
                    folium.Marker([visitors_total1['lat'][n],
                    visitors_total1['lng'][n]],tooltip = '"'+visit_name[n]+'"').add_to(marker_cluster)
            elif st.checkbox('음식점기타'):
                for n1 in range(int(len(food1))):
                    folium.Marker([food1['lat'][n1],
                    food1['lng'][n1]],popup = "<a href="+'"'+food1_info[n1]+'"'+"target ="+"_blank"+">Site</a>",tooltip = '"'+food1_name[n1]+'"',icon = folium.Icon(icon = 'star', color = 'red')).add_to(marker_cluster)
            elif st.checkbox('한식'):
                for n2 in range(int(len(food2))):
                    folium.Marker([food2['lat'][n2],
                    food2['lng'][n2]],popup = "<a href="+'"'+food2_info[n2]+'"'+"target ="+"_blank"+">Site</a>",tooltip = '"'+food2_name[n2]+'"',icon = folium.Icon(icon = 'star', color = 'yellow')).add_to(marker_cluster)
            elif st.checkbox('카페/찻집'):
                for n3 in range(int(len(food3))):
                    folium.Marker([food3['lat'][n3],
                    food3['lng'][n3]],popup = "<a href="+'"'+food3_info[n3]+'"'+"target ="+"_blank"+">Site</a>",tooltip = '"'+food3_name[n3]+'"',icon = folium.Icon(icon = 'star', color = 'green')).add_to(marker_cluster)
            elif st.checkbox('간이음식'):
                for n4 in range(int(len(food4))):
                    folium.Marker([food4['lat'][n4],
                    food4['lng'][n4]],popup = "<a href="+'"'+food4_info[n4]+'"'+"target ="+"_blank"+">Site</a>",tooltip = '"'+food4_name[n4]+'"',icon = folium.Icon(icon = 'star', color = 'orange')).add_to(marker_cluster)
            elif st.checkbox('전문음식'):
                for n5 in range(int(len(food5))):
                    folium.Marker([food5['lat'][n5],
                    food5['lng'][n5]],popup = "<a href="+'"'+food5_info[n5]+'"'+"target ="+"_blank"+">Site</a>",tooltip = '"'+food5_name[n5]+'"',icon = folium.Icon(icon = 'star', color = 'lightgray')).add_to(marker_cluster)
            elif st.checkbox('외국식'):
                for n6 in range(int(len(food6))):
                    folium.Marker([food6['lat'][n6],
                    food6['lng'][n6]],popup = "<a href="+'"'+food6_info[n6]+'"'+"target ="+"_blank"+">Site</a>",tooltip = '"'+food6_name[n6]+'"',icon = folium.Icon(icon = 'star', color = 'lightcyan')).add_to(marker_cluster)
            
            return map
    st.subheader("주변 Search 지도.")
    m = Folium_visit()
    output = st_folium(m, key = "map", width = 1800, height = 600)

    folium

    import folium
    
    m=folium.Map(location=[37.55092, 127.0377],zoom_start=11)
    m.add_child(folium.LatLngPopup()) 
    #Tpo10 우리나라 관광지추천
    #경복궁iframe으로 사진 띄우기-사진 경로지정해야함 
    pic1 = base64.b64encode(open('C:/Users/김나영/Desktop/Gbg.jpg','rb').read()).decode()
    image_tag1 = '<img src="data:image/jpeg;base64,{}">'.format(pic1)
    iframe1 = folium.IFrame(image_tag1, width=500, height=500)
    popup1 = folium.Popup(iframe1, max_width=650)
    # 1.경복궁
    folium.Marker([37.579617, 126.977041], # 마커 찍고싶은 좌표를 구해와서 원본 m에다 표시/추가
                popup=popup1, # popup: 마커 클릭시 팝업으로 상세내용 표시되는 옵션 추가
                tooltip='<i>경복궁</i>').add_to(m)# tooltip: 마우스오버시 상세내용 표시
    #창경궁iframe으로 사진 띄우기
    pic2 = base64.b64encode(open('C:/Users/김나영/Desktop/Cgg.jpg','rb').read()).decode()
    image_tag2 = '<img src="data:image/jpeg;base64,{}">'.format(pic2)
    iframe2 = folium.IFrame(image_tag2, width=500, height=500)
    popup2 = folium.Popup(iframe2, max_width=650)          
    # 2.창경궁
    folium.Marker([37.5787708, 126.9948698],
                popup=popup2,
                tooltip='<i>창경궁</i>').add_to(m)              
    #창덕궁iframe으로 사진 띄우기
    pic3 = base64.b64encode(open('C:/Users/김나영/Desktop/Cdg.jpg','rb').read()).decode()
    image_tag3 = '<img src="data:image/jpeg;base64,{}">'.format(pic3)
    iframe3 = folium.IFrame(image_tag3, width=500, height=500)
    popup3 = folium.Popup(iframe3, max_width=650)
    # 3.창덕궁
    folium.Marker([37.5794309, 126.9910426],
                popup=popup3,
                tooltip='<i>창덕궁</i>').add_to(m)
    #덕수궁iframe으로 사진 띄우기
    pic4 = base64.b64encode(open('C:/Users/김나영/Desktop/Dsg.jpg','rb').read()).decode()
    image_tag4 = '<img src="data:image/jpeg;base64,{}">'.format(pic4)
    iframe4 = folium.IFrame(image_tag4, width=500, height=500)
    popup4 = folium.Popup(iframe4, max_width=650)
    #4.덕수궁
    folium.Marker([37.5658049, 126.9751461],
                popup=popup4,
                tooltip='<i>덕수궁</i>').add_to(m)
    #경희궁iframe으로 사진 띄우기
    pic5 = base64.b64encode(open('C:/Users/김나영/Desktop/Ghg.jpg','rb').read()).decode()
    image_tag5 = '<img src="data:image/jpeg;base64,{}">'.format(pic5)
    iframe5 = folium.IFrame(image_tag5, width=500, height=500)
    popup5 = folium.Popup(iframe5, max_width=650)
    #5.경희궁
    folium.Marker([37.5712378, 126.9681688],
                popup=popup5,
                tooltip='<i>경희궁</i>').add_to(m)
    #세종대왕기념관iframe으로 사진 띄우기
    pic6 = base64.b64encode(open('C:/Users/김나영/Desktop/King.jpg','rb').read()).decode()
    image_tag6 = '<img src="data:image/jpeg;base64,{}">'.format(pic6)
    iframe6 = folium.IFrame(image_tag6, width=500, height=500)
    popup6 = folium.Popup(iframe6, max_width=650)
    #6.세종대왕기념관
    folium.Marker([37.590783, 127.0435458],
                popup=popup6,
                tooltip='<i>세종대왕기념관</i>').add_to(m)
    #서울스카이iframe으로 사진 띄우기
    pic7 = base64.b64encode(open('C:/Users/김나영/Desktop/Sky.png','rb').read()).decode()
    image_tag7 = '<img src="data:image/jpeg;base64,{}">'.format(pic7)
    iframe7 = folium.IFrame(image_tag7, width=500, height=500)
    popup7 = folium.Popup(iframe7, max_width=650)
    #7.서울스카이
    folium.Marker([37.5136918, 127.1037211],
                popup=popup7,
                tooltip='<i>남산타워</i>').add_to(m)
    #롯데월드iframe으로 사진 띄우기
    pic8 = base64.b64encode(open('C:/Users/김나영/Desktop/Lotte.jpg','rb').read()).decode()
    image_tag8 = '<img src="data:image/jpeg;base64,{}">'.format(pic8)
    iframe8 = folium.IFrame(image_tag8, width=500, height=500)
    popup8 = folium.Popup(iframe8, max_width=650)
    #8.롯데월드
    folium.Marker([37.5111158, 127.098167],
                popup=popup8,
                tooltip='<i>롯데월드</i>').add_to(m)
                  
    #서울시립미술관iframe으로 사진 띄우기
    pic9 = base64.b64encode(open('C:/Users/김나영/Desktop/SMA.jpg','rb').read()).decode()
    image_tag9 = '<img src="data:image/jpeg;base64,{}">'.format(pic9)
    iframe9 = folium.IFrame(image_tag9, width=500, height=500)
    popup9 = folium.Popup(iframe9, max_width=650)
    #9.서울시립미술관
    folium.Marker([37.5640625, 126.9738125],
                popup=popup9,
                tooltip='<i>서울시립미술관</i>').add_to(m)
                  
    #국립중앙박물관iframe으로 사진 띄우기
    pic10 = base64.b64encode(open('C:/Users/김나영/Desktop/NMK.jpg','rb').read()).decode()
    image_tag10 = '<img src="data:image/jpeg;base64,{}">'.format(pic10)
    iframe10 = folium.IFrame(image_tag10, width=500, height=500)
    popup10 = folium.Popup(iframe10, max_width=650)
    #10.국립중앙박물관
    folium.Marker([37.5238506, 126.9804702],
                popup=popup10,
                tooltip='<i>국립중앙박물관</i>').add_to(m

    streamlit →folium지도

    import urllib.request
    import numpy as np
    import pandas as pd
    import plotly.express as px
    import requests
    import streamlit as st
    from streamlit_folium import st_folium
    from folium.plugins import MarkerCluster
    import folium
    import xmltodict
    import base64
    from pandas import json_normalize
    from streamlit_extras.add_vertical_space import add_vertical_space
    from streamlit_lottie import st_lottie
    st.set_page_config(page_title="파이썬응용 데이터분석 기말 프로젝트", layout="wide")
    row0_spacer1, row0_1, row0_spacer2, row0_2, row0_spacer3 = st.columns(
        (0.1, 6, 0.2, 2, 0.1)
    )
    row0_1.title("파이썬응용 데이터분석 기말 프로젝트.")
    with row0_2:
        add_vertical_space()
        st.markdown("###### 2017E8129 통계데이터과학과 조현준")
    def visitor_area():
            st.subheader("방문자 거주지 분포.")
            visitorArea = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/visitor_area.csv', encoding = 'CP949')
            fig3 = px.treemap(visitorArea, path = [px.Constant('대한민국'),'광역지자체명','기초지자체명'], values = '방문자 수(합)',
                                color = '방문자 수(합)',
                                color_continuous_scale = 'GnBu')
            fig3.update_layout(margin = dict(t=50, l=25, r=25, b=25))
            st.plotly_chart(fig3, theme = "streamlit", use_container_width = True)
    def visitor_seoul():
        line1_spacer1, line1_1, line1_spacer2 = st.columns((0.1, 3.2, 0.1))
        with line1_1:
            st.header("Analysis of Seoul Data.")
        row3_space1, row3_1, row3_space2, row3_2, row3_space3 = st.columns(
            (0.1, 1, 0.1, 1, 0.1)
        )
        with row3_1:
            st.subheader("서울 방문자 수")
            visitorData = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/visitorData_seoul.csv', encoding='CP949')
            visitorData.columns = ["기준연월","지역명","방문자 수"]
            fig = px.line(
                visitorData,
                x = '기준연월',
                y = '방문자 수',
                color_discrete_sequence = ["lightgoldenrodyellow"]
            )
            st.plotly_chart(fig, theme = "streamlit", use_container_width = True)
        with row3_2:
            visitor_area()
    visitor_seoul()
    def inflow_ouflow_chart():
        row4_spacer1, row4_1, row4_spacer2 = st.columns((0.1, 5, 0.1))
        with row4_1:
            st.subheader("유입 유출 분석")
            flowData = pd.read_csv("https://raw.githubusercontent.com/CHJun47/Data/main/inflow_outflow.csv", encoding = 'CP949')
            fig1 = px.parallel_categories(
                flowData,
                color = "유입 비율",
                color_continuous_scale = "GnBu"
                )
            st.plotly_chart(fig1, theme = "streamlit", use_container_width = True)
    inflow_ouflow_chart()
    def touristDest():
        row5_space1, row5_1, row5_space2, row5_2, row5_space3 = st.columns(
            (0.1, 1, 0.1, 1, 0.1)
        )
        with row5_1:
            st.subheader("관광소비 유형.")
            tourrist_dest = pd.read_csv("https://raw.githubusercontent.com/CHJun47/Data/main/tourrist_dest.csv", encoding='CP949')
            fig4 = px.treemap(tourrist_dest, path = [px.Constant('점포'),'업종대분류명','업종중분류명'], values = '중분류 소비액(합)',
                                color = '중분류 소비액(합)',
                                color_continuous_scale = "GnBu")
            fig4.update_layout(margin = dict(t=50, l=25, r=25, b=25))
            st.plotly_chart(fig4, theme = "streamlit", use_container_width = True)
        with row5_2:
            st.subheader("SNS언급량.")
            seoul_SNS = pd.read_csv('https://raw.githubusercontent.com/CHJun47/Data/main/seoul_SNS.csv', encoding = 'CP949')
            fig5 = px.bar(
                seoul_SNS,
                x = '기준연월',
                y = '검색량(건)',
                color_discrete_sequence = ["lightgoldenrodyellow"]
            )
            st.plotly_chart(fig5, theme = "streamlit", use_container_width = True)
    touristDest()
    def draw_folium_map():
        center = [39.5, -98.5]
        tiles = ["cartodbpositron", "Stamen Toner", "OpenStreetMap"]
        map = folium.Map(
            location=[center[0], center[1]],
            zoom_start=10,
            zoom_control=True,
            scrollWheelZoom=False,
            tiles=tiles[0],
        )
        folium.Marker(
            location=[39.5, -98.5],
            popup=f"A location!",
            icon=folium.Icon(color="blue", icon="star"),
        ).add_to(map)
        return map
    m = draw_folium_map()
    output = st_folium(m, key="map", width=650, height=600)
    st.write(output)

    CircleMarker — popup

    import pandas as pd
    import folium
    from folium.plugins import FastMarkerCluster
    file_url = 'http://www2.census.gov/geo/docs/maps-data/data/gazetteer/2016_Gazetteer/2016_Gaz_zcta_national.zip'
    #Pandas usually infers zips are numerics, but we lose our leading zeroes so let's go with the object dtype
    df = pd.read_csv(file_url, sep='\t', dtype={'GEOID' : object}) 
    df.columns = df.columns.str.strip() #some column names have some padding
    df = df.sample(1000)
    folium_map = folium.Map(location=[38, -97],
                            zoom_start=4.4,
                            tiles='CartoDB dark_matter')
    # These two lines should create FastMarkerClusters
    FastMarkerCluster(data=list(zip(df['INTPTLAT'].values, df['INTPTLONG'].values))).add_to(folium_map)
    folium.LayerControl().add_to(folium_map)
    for index, row in df.iterrows():
        # generate the popup message that is shown on click.
        popup_text = "{}<br> ALAND: {:,}<br> AWATER: {:,}"
        popup_text = popup_text.format(
                          index,
                          row["ALAND_SQMI"],
                          row["AWATER_SQMI"]
                          )
        folium.CircleMarker(location=(row["INTPTLAT"],
                                      row["INTPTLONG"]),
                            radius= row['ALAND_SQMI']/100,
                            color="#007849",
                            popup=popup_text,
                            fill=False).add_to(folium_map)
    folium_map
  • 회귀분석과 KNN: 패키지부터 모형화까지

    회귀분석과 KNN: 패키지부터 모형화까지

    회귀분석

    flowchart TD
    
    A['1단계 패키지 설정'] --> B['2단계 데이터 준비'] --> C['3단계 탐색적 데이터분석'] --> D['4단계 피처 스케일링'] --> E['5단계 모형화 및 학습'] --> F['6단계 예측']
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn.preprocessing import StandardScaler
    import numpy as np
    import matplotlib.pyplot as plt
    # 학습용 데이터
    # 입력.
    X_train = np.array([[25, 25],
            [33, 30],
            [38, 30],
            [45, 35],
            [28, 40]])
    # 라벨.
    y_train = np.array([0,0,1,1,0])
    # 테스트용 데이터(새로운 개체)
    X_test = np.array([[30, 35]]) # 새로운 개체의 X1, X2
    # 산포도.
    # 학습용 데이터.
    plt.scatter(X_train[:,0], X_train[:,1], c = y_train)
    # 테스트용 데이터.
    plt.scatter(X_test[:,0], X_test[:,1], c = 'red', marker = 'D', s = 100)
    plt.xlabel('x1')
    plt.ylabel('x2')
    plt.show()
    # 피처 스케일링: 학습용 데이터.
    scalerX = StandardScaler()
    scalerX.fit(X_train)
    X_train_std = scalerX.transform(X_train)
    print(X_train_std)
    # 피처 스케일링 : 테스트용 데이터.
    
    X_test_std = scalerX.transform(X_test)
    print(X_test_std)
    # 모형화.
    knn = KNeighborsClassifier(n_neighbors=3, metric='euclidean')
    # 학습.
    knn.fit(X_train_std, y_train)
    # 에측.
    pred = knn.predict(X_test_std)
    print(pred)
    #클래스별 확률 값을 반환.
    knn.predict_proba(X_test_std)
    # 인접한 k개의 개체들에 대한 거리와 색인을 반환.
    dist,index = knn.kneighbors(X_test_std)
    print(dist)
    print(index)

    KNN(k-Nearest Neighbor Classifier)

    K-NN의 꽃잎 분류에의 적용 예.

    • 꽃잎의 크기와 밝기에 따른 K-NN 분류.
    • 오른쪽 위에 새로운 꽃잎이 입력으로 들어왔을 때 빨간 화살표의 3가지를 비교한 후 분류하는 것을 보여줌.

    K-NN의 장단점과 활용 분야.

    • 장점은 매우 간단하며 빠르고 효과적인 알고리즘 또 어떤 데이터라도 유사성 측정 가능.
    • 단점으로는 적절한 k를 선택해야 한다는 점 새로운 데이터에 대해 일일이 거리를 계산한 후 분류.

    K-NN의 활용 분야.

    • 영화나 음악 추천에 대한 개인별 선호 예측.
    • 수표에 적힌 광학 숫자와 글자인식.
    • 얼굴인식과 같은 컴퓨터 비전.
    • 유방암 등 질병의 진단과 유전자 데이터 인식.
    • 재정적인 위험성의 파악과 관리, 주식 시장 예측.
    # 새로운 값을 분류할 때 .predict() 사용.
    unknown_points = [
        [0.2,0.1,0.7],
        [0.4,0.7,0.6],
        [0.5,0.8,0.1]
    ]
    guesses = classifier.predict(unknown_points)
    print(guesses)

    sklearn을 이용한 kNN 알고리즘 실습

    from sklearn.datasets import load_iris
    iris = load_iris()
    print(iris.data)
    # 4개의 특징 이름을 출력.
    print(iris.feature_names)
    # 정수는 꽃의 종류를 나타낸다.: 0 = setosa, 1 = versicolor, 2 = virginica
    print(iris.target)
    from sklearn.model_selection import train_test_split
    X = iris.data
    y = iris.target
    # (80:20)으로 분할.
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state=4)
    print(X_train.shape)
    print(X_test.shape)
    from sklearn.neighbors import KNeighborsClassifier
    from sklearn import metrics
    knn = KNeighborsClassifier(n_neighbors=6)
    knn.fit(X_train, y_train)
    y_pred = knn.predict(X_test)
    scores = metrics.accuracy_score(y_test, y_pred)
    #0 = setosa, 1 = versicolor, 2 = virginca
    classes = {0:'setosa', 1:'versicolor', 2:'virginca'}
    # 아직 보지 못한 새로운 데이터를 제시해보자.
    
    x_new = [[3,4,5,2],
            [5,4,2,2]]
    y_predict = knn.predict(x_new)
    print(classes[y_predict[0]])
    print(classes[y_predict[1]])

    나이브 베이지 분류 예제 살펴보기

    나이브 베이즈의 정리

    💡 P(A)가 A가 일어날 확률, P(B)가 B가 일어날 확률, P(B|A)가 A가 일어나고나서 B가 일어날 확률, P(A|B)가 B가 일어나고나서 A가 일어날 확률이라고 해봅시다. 이때 P(B|A) 를 쉽게 구할 수 있는 상황이라면, 아래와 같은 식을 통해 P(A|B)를 구할 수 있습니다.

    P(AB)=P(BA)P(A)/P(B)

    K-NN

    • sklearn에서 제공하는 예시 데이터 중 유방암 데이터를 사용해 KNN 모델을 적용.
    1. KNeighborsClassifier(n_neighbos = K)에서 K를 1부터 100까지 변화시켜서 테스트 해보기.
    2. 가장 정확도가 큰 K는 얼마인지 알아보기.
  • 기업별 개인 비서 소개 및 특징

    기업별 개인 비서 소개 및 특징

    기업별 개인 비서 리스트

    ⇒ 애플 → 시리

    ⇒ 구글 → 구글 어시스턴트, 구글 나우

    ⇒ 마이크로소프트 → 코타나

    ⇒ 아마존 → 알렉사(에코)

    ⇒ 페이스북 → M.(2018년 1월 중단.)

    ⇒ 삼성 → 빅스비

    ⇒ LG →. Q보이스

    ⇒ KT → KT 비서

    intelligent agent(혹은 개인 비서)란?

    에이전트는 특정한 목적을 위해 사용자를 대신해서 작업을 수행하는 자율적 프로세스. 에이전트는 독자적으로 존재하지 않고 어떤 환경의 일부이거나 그 안에서 동작하는 시스템. 여기서의 환경은 운영 체제, 네트워크 등을 지칭함. 에이전트는 지식베이스와 추론 기능을 가지며 사용자, 자원(resource), 또는 다른 에이전트와의 정보교환과 통신을 통해 문제해결을 도모함. 에이전트는 스스로 환경의 변화를 인지하고 그에 대응하는 행동을 취하며, 경험을 바탕으로 학습하는 기능을 가짐. 에이전트는 수동적으로 주어진 작업만을 수행하는 것이 아니고, 자신의 목적을 가지고 그 목적 달성을 추구하는 능동적 자세를 지님. 에이전트의 행동의 결과로 환경의 변화를 가져올 수 있다. 에이전트의 행동은 한번에 끝나는 것이 아니라 지속적으로 이루어짐.

    성질

    • 자율성.

    에이전트는 사람이나 다른 사물의 직접적인 간섭 없이 스스로 판단하여 동작하고, 그들의 행동이나 내부 상태에 대한 어떤 종류의 제어를 갖음.

    • 사회성.

    에이전트는 에이전트 통신 언어를 사용하여 사람과 다른 에이전트들과 상호작용할 수 있음.

    • 반응성.

    에이전트는 실세계, 그래픽사용자 인터페이스를 경유한 사용자, 다른 에이전트들의 집합, 인터넷 같은 환경을 인지하고 그 안에서 일어나는 변화에 시간상 적절히 반응함.

    • 능동성.

    에이전트는 단순히 환경에 반응하여 행동하는 것이 아니라 주도권을 가지고 목표 지향적으로 행동함.

    • 시간연속성.

    에이전트는 단순히 한번 주어진 입력을 처리하여 결과를 보여주고 종료하는 것이 아니라, 전면에서 실행하고 이면에서 잠시 휴식하는 연속적으로 수행하는 데몬(demon)같은 프로세스.

    • 목표지향성.

    에이전트는 복잡한 고수준 작업들을 수행한다. 작업이 더 작은 세부 작업으로 나뉘고 처리순서가 결정되어 처리되는 등의 책임을 에이전트가 진다.

    속성

    • 이동성.

    사용자가 요구한 작업을 현재의 컴퓨터에서 처리하지 않고 그 작업을 처리할 수 있는 다른 컴퓨터로 이동시켜 수행함으로써 효율을 높이고 네트워크 부하를 감소.

    • 합리성.

    에이전트가 목표를 달성하기 위해 행동하지 목표 달성을 방해하는 방향으로는 행동하지 않는다.

    • 적응성.

    에이전트는 사용자의 습관과 작업 방식 그리고 취향에 따라 스스로를 적응시킬 수 있다.

    • 협동성.

    에이전트는 다른 에이전트, 자원, 사람과도 복잡한 작업을 수행하기 위해 협력할 수 있다.

    분류

    • 학습에이전트.

    학습 에이전트(learning agent)는 사용자가 웹상에서의 수행하는 행동을 관찰하고 어떤 내용에 관심을 가지고 있는지 판단하여 사용자에게 알맞은 내용을 전달하도록 하는 것을 말함.

    • 인터페이스 에이전트.

    현존하는 많은 컴퓨터 프로그램과 인터페이스는 명백하게 인간의 재능과 흥미를 표현하지만 인간과 컴퓨터 사이에는 아직도 대화능력이 부족하다. 사용자 인터페이스 에이전트(user interface agent)는 사용자의 원하는 작업을 찾아내서 이들을 네트워크나 응용 프로그램안 어디에서든지 실행할 수 있도록 이동시켜 준다. 사용자 인터페이스는 응용 프로그램의 성공에 있어 매우 중요하다. 이것은 사용자 요구의 자연적 모호성을 명확하게 해석하여 모호하지 않은 문장을 즉시 프로세스로 보낼 수 있어야 한다. 인터페이스는 또한 결과를 사용자에 의해 요구되고 이해되는 형태로 변환할 수 있어야 함.

    • 데스크톱 에이전트.

    데스크톱 에이전트(desktop agent)는 PC나 워크스테이션의 운영 체제에 상주하면서 국부적으로 실행되는 소프트웨어 에이전트이다. 데스크톱 에이전트는 운영 체제 에이전트, 응용 프로그램 에이전트, 응용 프로그램 환경 에이전트로 분류.

    • 인터넷 에이전트.

    인터넷 에이전트(internet agent)는 서버에 상주하면서 사용자와 직접적인 상호 작용없이 사용자를 대신해서 작업을 수행하도록 인터넷상에서 분산된 온라인 정보를 접근하는 컴퓨터 프로그램이다. 인터넷 에이전트는 정보제공자와 정보소비자 사이의 정보중개인으로 동작한다. 그런 정보 매개체로서 인터넷 에이전트는 사용자들의 정보 요구를 정보 공급자, 정보 형태, 정보 내용에 따라 중재해 준다.

    • 전자상거래 에이전트.

    현재의 상거래는 사람이 물건을 사고 파는 업무를 수행하는 거의 전적으로 사람에 의해 이루어지고 있다. 그러나 일부 상거래 과정을 살펴보면 상거래의 일부가 자동화되지 않을 이유가 없다. 상거래 과정의 일부는 에이전트가 대신하는 전자상거래 에이전트(electronic commerce agent)가 출현.

    2. 전문가 시스템과 전통적인 프로그래밍과의 차이점은 무엇인가?

    전문가 시스템이란?

    전문지식의 특정영역에 대한 전문가의 지식을 요약하고 그 영역 안에서 지적인 판단을 내릴 수 있는 Software Package이다. 전문가시스템을 정의하는 다른 방법은, 이를 보통의 프로그램과 비교하는 것. 가장 기본적인 차이는, 보통의 프로그램이 data를 처리하는데 반하여 전문가시스템은 Knowledge를 처리하는 것.

    일반 프로그램전문가 시스템데이터 표현하고 사용.지식을 표현하고 사용.알고리즘을 사용.휴리스틱을 사용.반복적인 처리.추론적인 처리.데이터베이스를 처리.지식 베이스.

    전문가시스템의 특징

    1. 전문지식을 취급함.

    따라서 관련 분야의 전문가와 같은 정도의 성과를 발휘해야 하며 또한 빠르게 좋은 해를 찾아내기 위해 효율적으로 구성되어야 한다. 또한 인간과 같이 넓고 깊은 지식을 제공할 수 있어야 한다.실제에 있어서는 관련분야에 2년 정도 종사한 전문가의 지식구현에 만족하는 경향이며 또한 정확한 해를 구하기 위하여 문제를 축소 시켜 좁은 부분에서 정확한 해를 추구하는 경향

    1. 심볼에 의한 추론을 행함.

    전문가뿐 아니라 전문가시스템의 User들은 인간이기 때문에 인간과의Interactive한 지식교환을 하려면 인간의 애매한 표현들을 정량화하여 전문가 시스템에 구현하여 불확실성을 줄여 나가야 한다. 이러한 심볼 표현에 의한 불확실성은 Certainty Factor나 Fuzzy 이론으로써 구현하게 된다.

    1. 휴리스틱을 이용.

    “휴리스틱”의 의미는 “자기 힘으로 알아내는 자기 발견적인”의 의미이다. 따라서 항상 옳은 것은 아니지만 대부분의 경우에 옳은 정보를 제공한다. Graph Search 과정에서의 넓이우선,깊이우선 탐색은 목표의 위치에 무관한 Blind Search 이다. 그러나 휴리스틱 Search는 가장 가능성이 있는 목표의 위치에 대하여 탐색을 행하여 불필요한 자원낭비를 줄이게 된다. 이때 가장 가능성이 있는 위치를 찾아내기 위하여 전문가의 경험에 의한 규칙(Rules of Thumb)을 이용하거나 또는 각 단계에서의 바람직한 정도를 평가하기 위한 척도로써 Evaluation Function을 사용하기도 한다.

    1. 자기지식을 사용.

    이는 시스템이 갖는 자신의 사고에 관한 지식을 말한다. 이는 지식에 대한 지식을 의미한다. “이순신 장군의 신발은 몇 문인가”하는 질문에 대하여 인간은 쉽게 “모른다”는 답을 하지만 컴퓨터는 자기의 지식을 모두 검색한 후에야 답을 얻는다.그러나 전문가시스템은 Rule로써 문제의 성격을 파악하여 결론의 정확성,일관성,가능성들을 검토하여 추론한다. 이를 위해서 explanation facility를 가지게 되며 Why (왜 전문가시스템이 그런 질문을 하는가를 보여준다), How (어떻게 해서 전문가시스템이 그런 결론을 내렸는가를 보여준다) 등의 자문에 응하게 된다.

    기존의 program과 expert System의 다른 점

    특징conventional programexpert system제어 (control by…)statement orderinference enginecontrol and dataimplicit integrationexplicit separationcontrol strengthstrongweaksolution by..algorithmrules and inferencesolution searchsmall or nonelargeproblem solvingalgorithm is correctrulesinputassumed correctincomplete, incorrectunexpected inputdifficult to deal withvery responsiveoutputalways correctvaries with problemexplanationnoneusuallyapplicationsnumeric, file, and textsymbolic reasoningexecutiongenerally sequentialopportunistic rulesprogram designstructured designlittle or no structuremodifiabilitydifficultreasonableexpansiondone in major jumpsincremental

    3. 순방향 추론과 역방향 추론 과정을 예를 들어 설명해 보세요.

    전제 추론의 정의.

    문제의 해결책은 일반적으로 솔루션에 도달하기 위해 초기 데이터와 사실을 포함합니다. 이러한 알려지지 않은 사실과 정보는 결과를 추론하는 데 사용됩니다. 예를 들어, 환자를 진단하는 동안 의사는 먼저 온도, 혈압, 맥박, 눈 색깔, 혈액 등과 같은 신체의 증상과 의학적 상태를 확인합니다. 그 후, 환자의 증상을 분석하고 미리 결정된 증상과 비교합니다. 그러면 의사는 환자의 증상에 따라 약을 제공 할 수 있습니다. 따라서 솔루션에서 이러한 추론 방식을 사용하는 경우 정방향 추론이라고
    합니다.

    • 정방향 추론에서 수행되는 단계.

    추론 엔진은 우선 순위가 주어진 현재 상태와 일치하는 제약 조건에 대해 제공된 정보를 사용하여 지식 기반을 탐색합니다.

    • 첫 번째 단계에서는 시스템에 하나 이상의 제약 조건이 부여됩니다.
    • 그런 다음 각 제약 조건에 대한 지식 기반에서 규칙을 검색합니다. 조건을 충족시키는 규칙이 선택됩니다 (즉, IF 부분).
    • 이제 각 규칙은 호출 된 규칙의 결론에서 새로운 조건을 생성 할 수 있습니다. 결과적으로 THEN 부분은 기존 부분에 다시 포함됩니다.
    • 추가 된 조건은 2 단계를 반복하여 다시 처리됩니다. 새 조건이없는 경우 프로세스가 종료됩니다.

    역 추론의 정의

    역방향 추론
    은 규칙, 초기 사실 및 데이터를 추론하기 위해 목표가 분석되는 순방향 추론의 역입니다. 의사는 증상과 같은 잘못된 데이터의 도움을 받아 환자를 진단하려고하는 위의 정의에서 주어진 비슷한 예를 통해 개념을 이해할 수 있습니다. 그러나이 경우 환자는 자신의 신체에 문제가있어 의사가 증상을 증명할 수 있습니다. 이러한 종류의 추론은 역 추론 하에서 이루어진다.

    역방향 추론에서 따르는 단계

    이러한 유형의 추론에서 시스템은 목표 상태와 이유를 역방향으로 선택합니다. 자, 어떻게 그것이 일어나고 어떤 단계가 뒤따른 지 이해합시다.

    • 첫째, 목표 상태와 규칙은 목표 상태가 THEN 부분에있는 경우 결론으로 선택됩니다.
    • 선택된 규칙의 IF 부분에서 목표 상태가 참이되도록 부 대상이 만족되도록 만들어집니다.
    • 모든 부 목적을 만족시키는 데 중요한 초기 조건을 설정하십시오.
    • 제공된 초기 상태가 설정된 상태와 일치하는지 확인하십시오. 조건을 충족하면 목표는 다른 목표 상태가 선택되는 솔루션입니다.

    인공지능의 전후 추론의 주요 차이점

    1. 순방향 추론은 데이터 중심 접근 방식이며 역방향 추론은 목표 기반입니다.
    2. 프로세스는 순방향 추론에서 새로운 데이터와 사실로 시작합니다. 반대로, 역 추론은 결과로 시작됩니다.
    3. 순방향 추론은 결과를 결정하고 일부 시퀀스가 뒤 따르는 것을 목표로합니다. 반면에, 결론을 뒷받침하는 행위에 대한 역 추론 강조.
    4. 앞으로의 추론은 다른 결과를 가져올 수 있으므로 기회 주의적 접근 방식입니다. 반대로 후진 적 추론에서 특정 목표는 제한된 특정 초기 데이터 만 가질 수 있습니다.
    5. 앞으로 추론의 흐름은 선행에서 추론으로 이어지는 반면, 후진 추론은 결론에서 시작으로 시작하는 역순으로 작용합니다.

    예시.

    ⇒ 대전제 : 모든사람은 죽는다.

    ⇒ 소전제 : 소크라테스는 사람이다.

    ⇒ 결 론 : 소크라테스는 죽는다.

    4. 자율주행 자동차에 필요할 것 같은 규칙을 만들어 보자

    ⇒ 필요한 규칙

    • 부분 자율주행시스템은 다음 조건을 모두 만족하는 경우에만 작동 할 것
    • 운전자가 부분 자율주행시스템을 의도적으로 작동시키는 행위가 있을 것
    • 운전자가 운전석에 있고, 안전띠를 착용하고 있을 것
    • 운전자가 운전전환 준비상태가 된 것을 감지할 것
    • 운행에 필요한 모든 기능이 정상적으로 작동되고 있을 것
    • 자동차가 주행하는 도로는 다음의 조건을 갖추고 있을 것
    • 보행자와 자전거탑승자의 통행이 금지되는 도로일 것
    • 중앙분리대 등 반대방향으로 이동하는 교통수단을 물리적으로 분리하는 시설을 갖춘 도로일 ML것
    • 운행가능영역 내에 있을 것
    • 시동 후 제작자가 정한 감지거리 이상의 거리에서 최소 한 번 이상 물체를 감지할 것
    • 자율주행정보 기록장치가 정상적으로 작동하고 있을 것

    등이 필요할 것이다.

  • 머신러닝, 딥러닝과 신경망의 기본 개념

    머신러닝, 딥러닝과 신경망의 기본 개념

    머신러닝의 종류.

    • Training : 학습에 사용됨
    • Verification data : 학습되는 모델을 검증 하는데 사용됨
    • Test data : 학습된 모델의 성능을 실제로 평가하기 위해서 사용됨

    머신러닝은 4가지 종류로 분류됨.

    • Supervised learning
    • Unsupervised learning
    • semi-supervised learning
    • Reinforcement learning

    Supervised learning.

    • labeled data로 학습 수행
    • 라벨이 붙어있는 학습 데이터의 예
    • 입력과 출력 사이의 관계를 학습하고, 이 관계가 규칙 또는 함수로 표현되는 모델을 찾음
    • 가장 일반적인 문제 유형
    • image labeling : tagged images로부터 학습
    • Email spam filter: labeled (spam or ham) 이메일로부터 학습
    • 시험 점수 예측 : 이전의 시험 성적과 공부한 시간을 학습

    Unsupervised learning

    • Unlabeled data로 학습.
    • 어떤 데이터는 라벨을 일일이 할당할 수 없음
    • Google news grouping
    • 자동적으로 유사한 뉴스를 그룹핑함
    • 유사한 단어를 수집하는 Word clustering
    • 일일이 데이터에 라벨을 부여하기가 어려움
    • 데이터를 보고 스스로 학습을 수행

    반지도학습.(semi-supervised learning.)

    • 지도 학습과 비지도 학습의 중간에 위치함
    • 입력과 출력 정보가 있는 학습데이터와 입력만 있고 출력 정보가 없는 학습데이터를 함꼐 사용함
    • 입력과 출력정보가 함께 있는 학습데이터가 적은 상황에서 분류나 회귀 모델 개발시
    • 출력 정보가 없는 입력데이터의 분포 특성 정보를 활용하여 성능 개선

    강화학습(reinforcement learning.)

    • 특정 환경에서 행동과 이에 대한 보상의 경험을 통해서 보상이 최대가 되도록 상황별로 취할 행동을 결정하는 방법
    • 게임, 제어문제, 금융공학 등에서 행동 전략이나 정책을 결정할 때 사용함

    supervised Learning의 수행단계

    • step 1 : Training data set과 ML 모델이 주어짐
    • step 2 : Label이 주어진 training data set을 학습시킴
    • step 3 : 학습을 통해 ML 모델이 생성됨
    • 모델의 파라미터가 학습을 통해 결정됨
    • step 4 : 생성된 ML 모델에 x_test라는 값을 입력하여 y의 값을 물어봄
    • step 5 : 생성된 ML 모델은 x_test에 대한 y의 값은 3이라고 알려줌

    감독학습의 종류.

    • Regression
      • 출력이 연속적인 영역 안의 값을 결정하는 분야
      • Linear regression과 nonlinear regression으로 분류됨
      • 공부한 시간을 기반으로 0점에서 100점 사이의 시험 성적을 예측하는 시스템
    • Classification
      • 데이터들을 정해진 몇 개의 class로 대응시키는 문제
    • Binary classification
      • 데이터를 2가지 class로 분류함
      • 공부한 시간을 기준으로 성적이 pass했는지 non-pass 했는지를 예측하는 시스템
    • Multi-label classification
      • 데이터를 여러 가지 class로 분류함
      • 공부한 시간을 기반으로 성적이 A,B,C,D,F 이지를 예측하는 시스템

    신경망

    • 인간 두뇌의 생리적 활동에 대한 계산적 모델을 통해 인공지능을 구현하려는 분야
    • 인간의 궁극적인 꿈 : 생각하는 기계 만들기
    • 생물학적인 뉴런의 구성도
    • 여러 개의 Signals 들이 입력되어서 cell nucleus에서 합해짐
    • 합쳐진 시그널들이 일정한 값 이상이 될 때에는 활성화가 되어서 다음 뉴런에 전달됨

    Biological neuron 동작 원리를 흉내냄

    • 인공적인 뉴런을 만듦
    • 인공적인 뉴럴 네트워크
    • 인공적인 뉴런을 여러 개 결합한 것

    perceptron

    • 입력 노드와 출력 노드로 구성된 ANN
    • Frank Rosenblatte 박사에 의해 고안됨

    Multi-layer perceptron (MLP)

    • input layer 및 output layer와 함께 hidden layer가 존재함
    • Marvin Minsky 교수에 의해 고안됨

    Deep neural network (DNN)

    • 은닉층이 2개 이상인 MLP를 의미

    딥러닝(deep learning.)

    • Deep NN을 사용해 만든 모든 알고리즘

    딥러닝의 종류.

    • Convolutional neural network (CNN)
    • Recurrent Neural network(RNN)
    • Restricted Boltzmann Machine (RBM)
    • Deep Belief Network (DBN)
    • Generative Adversarial Network (GAN)
    • Relation Networks (RN)

    Convolutional neural network (CNN)

    • 특징맵을 생성하는 필터까지도 학습이 가능해 비전(vision)분야에서 성능이 우수함

    Recurrent Neural network (RNN)

    • 음성과 같은 Time-series data의 처리에 적합함

    필요한 개발 툴.

    • IDE : jupyter Notebook
    • Python
    • Numpy : 강력한 계산 기능 수행
    • Matplotlib : 분석된 데이터의 시각화
    • Scikit-Learn : Python의 ML package
    • TensorFlow
    • 머신러닝을 위해 구글에서 만들어짐
    • data flows를 사용해서 수치 계산을 위한 open-source software library for
    • 최근에 머신러닝 라이브러리로 가장 많이 사용 되고 있음

    머신러닝으로 암 데이터 예측.

    • 특징 데이터
    • Age와 tumor_size
    • Label 데이터
    • 0(암), 1(정상)
    • 학습 모델
    • Multi-variable linear
    • regression model
    • ML library
    • Scikit-learn 사용함
    import matplotlib.pyplot as plt
    import numpy as np
    import numpy.random as npr
    from sklearn import datasets, linear_model
    from sklearn.metrics import mean_squared_error, r2_score
    datum = np.genfromtxt('../Desktop/data/cancer_data.csv',delimiter = ',', dtype = np.float32, skip_header = True)
    # except header.
    datum = datum[1:,:]
    #shuffle.
    npr.shuffle(datum)
    X = datum[:, :2]
    Y = datum[:, 2]
    train_x = X[:60]
    test_x = X[60:80]
    val_x = X[80:]
    train_y = Y[:60]
    test_y = Y[60:80]
    val_y = Y[80:]
    regr = linear_model.LinearRegression()
    regr.fit(train_x, train_y)
    test_preds = regr.predict(test_x)
    fig = plt.figure()
    ax = fig.add_subplot(2,2,1)
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 10)
    ax.set_title('Pred')
    test_preds = [0 if pred <= 0.5 else 1 for pred in test_preds]
    pred_colors = ['b' if pred == 0 else 'r' for pred in test_preds]
    ax.scatter(test_x[:,0], test_x[:,1], color = pred_colors, linewidth = 3)
    ax = fig.add_subplot(2,2,2)
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 10)
    ax.set_title('True')
    y_colors = ['b' if y == 0 else 'r' for y in test_y]
    ax.scatter(test_x[:,0], test_x[:,1], color = y_colors, linewidth = 3)
    plt.show()
  • Jenkins와 Bitbucket 연동하기: Webhook 설정 가이드

    Jenkins와 Bitbucket 연동하기: Webhook 설정 가이드

    Jenkins와 BitBucket을 연동하려고 했을 때, Bitbucket Plugin을 설치해서 사용하려 했으나, 연동이 잘 되질 않아, Jenkins Plugin 중 Generic Webhook Trigger를 사용하였다.

    📌 구성

    로컬 PC에서 사용하고자 하는 Repo — main 브랜치에 Push할 때, Jenkins가 Push를 인지하여 자동으로 Dev 서버, Prod 서버에 소스코드 배포 되게 만들고 싶었다. (다른방법도 가능.)

    🚧 사전작업

    내가 CI/CD를 하고 싶은 Repo를 가서, Repository Setting 으로 들어간다.

    들어가면 Webhook라는 메뉴가 있는데, 여길 들어가면 Webhook를 추가 할 수 있다.

    설정해야 하는 항목

    이하 설정은 필요한 대로 설정하면 된다.

    ✅ URL 항목에 Jenkins Security 토큰 값 받는 법

    Jenkins 페이지에 들어가서, 오른쪽 상단에 닉네임을 클릭하면 아래와 같은 메뉴가 나온다.

    여기서, Security를 들어가준다.

    그러면, 밑에와 같은 API Token 값을 만들수가 있다.

    여기서 Token값을 만들면 나에게 Token값을 부여함. 해당 토큰값은 한번만 보여주니 별도로 저장해 놓자.

    📌 Jenkins에서 Generic Webhook Trigger Plugin 설치.

    Jenkins 관리 ➡️ System Configuration ➡️ Plugins 에 들어가면,

    해당 페이지가 나온다. 여기서, Available Plugins 에 들어가 Generic Webhook Trigger Plugin 을 설치해준다.

    📌 Jenkins Pipeline 작성

    위에 까지 구축해 놨으면, 이제 Pipeline Project를 작성해주면 된다.(freestyle로 작성해도 무관.)

    Pipeline과 freestyle 프로젝트 중에 원하는걸로 작성해도 되지만, CI/CD의 유연성을 위해 Pipeline으로 작성했다.

    📦 Pipeline Configure

    📌General

    이 부분은 설명할 것을 넣어주고 필요한 옵션들을 선택해주면 된다. 물론, 선택을 안해도 상관없다. (난 선택 안함..)

    📌 Trigger

    Pipeline에 Trigger를 넣어놔서 Jenkins UI에 적용시키지 않아도 적용이 된다.

    Pipeline 스크립트에 설정하면 자동으로 적용됨

    📌 Pipeline. (Pipeline Script.)

    파이프라인 스크립트로 작성했다. Trigger 부분은 위에서 선택하고 작성 부분이랑 중복될 수있다. 참고해서 보자.

    pipeline {
        agent any
        triggers {
            GenericTrigger(
                genericVariables: [
                    [key: 'branch_name', value: '$.push.changes[0].new.name']
                ],
                tokenCredentialId: '', // Bitbucket Webhook 토큰 Credential ID
                causeString: 'Triggered by Bitbucket Push to ${branch_name}',
                printContributedVariables: true,
                printPostContent: true,
                regexpFilterText: '$branch_name',
                regexpFilterExpression: '^dev$' //branch 이름.
            )
        }
        environment {
            TELEGRAM_API_URL = ""
            CHAT_ID = ""
        }
        stages {
            stage('Clone Repository') {
                steps {
                    echo 'Cloning repository...'
                    git branch: 'develop', 
                        credentialsId: '', // CredentialId 이름 넣기.
                        url: '' // bitbucket URL
                }
            }
            stage('Test & Build') {
                steps {
                    script {
                        try {
                            sh '''
                            // 실행할 CLI 명렁어.
                            '''
                            sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n🥷 Jenkins CICD | Step Testing and building Success!'"
                        } catch (e) {
                            sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n❌ Jenkins CICD | Step Testing and building Failed!'"
                            throw e
                        }
                    }
                }
            }
            stage('Old Directory Remove') {
                steps {
                    script {
                        try {
                            sh '''
                            // 실행할 CLI 명렁어.
                            '''
                            sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n🥷 Jenkins CICD | Step Old Directory Remove Success!'"
                        } catch (e) {
                            sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n❌ Jenkins CICD | Step Old Directory Remove Failed!'"
                            throw e
                        }
                    }
                }
            }
            stage('Deploy to Server') {
                steps {
                    script {
                        try {
                            sh '''
                            // 실행할 CLI 명렁어.
                            '''
                            sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n🥷 Jenkins CICD | Step Deploy to Server Success!'"
                        } catch (e) {
                            sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n❌ Jenkins CICD | Step Deploy to Server Failed!'"
                            throw e
                        }
                    }
                }
            }
        }
        post {
            always {
                echo 'Pipeline execution completed.'
            }
            failure {
                sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n❌ Jenkins CICD | Pipeline Failed!'"
            }
            success {
                sh "curl -s -X POST '${TELEGRAM_API_URL}' -d chat_id=${CHAT_ID} -d text='[Repository: ${env.JOB_NAME} Branch: ${env.branch_name}]\n✅ Jenkins CICD | Pipeline Succeeded!'"
            }
        }
    }

    🚀 code 내용

    Repo Clone (젠킨스 서버로 복제) ➡️ Repo HOST OS 로 이동 ➡️ Repo node container로 이동 ➡️ Test & Build (통과하면) ➡️ 배포할 서버에 기존 Directory 삭제 ➡️ 배포하고 싶은 서버에 배포. 순으로 Pipeline 작성

    ✅ 추가 작업 사항

    ✔️ credentialId

    credentialId을 만드는 법은 Jenkins 페이지에서 오른쪽 상단에 닉네임을 클릭하면 아래와 같은 메뉴가 나온다.

    여기서 Credentials 를 들어가,

    Add. Credentials 해준다. 그럼, 아래와 같은 화면이 나오는데,

    • Username : 비트버킷 아이디
    • password : 비트버킷에서 받은 앱 비밀번호
    • ID : Credential ID
    • Description : 설명

    비트버킷에서 받은 앱 비밀번호는 비트버켓에서 받을 수 있다.

    ✔ 비트버킷에서 앱 비밀번호 받는 법

    • Personal Bitbucket settings ➡️ 앱 비밀번호

    이곳에서 받으면 된다.

    ✔ Bitbucket_URL 가져오는 법

    비트버킷 URL을 가져오려면 비트버킷에서 Access tokens을 설정해야 한다. 비트버킷에서 Repository Setting로 들어가 Access Token 메뉴를 들어가서 token을 생성하면 URL 생성이 된다.

    ✔ Publish over SSH 설정하는 법

    해당 플러그인은 여러개의 키값을 설정할 수가 없어서 다른 플러그인을 써도 되고, 키파일을 ssh로 설정을 해서 접근을 가능하게 만들어도 된다. (원하는대로..)

  • Jenkins Docker 실행 가이드

    Jenkins Docker 실행 가이드

    Jenkins Docker 실행 가이드

    📌 Mount 할 Jenkins 디렉토리 폴더 생성 및 권한 설정

    mkdir jenkins_home
    chmod 777 jenkins_home

    📌 Jenkins 이미지 Pull

    # jenkins 이미지 띄우기.
    
    docker pull jenkins/jennkins:lts

    📌 Jenkins 컨테이너 실행

    docker run -d --name jenkins \
      -p 8080:8080 -p 50000:50000 \
      -v /your/path/jenkins_home:/var/jenkins_home \
      --restart unless-stopped \
      jenkins/jenkins:lts
    • -p 8080:8080: Jenkins 웹 인터페이스를 호스트의 8080 포트에 노출
    • -p 50000:50000: 빌드 에이전트와 통신을 위한 포트
    • -v /your/path/jenkins_home:/var/jenkins_home: Jenkins 데이터를 호스트 디렉토리에 마운트
    • restart unless-stopped: Docker 재시작 시 컨테이너 자동 실행

    📌 Jenkins 초기설정

    1. 브라우저에서 http://localhost:8080으로 접속.
    2. 초기 관리자 비밀번호는/your/path/jenkins_home/secrets/initialAdminPassword 파일에 저장.
    cat /your/path/jenkins_home/secrets/initialAdminPassword