[go] Go 언어로 웹 스크래핑 시 성능 향상 방법

웹 스크래핑은 웹 페이지에서 데이터를 추출하는 작업을 의미합니다. Go 언어는 웹 스크래핑을 위한 강력한 툴을 제공하며, 이를 최대한 효율적으로 사용하여 성능을 향상시킬 수 있습니다. 이번 글에서는 Go 언어로 웹 스크래핑 시 성능을 향상시키기 위한 몇 가지 방법에 대해 알아보겠습니다.

1. 다중 고루틴 사용

고루틴은 Go 언어의 핵심 기능 중 하나로, 경량화된 스레드로 동시성을 구현할 수 있습니다. 웹 스크래핑 작업은 여러 개의 요청을 동시에 처리해야 하기 때문에, 고루틴을 사용하여 동시성을 활용할 수 있습니다. 이를 통해 CPU 사용량을 최대화하고 처리 속도를 향상시킬 수 있습니다.

package main

import (
	"fmt"
	"net/http"
	"sync"
)

func scrapeWebsite(url string, wg *sync.WaitGroup) {
	defer wg.Done()

	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("Error scraping website:", err)
		return
	}

	// 웹 페이지 스크래핑 작업 수행
	// ...

	resp.Body.Close()
}

func main() {
	urls := []string{"https://example.com", "https://google.com", "https://github.com"}

	var wg sync.WaitGroup
	wg.Add(len(urls))

	for _, url := range urls {
		go scrapeWebsite(url, &wg)
	}

	wg.Wait()
}

위 코드에서는 scrapeWebsite 함수를 고루틴으로 실행하고, sync.WaitGroup을 사용하여 모든 고루틴이 작업을 완료할 때까지 기다립니다. 이를 통해 여러 웹 페이지를 동시에 스크래핑할 수 있습니다.

2. HTTP Keep-Alive 사용

HTTP Keep-Alive는 웹 서버와의 TCP 연결을 유지하는 기능입니다. 일반적으로 HTTP 요청 시마다 TCP 연결을 맺고 끊는 것은 오버헤드가 발생하므로, Keep-Alive를 사용하여 TCP 연결을 재사용할 수 있습니다. 이를 통해 웹 스크래핑 작업에서의 네트워크 지연을 줄일 수 있습니다.

package main

import (
	"fmt"
	"net/http"
)

func main() {
	client := &http.Client{
		Transport: &http.Transport{
			MaxIdleConnsPerHost: 100,
		},
	}

	urls := []string{"https://example.com", "https://google.com", "https://github.com"}

	for _, url := range urls {
		resp, err := client.Get(url)
		if err != nil {
			fmt.Println("Error scraping website:", err)
			continue
		}

		// 웹 페이지 스크래핑 작업 수행
		// ...

		resp.Body.Close()
	}
}

위 코드에서는 http.TransportMaxIdleConnsPerHost를 사용하여 동시에 유지할 수 있는 TCP 연결의 최대 개수를 설정합니다. 이렇게 하면 작업량이 많은 웹 스크래핑 작업에서도 TCP 연결을 효율적으로 재사용할 수 있습니다.

3. 적절한 캐싱 활용

웹 스크래핑 작업은 동일한 웹 페이지를 여러 번 요청하는 경우가 많습니다. 이 경우, 적절한 캐싱을 활용하여 중복 요청을 피할 수 있습니다. Go 언어에서는 GoCache와 같은 캐싱 라이브러리를 사용할 수 있습니다.

package main

import (
	"fmt"
	"net/http"
	"time"

	"github.com/patrickmn/go-cache"
)

var (
	c = cache.New(5*time.Minute, 10*time.Minute)
)

func scrapeWebsite(url string) {
	data, found := c.Get(url)
	if found {
		// 캐싱된 데이터 사용
		fmt.Println("Using cached data for", url)
		return
	}

	resp, err := http.Get(url)
	if err != nil {
		fmt.Println("Error scraping website:", err)
		return
	}

	// 웹 페이지 스크래핑 작업 수행
	// ...

	resp.Body.Close()

	// 데이터 캐싱
	c.Set(url, data, cache.DefaultExpiration)
}

func main() {
	urls := []string{"https://example.com", "https://google.com", "https://github.com"}

	for _, url := range urls {
		go scrapeWebsite(url)
	}

	time.Sleep(time.Second * 5) // 스크래핑 작업이 완료될 때까지 대기
}

위 코드에서는 go-cache 패키지를 사용하여 데이터를 캐싱합니다. c.Get을 통해 캐싱된 데이터를 가져오고, 캐시가 없는 경우에만 웹 페이지를 스크래핑합니다. 이를 통해 중복 웹 페이지 요청을 줄일 수 있습니다.

마무리

Go 언어로 웹 스크래핑 시 성능 향상을 위해 다중 고루틴 사용, HTTP Keep-Alive 활용, 그리고 적절한 캐싱을 활용하는 방법에 대해 알아보았습니다. 이러한 방법들을 적용하여 웹 스크래핑 작업의 성능을 최적화할 수 있습니다.