본문 바로가기
GD's IT Lectures : 기초부터 시리즈/파이썬(Python) 기초부터 ~

[파이썬(PYTHON) : 중급] 네트워크 프로그래밍

by GDNGY 2023. 5. 11.

7. 네트워크 프로그래밍

네트워크 프로그래밍에서는 소켓 프로그래밍을 통해 네트워크 통신을 구현하는 방법을 배웁니다. HTTP 요청 및 응답 처리를 다루며, RESTful API 개념 및 활용 방법에 대해 알아봅니다. 웹 스크레이핑 기법을 통해 웹사이트에서 데이터를 추출하는 방법을 학습하게 됩니다.

7.1. 소켓 프로그래밍

7.1.1. 소켓 프로그래밍 이해하기

7.1.1.1. 소켓의 개념 및 이해

소켓(socket)은 컴퓨터 네트워크에서 데이터를 주고받는 두 컴퓨터 간의 통신을 가능하게 하는 연결점입니다. 기본적으로 하나의 컴퓨터(서버)가 특정 포트에 소켓을 열어두면, 다른 컴퓨터(클라이언트)가 그 소켓에 연결하여 데이터를 주고받을 수 있습니다.

 

7.1.1.2. 클라이언트와 서버 소켓의 차이점

서버 소켓은 특정 포트에서 연결 요청을 기다리는 역할을 합니다. 한편, 클라이언트 소켓은 서버의 특정 포트로 연결을 요청하는 역할을 합니다. 즉, 서버 소켓은 받아들이는 측이고, 클라이언트 소켓은 연결을 요청하는 측입니다.

 

7.1.2. TCP/IP 소켓 프로그래밍

7.1.2.1. TCP/IP 프로토콜 개요

TCP/IP(Transmission Control Protocol/Internet Protocol)는 인터넷에서 가장 널리 사용되는 프로토콜입니다. TCP는 데이터를 패킷으로 나누어 안전하게 전송하며, IP는 이 패킷들을 목적지로 전달합니다. TCP/IP 소켓 프로그래밍은 이 프로토콜을 이용한 소켓 프로그래밍을 의미합니다.

 

7.1.2.2. Python에서의 TCP/IP 소켓 구현

Python에서는 socket 모듈을 이용하여 TCP/IP 소켓을 쉽게 구현할 수 있습니다. 예를 들어, 간단한 TCP/IP 서버를 만들어 보겠습니다.

import socket

# 소켓 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 소켓 바인드: ''는 모든 IP에 바인드하라는 의미
server_socket.bind(('', 12345))

# 소켓이 연결 요청을 기다림
server_socket.listen()

while True:
    # 연결 수락
    client_socket, addr = server_socket.accept()
    print('Connected by', addr)

    while True:
        # 클라이언트로부터 데이터 받기
        data = client_socket.recv(1024)
        if not data:
            # 데이터가 없는 경우 연결 종료
            break
        print('Received from', addr, data.decode())

        # 받은 데이터를 클라이언트에게 다시 전송 (에코)
        client_socket.sendall(data)

    # 연결 종료
    client_socket.close()

 

위의 코드는 TCP/IP 프로토콜을 이용하여 서버 소켓을 구현한 것입니다. 클라이언트로부터 데이터를 받으면, 그대로 다시 클라이언트에게 데이터를 전송하는 에코 서버입니다.

 

7.1.3. UDP 소켓 프로그래밍

7.1.3.1. UDP 프로토콜 개요

UDP(User Datagram Protocol)는 TCP와 달리 연결 없이 데이터를 전송하는 프로토콜입니다. 따라서 데이터의 전송이 보장되지 않지만, 빠른 전송 속도를 가집니다.

 

7.1.3.2. Python에서의 UDP 소켓 구현

Python에서는 마찬가지로 socket 모듈을 이용하여 UDP 소켓을 구현할 수 있습니다. UDP 서버를 만들어 보겠습니다.

import socket

# 소켓 생성
server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# 소켓 바인드
server_socket.bind(('', 12345))

while True:
    # 클라이언트로부터 데이터 받기
    data, addr = server_socket.recvfrom(1024)
    print('Received from', addr, data.decode())

    # 받은 데이터를 클라이언트에게 다시 전송
    server_socket.sendto(data, addr)

 

UDP 서버는 TCP 서버와 비슷하지만, 연결 없이 데이터를 바로 받고 전송하는 점이 차이점입니다.

 

7.1.3.3. Python에서의 UDP 클라이언트 소켓 구현

마찬가지로 UDP 클라이언트도 구현해 보겠습니다.

import socket

