본문 바로가기

go

[Golang] Proxy 환경 변수 http.ProxyFromEnvironment 대부분의 서비스는 어플리케이션이 직접 외부 인터넷과 통신하지 않습니다.특히 회사 내부망, 보안망 등 환경에서는 주로 아래와 같은 구조를 사용합니다.Application Proxy Server Internet 이러한 환경에서 서비스가 배포가 되며, 외부와 통신을 하려면 반드시 프록시 서버를 거치게 됩니다.그래서 단순히 HTTP 요청만 구현하는 것이 아니라, 현재 환경에서 프록시를 사용하고 있는지어떤 요청은 프록시를 거치고, 어떤 것은 거치지 않는지Proxy 운영 정책에 고려 사항이 있는지를 함께 고려해야 합니다. Golang에서는 표준 라이브러리 net/http에서 이를 통해서 기능을 제공하고 있습니다. 1. Proxy 환경변수Golang의 http.ProxyFromEnvironment 에서 .. 더보기
[Golang] io 패키지 MultiWriter, MultiReader 예제 백엔드 개발에서 데이터 스트림을 효율적으로 제어하는 것은 성능과 직결이 됩니다.io 패키지 활용 예제를 함께 살펴봅시다. 1. MultiWriter왜 쓰는가?로그를 남기거나, 파일을 업로드 할 경우, 동일한 데이터로 여러 일들을 함께 처리해야할 상황데이터를 두 번 읽거나 반복문을 사용하는 것 대신, "MultiWriter" 를 활용해 한 번의 쓰기 동작으로여러 목적지에 데이터를 전달 할 수 있습니다.즉 데이터를 한번 읽고, 여러 목적지에 동시에 쓰기 기능을 제공합니다.로깅 : 표준출력 및 파일 기록무결성 : 파일 업로드 및 해시(Checksum) 계산백업 : 주 저장소 와 보조 저장소 동시 저장- 예제 코드package mainimport ( "crypto/sha256" "encoding/hex" "fm.. 더보기
[Golang] io.Pipe 대용량 데이터를 처리할 때 slice나 구조체를 적절히 잘 사용하는 것도 좋지만,Go언어에서 제공하는 표준 라이브러라 "io.Pipe"를 사용한다면 "OOM"을 방지하는데 도움이 됩니다.1. io.Pipe왜 사용 하는가?보통 slice, buffer으로 데이터를 적재하고 이동시키는 방법은 데이터의 크기 만큼 RAM을 점유하기 때문에,OOM에 취약합니다.대신 io.Pipe는 데이터를 쌓아두지 않고, 생성된 데이터는 즉시 바로 목적지에 전달하는 실시간 통로를 제공합니다.데이터가 아무리 크더라도 전송 되는 동안에는, 설정된 버퍼만큼만 유지되며 속도도 빠릅니다.동작원리io.Pipe는 메모리 내부에서 Reader와 Writer가 연결된 동시식 통로를 만듭니다.Writer에서 데이터를 파이프로 넣으려고 하더라도,.. 더보기
[Golang] io 패키지 기초 1. io.Copy데이터를 원하는 목적지로 옮기는 표준 메서드왜 쓰는가? : 인메모리 폭주 방지 예 ) 1GB 데이터를 옮길 때 메모리를 1GB 사용하는게 아니라, 내부적으로 32KB 고정 버퍼만 사용해 데이터를 옮깁니다.데이터가 RAM에 쌓이지 않게 해 저사양 서버에서도 대용량을 처리 할 수 있도록 합니다.func copyDemo() { src := strings.NewReader("Hello, Go World!\n") var dst bytes.Buffer io.Copy(&dst, src)} 2. io.TeeReader데이터를 읽음과 동시에 다른 곳에 복사본 전달하는 T 자형 분기점 역할을 합니다.왜 쓰는가? : 일회성 데이터 재활용HTTP 요청의 바디처럼 한 번 읽으면 사라지는 데.. 더보기
[Golang] slog : Context Handler 패턴 Go 1.21 버전부터 추가된 slog 는 구조화된 로깅을 지원하며,특히 Handler 기반 구조를 통해 로깅 로직을 유연하게 확장 할 수 있는데요. 실무에서는 로그 추적을 위해서 다음과 같은 메타데이터를 남기는 경우가 많이 있습니다.request_idtrace_iduser_idserviceippath위 값들은 고유 값들로 각 요청과 종료의 범위, 흐름을 파악할 때 유용하게 사용이 됩니다.이 값을 매번 수동으로 넣는 방식을 사용하면 번거럽고, 누락하는 문제가 발생하기도 합니다.logger.Info("payment completed", slog.String("request_id", requestID), slog.String("user_id", userID),) 위 로그만 본다면 단순하고 어려울 것도 없지만.. 더보기
[Golang] net/url 패키지를 활용한 SSRF 방어 1. SSRF(Server-Side Request Forgery) 란?SSRF를 번역하면 "서버 측 요청 위조" 이며,공격자가 서버를 속여서, 서버가 의도하지 않은 주소로 HTTP 요청을 보내게 만드는 공격 방법 입니다.공격자는 서버의 권한을 이용해서 서버 내부망에 있는 다른 서버나, 서버 자산 등을 접근하려고 시도합니다.2. SSRF 왜 발생하는가?서버와 기능을 구현하다보면 서버가 외부 URL에 대신 접근해야하는 기능이 필요할 때가 있습니다.이미지 프록시/썸네일 생성 : 사용자가 입력한 프로필 이미지 URL을 서버가 다운로드 하여 리사이징 할때웹훅 알림 : 결제가 완료되면 사용자가 설정한 URL로 서버가 알림을 보낼 때외부 데이터 가져오기 : RSS 피드나 외부 API 문서를 URL을 통해서 불러올 때.. 더보기
[Golang] 자식 프로세스 생명 주기 관리 (Shutdown) 지난 포스팅에서는 간단한 서비스 Shutdown 로직에 대해서, 그 중에서 단일 프로세스 종료 절차 구현에 대해서 알아보았습니다.이번에는 자식 프로세스(Child Process)를 관리하는 부모 프로세스의 종료 구현에 대해서 알아보려고 합니다. 1. 프로세스 종료 방법자식 프로세스가 있는 부모 프로세스는 반드시 자식에게 종료가 완료 될 수 있는 시간을 제공해 주어야 합니다.이유는 만약 상위 부모 프로세스만 먼저 종료가 되고, 자식 프로세스는 종료가 올바르게 되었는지 아니었는지 확인이 제대로 안되면좀비 프로세스가 되어 서버 리소스를 계속 사용할 수 있습니다. 2. 3단계 에스컬레이션Sigterm : 자식에게 종료 신호를 보냅니다.Timout : 자식에게 종료 잘 될 수 있도록 유예시간을 줍니다.(만약 .. 더보기
[Golang] net/url 기초 API 호출을 위해 외부 URL을 생성하거나 들어온 URL 파싱할 때 쓰는 표준 라이브러리 "net/url"1. URL 구조체URL 구조체는 Scheme, Host, Path, Query 등으로 이루어져 있습니다.u := url.URL{ Scheme: "https", Host: "example.com", Path: "/search",} 2. Query 인코딩보통 그냥 하드코딩해서 쓰면 &,? 같은 특수 문자를 포함할 때 실수가 일어나는데,url.Value를 활용하면 실수를 줄이고 안전하게 URL를 만들 수 있습니다.q := url.Values{}q.Set("q", "go handbook")q.Set("page", "1")u.RawQuery = q.Encode()fmt.Println.. 더보기