Go 언어로 만드는 간단한 리버스 프록시 서버
안녕하세요! 프로그래밍의 매력을 느끼고 있는 여러분, 오늘은 Go 언어를 이용하여 간단한 리버스 프록시 서버를 구축하는 방법을 알아보겠습니다. 특히, Go의 생생한 패키지들을 활용해 일반적인 프록시 서버의 역할을 하는 코드를 만들어볼 예정입니다.
들어가며
리버스 프록시 서버란, 클라이언트와 서버 사이에서 클라이언트의 요청을 다른 서버로 전달하고, 그 응답을 클라이언트에게 반환하는 역할을 합니다. 웹사이트의 트래픽 증가에 대처하기 위한 엔지니어링 방법 중 하나로, 리버스 프록시가 많은 비즈니스에서 사용되고 있습니다.
코드 작성하기
아래는 Go 언어의 표준 라이브러리를 사용해 리버스 프록시 서버를 구현한 코드입니다.
1. 프로젝트 파일 구조
.
├── go.mod
├── main.go
├── handler
│ ├── default_handler.go
│ └── proxy_handler.go
└── server
└── server.go
2. main.go
package main
import (
"fmt"
"my-go-proxy-server/server"
)
func main() {
fmt.Println("proxy-server start")
server.InitProxyServer()
}
이 코드는 프로그램의 진입점으로, InitProxyServer()
함수를 호출하여 서버를 시작합니다.
3. server.go
package server
import (
"my-go-proxy-server/handler"
"net/http"
)
func InitProxyServer() {
mux := http.NewServeMux()
handler.InitDefaultHandler(mux)
handler.InitProxyHandler(mux)
err := http.ListenAndServe(":8081", mux)
if err != nil {
panic(err)
}
}
여기에서는 HTTP 요청을 처리할 ServeMux
인스턴스를 생성한 후, 기본 핸들러와 프록시 핸들러를 추가합니다.
4. default_handler.go
package handler
import (
"fmt"
"net/http"
)
func InitDefaultHandler(mux *http.ServeMux) {
mux.HandleFunc("/health", health)
}
func health(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "hello~")
}
기본 핸들러는 /health
경로로의 요청에 대한 응답을 정의합니다.
5. proxy_handler.go
package handler
import (
"context"
"crypto/tls"
"fmt"
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)
func InitProxyHandler(mux *http.ServeMux) {
mux.HandleFunc("/", handleProxy)
}
func handleProxy(w http.ResponseWriter, r *http.Request) {
host := getHost(r)
path := r.URL.Path
fmt.Printf("host: [%s], path: [%s]
", host, path)
var target *url.URL
if path == "/" {
target, _ = url.Parse("https://example.com") // redirect to your preferred target
} else {
u := fmt.Sprintf("https://example.com/search?q=%s", path[1:]) // sample search URL format
target, _ = url.Parse(u)
}
reverseProxy := httputil.NewSingleHostReverseProxy(target)
reverseProxy.Transport = &http.Transport{
DialTLSContext: dialTLS,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
reverseProxy.ServeHTTP(w, r)
}
func getHost(r *http.Request) string {
i := strings.Index(r.Host, ":")
if i > 0 {
return r.Host[:i]
}
return r.Host
}
func dialTLS(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := net.Dial(network, addr)
if err != nil {
return nil, err
}
host, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
cfg := &tls.Config{ServerName: host}
tlsConn := tls.Client(conn, cfg)
if err := tlsConn.Handshake(); err != nil {
conn.Close()
return nil, err
}
return tlsConn, nil
}
위의 핸들러는 기본 /
경로에 대한 모든 요청을 처리하며, 특정 경로에 따라 요청을 나누어 다른 URL로 전송합니다.
예제 실행 결과
서버를 실행한 후, http://localhost:8081
로 접근하면 설정한 도메인으로 리다이렉트됩니다.
추가적으로
이 코드에서는 기본적인 리버스 프록시 기능만 제공하므로 다음과 같은 기능을 추가할 수 있습니다:
- 에러 핸들링 향상
- 로깅 기능 추가
- 다양한 URL 패턴에 대한 포워딩 정책 추가
마무리하며
이번 포스트에서는 Go 언어로 리버스 프록시 서버를 구축하는 방법에 대해 알아보았습니다. 이 프록시 서버는 많은 실무 환경에서 유용하게 사용될 수 있습니다. 여러분도 직접 코드로 실습해 보며 더 깊이 있는 이해를 해보시기 바랍니다! 질문은 언제든지 댓글로 남겨주세요.
이 정보가 도움이 되었다면 공유해주시길 바랍니다! 다음 포스트에서 또 만나요!
'개발' 카테고리의 다른 글
파이썬을 이용한 텍스트 파일 데이터 처리와 분석 방법 (0) | 2024.11.12 |
---|---|
Go 언어로 ECHO 프레임워크를 이용한 JWT 인증 시스템 구현 방법 (1) | 2024.11.12 |
OpenSearch와 AWS SSO 연동으로 안전한 클라우드 환경 구축하기 (4) | 2024.11.12 |
파이썬으로 만드는 단어 빈도 계산기 튜토리얼 (5) | 2024.11.12 |
간단한 이메일 유효성 검사기 만들기 안내 (2) | 2024.11.12 |