# 소켓 생성
client_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

while True:
    # 서버에 보낼 데이터 입력
    msg = input("Enter message to send: ")
    if msg == 'q':
        break

    # 데이터 전송
    client_socket.sendto(msg.encode(), ('localhost', 12345))

    # 서버로부터 응답 받기
    data, addr = client_socket.recvfrom(1024)
    print('Received from', addr, data.decode())

# 소켓 종료
client_socket.close()

 

이 코드는 사용자로부터 입력받은 데이터를 UDP로 서버에 전송하고, 서버로부터의 응답을 출력하는 클라이언트입니다. 'q'를 입력하면 프로그램이 종료됩니다. 

 

7.2. HTTP 요청 및 응답 처리

7.2.1. HTTP 요청 이해하기

7.2.1.1. HTTP 프로토콜 및 요청 메서드 개요

HTTP(Hypertext Transfer Protocol)는 클라이언트와 서버 간의 데이터 전송을 위해 사용되는 프로토콜입니다. 이는 웹에서 정보를 공유하는 주요 수단입니다. HTTP는 요청(request)과 응답(response)으로 구성되며, 클라이언트가 서버에게 요청을 보내면, 서버는 해당 요청에 대한 응답을 반환합니다.

 

HTTP 요청에는 여러 가지 메소드가 있습니다:

  • GET: 해당 URL의 정보를 조회합니다. 데이터를 서버로 전송하려면, 데이터가 URL에 포함되어 전송됩니다.
  • POST: 서버로 데이터를 전송할 때 사용합니다. 데이터는 요청 본문에 포함되어 전송됩니다.
  • PUT: 서버의 리소스를 새 데이터로 대체하거나, 리소스가 없는 경우 새 리소스를 생성합니다.
  • DELETE: 해당 URL의 리소스를 삭제합니다.

 

7.2.1.2. Python에서의 HTTP 요청 생성 및 전송

Python에서는 requests 라이브러리를 이용하여 HTTP 요청을 생성하고 전송할 수 있습니다. requests.get(URL)을 이용하여 GET 요청을 생성하고, 서버로부터 받은 응답을 response 객체에 저장할 수 있습니다.

import requests

# GET 요청
response = requests.get('http://example.com')

# 응답 내용 출력
print(response.text)

 

위의 코드는 'http://example.com'에 GET 요청을 보내고, 응답을 출력하는 코드입니다.


7.2.2. HTTP 응답 처리하기

7.2.2.1. HTTP 상태 코드 이해하기

HTTP 응답에는 상태 코드가 포함됩니다. 이는 서버가 클라이언트의 요청을 어떻게 처리했는지를 나타냅니다. 일반적인

 

상태 코드로는 다음과 같은 것들이 있습니다:

  • 200 OK: 요청이 성공적으로 처리되었습니다.
  • 400 Bad Request: 요청이 서버로부터 이해할 수 없는 형식으로 전달되었습니다.
  • 404 Not Found: 요청한 리소스가 서버에서 찾을 수 없습니다.
  • 500 Internal Server Error: 서버에서 요청을 처리하는 중에 오류가 발생하였습니다.

 

7.2.2.2. Python에서의 HTTP 응답 처리

requests 라이브러리를 이용하면 HTTP 응답도 쉽게 처리할 수 있습니다. 응답의 상태 코드는 response.status_code로, 응답 본문은 response.text로 확인할 수 있습니다.

import requests

# GET 요청 생성 및 전송
response = requests.get('http://example.com')

# 서버로부터 받은 응답 출력
print(response.text)

 

위 코드에서, requests.get('http://example.com')는 'http://example.com'에 GET요청을 보내는 코드입니다. 응답은 response 객체에 저장되고, 이 응답의 상태 코드와 본문은 각각 response.status_code와 response.text로 접근하여 출력할 수 있습니다. 

 

POST 요청을 보내는 경우, requests.post(URL, data) 함수를 사용하고, 데이터를 인자로 전달할 수 있습니다. 이 때, 데이터는 딕셔너리 형태로 전달되며, 이는 서버에 보내는 정보를 포함하고 있습니다.

import requests

# POST 요청 생성 및 전송
data = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('http://example.com', data=data)

# 상태 코드와 응답 본문 출력
print('Status Code:', response.status_code)
print('Response Body:', response.text)

 

위 코드에서, 'http://example.com'에 데이터를 포함한 POST 요청을 보내고 있습니다. 응답의 상태 코드와 본문은 앞서 설명한 방법과 동일하게 출력할 수 있습니다.

 

7.3. RESTful API 개념 및 활용

7.3.1. RESTful API 이해하기

7.3.1.1. REST 개념 및 원칙

REST(Representational State Transfer)는 웹 서비스 설계를 위한 아키텍처 스타일입니다. 이는 웹의 기본 프로토콜인 HTTP를 그대로 활용하며, 웹의 장점을 최대한 활용할 수 있는 아키텍처입니다.

 

REST의 핵심 원칙은 다음과 같습니다:

  • Stateless: 각 요청 간에 클라이언트의 상태를 저장하지 않습니다. 서버는 각 요청을 별개로 처리하며, 이전 요청을 기억하지 않습니다.
  • Client-Server: 클라이언트-서버 구조를 가집니다. 클라이언트는 사용자 인터페이스와 관련된 책임을, 서버는 데이터 관리와 관련된 책임을 가집니다.
  • Cacheable: 클라이언트는 응답을 캐싱할 수 있습니다. 이는 클라이언트가 필요에 따라 응답을 재사용할 수 있음을 의미합니다.
  • Layered System: 클라이언트는 직접 서버와 통신하거나, 중간 계층을 통해 서버와 통신할 수 있습니다.

 

7.3.1.2. RESTful API의 특징 및 장단점

RESTful API는 REST 원칙에 기반한 API(Application Programming Interface)입니다.

 

주요 특징은 다음과 같습니다:

  • HTTP 프로토콜을 그대로 사용합니다. 따라서 HTTP 메소드(GET, POST, PUT, DELETE 등)를 그대로 활용할 수 있습니다.
  • URI(Uniform Resource Identifier)를 이용해 리소스를 식별합니다. 각 리소스는 고유한 URI를 가집니다.
  • 데이터 포맷으로 주로 JSON을 사용합니다.

 

장점:

  • 웹의 인프라를 그대로 활용 가능합니다. HTTP 프로토콜 기반으로 동작하므로, 웹 인프라를 그대로 활용할 수 있습니다.
  • 언어 독립적입니다. 어떤 언어에서도 RESTful API를 사용할 수 있습니다.

 

단점:

  • HTTP 프로토콜만 사용 가능합니다. 다른 프로토콜을 사용하려면 별도의 아키텍처를 설계해야 합니다.
  • 표준이 없습니다. REST는 아키텍처 스타일이므로, API 설계에 있어서 엄격한 표준을 제공하지 않습니다.

 

7.3.2. Python에서의 RESTful API 활용

7.3.2.1. Python에서의 RESTful API 요청 구현

Python에서는 requests 라이브러리를 통해 간단하게 RESTful API를 호출할 수 있습니다. GET 요청을 보내는 예제는 다음과 같습니다:

import requests

# RESTful API GET 요청
response = requests.get('https://api.github.com')

# 응답 출력
print(response.json())

 

위 코드는 GitHub의 REST API를 호출하는 예제입니다. requests.get() 함수를 이용해 GET 요청을 보내고, 응답은 response 객체에 저장됩니다. 응답의 내용은 response.json()을 통해 JSON 형태로 확인할 수 있습니다.

 

POST, PUT, DELETE 등의 다른 HTTP 메소드를 사용하려면, requests.post(), requests.put(), requests.delete() 등의 함수를 사용하면 됩니다.

 

7.3.2.2. Python에서의 RESTful API 응답 처리

RESTful API 호출의 응답은 대부분 JSON 형태로 옵니다. Python에서는 이 JSON 응답을 json() 메서드를 이용해 딕셔너리 형태로 쉽게 변환할 수 있습니다.

import requests

# RESTful API GET 요청
response = requests.get('https://api.github.com')

# JSON 응답을 딕셔너리로 변환
data = response.json()

# 딕셔너리 출력
for key, value in data.items():
    print(f'{key}: {value}')

 

위 코드는 https://api.github.com 에서 받은 JSON 응답을 딕셔너리 형태로 변환하고, 각 키와 값을 출력하는 예제입니다.

 

7.4. 웹 스크레이핑 기법

7.4.1. 웹 스크레이핑 기본 이해

7.4.1.1. 웹 스크레이핑 개념 및 원리

웹 스크레이핑이란 웹사이트에서 원하는 정보를 추출하는 기술을 말합니다. 웹페이지는 대개 HTML, CSS, JavaScript 등을 통해 구성되는데, 웹 스크레이핑은 이러한 웹페이지의 구조를 분석하고 필요한 데이터만을 추출합니다. 이 과정에서 HTML의 구조적 특성인 태그나 속성을 이용해 데이터를 찾아내는 작업이 필요합니다.

 

7.4.1.2. 웹 스크레이핑의 법적인 측면

웹 스크레이핑은 법적으로 민감한 영역일 수 있습니다. 대부분의 웹사이트는 사용자가 데이터를 스크레이핑 하는 것을 금지하는 이용약관을 가지고 있습니다. 그러므로 스크레이핑을 진행하기 전에 해당 사이트의 이용약관을 반드시 확인하고, 필요하다면 사이트 운영자의 허락을 받는 것이 좋습니다.

 

7.4.2. BeautifulSoup 활용하기

7.4.2.1. BeautifulSoup 기본 사용법

BeautifulSoup는 웹페이지의 HTML을 분석하고 조작하기 위한 Python 라이브러리입니다. 다음은 BeautifulSoup를 이용한 기본적인 웹 스크레이핑 코드입니다:

from bs4 import BeautifulSoup
import requests

# 웹페이지 불러오기
response = requests.get('https://www.example.com')
html = response.text

# BeautifulSoup 객체 생성
soup = BeautifulSoup(html, 'html.parser')

# 태그를 이용한 데이터 추출
h1_tag = soup.find('h1')
print(h1_tag.text)

 

7.4.2.2. 실제 사이트에서 BeautifulSoup 활용

다음은 실제 웹사이트에서 BeautifulSoup를 활용하여 데이터를 추출하는 예제입니다:

from bs4 import BeautifulSoup
import requests

# 웹페이지 불러오기
response = requests.get('https://real-website.com')
html = response.text

# BeautifulSoup 객체 생성
soup = BeautifulSoup(html, 'html.parser')

# 클래스 이름을 이용한 데이터 추출
items = soup.find_all(class_='item-class-name')
for item in items:
    print(item.text)

 

7.4.3. Selenium 활용하기

7.4.3.1. Selenium 기본 사용법

Selenium은 웹 브라우저를 제어할 수 있는 자동화 도구입니다. 이를 Python에서 사용할 수 있게 해주는 패키지가 바로 Selenium WebDriver입니다. 주로 웹 애플리케이션 테스트를 자동화하는데 사용되지만, 웹 스크레이핑에서도 활용됩니다. JavaScript로 동적으로 로딩되는 데이터를 크롤링할 때 유용하죠.

 

아래는 Selenium을 이용해 웹사이트에 접속하고, 제목을 출력하는 간단한 코드입니다.

from selenium import webdriver

# WebDriver 객체 생성
driver = webdriver.Firefox()

# 웹사이트 접속
driver.get('https://www.example.com')

# 웹사이트 제목 출력
print(driver.title)

# 브라우저 종료
driver.quit()

 

7.4.3.2. 실제 사이트에서 Selenium 활용

Selenium은 실제 웹사이트에서 웹 요소를 검색하거나 클릭하고, 텍스트를 입력하고, JavaScript를 실행하는 등의 작업을 수행할 수 있습니다. 이러한 기능은 로그인이 필요한 사이트나 동적으로 렌더링되는 웹페이지에서 데이터를 추출할 때 유용합니다.

 

다음은 실제 웹사이트에서 Selenium을 활용하여 데이터를 추출하는 예제입니다:

from selenium import webdriver

# WebDriver 객체 생성
driver = webdriver.Firefox()

# 웹사이트 접속
driver.get('https://real-website.com')

# 웹 요소 선택
element = driver.find_element_by_css_selector('div.some-class')

# 웹 요소에서 텍스트 추출
print(element.text)

# 브라우저 종료
driver.quit()

 

이렇게 Selenium을 사용하면 JavaScript를 이용해 동적으로 변하는 웹페이지에서도 원하는 정보를 추출할 수 있습니다. 그럼에도 불구하고 Selenium은 웹 브라우저를 제어해야 하기 때문에 비교적 느리다는 단점이 있습니다. 따라서 가능하다면 정적 웹페이지에 대해서는 BeautifulSoup 등의 라이브러리를 활용하는 것이 효율적일 수 있습니다.

 

 

 

2023.05.11 - [GD's IT Lectures : 기초부터 시리즈/파이썬(Python) 기초부터 ~] - [파이썬(PYTHON) : 중급] 데이터 처리 및 분석

 

[파이썬(PYTHON) : 중급] 데이터 처리 및 분석

6. 데이터 처리 및 분석 데이터 처리 및 분석에서는 JSON과 CSV 파일 처리 방법을 배우고, pandas와 NumPy 라이브러리를 활용하여 데이터를 분석하는 방법을 익힙니다. 이를 통해 실제 데이터를 다루는

gdngy.tistory.com

 

반응형

댓글