2025년 하반기의 목표했던 오픈소스 기여를 2026년 상반기에 성공했습니다.
어떻게 할지 정말 어렵다고만 생각해서 계속 미루고 있었는데,
'오픈소스 기여모임' 이라는 커뮤니티를 알게되어 가입하게 되었습니다.
오픈소스 기여를 처음으로 도전하는 사람들을 위해서 운영진분들이 많은 도움을 주셔서 수월하게 성공할 수 있었다고 생각합니다.
저는 line에서 개발하고 운영하고 있는 armeria라는 오픈소스에 새로운 기능을 추가했습니다.
armeria는 HTTP뿐만 아니라, gRPC, Thrift와 같은 다양한 통신 프로토콜을 지원하는 Netty위에서 돌아가는 고성능 비동기 프레임워크입니다.
우선 이번 PR에서는 가상포트를 랜덤으로 배정할 수 있는 API를 개발했습니다.
기존 armeria는 다음과 같은 코드로 서버를 실행시킨다면
fun main(){
val server = Server.builder().apply {
service("/foo") { ctx, req -> HttpResponse.of("Hello foo")}
}
.http(0)
.build()
server.closeOnJvmShutdown()
server.start().join()
}
SLF4J(I): Connected with provider of type [ch.qos.logback.classic.spi.LogbackServiceProvider]
08:13:50.854 [armeria-boss-http-*:51313] INFO -- Serving HTTP at /[0:0:0:0:0:0:0:0]:51313 - http://127.0.0.1:51313/
다음과 같이 51313이라는 포트번호를 할당받습니다.
하지만 virtualHost에 0이라는 포트를 할당한다면
val isRandomPort = System.getenv("IS_RANDOM_PORT").toBooleanStrict()
fun main(){
val firstHost = if (isRandomPort) 0 else 8080
val secondHost = if (isRandomPort) 0 else 8081
val server = Server.builder().apply {
http(firstHost)
virtualHost(firstHost).apply {
service("/foo") { ctx, req -> HttpResponse.of("Hello, foo!")}
}
http(secondHost)
virtualHost(secondHost).apply {
service("/bar") { ctx, req -> HttpResponse.of("Hello, bar!")}
}
}
.build()
server.closeOnJvmShutdown()
server.start().join()
}
> Task :server:run FAILED
SLF4J(I): Connected with provider of type [ch.qos.logback.classic.spi.LogbackServiceProvider]
Exception in thread "main" java.lang.IllegalArgumentException: port: 0 (expected: 1-65535)
at com.linecorp.armeria.internal.shaded.guava.base.Preconditions.checkArgument(Preconditions.java:191)
at com.linecorp.armeria.server.ServerBuilder.virtualHost(ServerBuilder.java:1734)
at com.gitlab.davinkevin.experimentations.armeria.grpc.MainKt.main(Main.kt:15)
at com.gitlab.davinkevin.experimentations.armeria.grpc.MainKt.main(Main.kt)
FAILURE: Build failed with an exception.
virtualHost 파라미터에 1 미만의 값이 들어갈 수 없어서 다음과 같은 에러를 반환합니다.
0을 허용한다고 하더라도, 2개 이상의 virtualHost를 활용할 경우에는 둘 다 virtualHost(0), virtualHost(0)이기 때문에 구분할 수 없게 됩니다.
랜덤포트를 많이 활용하는 CI환경에서 이러한 문제가 일어나지 않도록 virtualHost에서 랜덤포트를 활용할 수 있는 기능을 추가했습니다.
ServerBuilder.virtualHost(int)라는 메서드를 보완하여 virtualHost(ServerPort)와 같은 메서드를 구현해 다음과 같은 문제를 해결했습니다.
덕분에
ServerPort port1 = new ServerPort(0, SessionProtocol.HTTP);
ServerPort port2 = new ServerPort(0, SessionProtocol.HTTP);
Server server = Server.builder()
.port(port1)
.virtualHost(port1)
.service("/foo", (ctx, req) -> HttpResponse.of("foo"))
.and()
.port(port2)
.virtualHost(port2)
.service("/bar", (ctx, req) -> HttpResponse.of("bar"))
.and()
.build();
와 같은 방식으로 2개 이상의 가상포트를 활용해서 서버를 실행시키는게 가능해졌습니다.
실제 매핑된 포트번호는 ServerPort에서 actualPort를 조회해서 확인할 수 있게 되었습니다.
https://github.com/line/armeria/pull/6603
Add VirtualHost support for random ports (#6410) by junjunclub · Pull Request #6603 · line/armeria
Motivation Currently, using virtualHost(0) throws an IllegalArgumentException: java.lang.IllegalArgumentException: port: 0 (expected: 1-65535) This is problematic for CI environments where random p...
github.com
위 링크는 제가 올린 PR입니다.
이번 경험을 통해서 많은 것들을 배웠지만, 그 중 3가지 정도를 정리해보려고 합니다.
1. 기초지식(자료구조)이 매우 중요하다.
제가 요청을 라우팅하는 하는 부분을 구현하면서, 초기에는 2중 포문으로 코드를 작성했는데요.
이 코드는 클라이언트에서 요청이 들어올 때 마다 호출하는 코드였기에, 메인테이너가 최적화가 필요하다고 안내해주었습니다.
그래서 서버가 실행될 때 실제 포트와 가상 포트를 매핑해주고, 이를 ' virtualHostAndPortMapping' 이라는 Map에 저장해둡니다.
이후 요청이 들어올 때 마다 이 Map을 조회해서 O(1)의 시간복잡도로 처리할 수 있었습니다.
자료구조와 알고리즘에 대한 이해도가 높으면 높을수록 오픈소스 기여에 조금 더 유리하겠구나. 라고 생각했습니다.
2. Maintainer들은 우리들을 도와주는 사람이다.
처음에 메인테이너들을 되게 어렵게 생각하고 댓글로 제 의견을 작성하는게 정말 어렵게 느껴졌었습니다. (막 혼날 것 같고 그랬어요...) 그치만 시간이 지날수록 메인테이너들로부터 존중받는듯한 느낌이 들었습니다.
의견을 나누다가 이 이슈가 처음 기여에 도전하는 사람에게 어려울 수 있을 것이라는 안내도 해주고, 메인테이너가 생각하기에 좋은 접근법을 제시해줘서 사고방식과 코드 작성 부분에 있어서도 큰 도움을 받았습니다.
마무리가 되어갈 때 쯤에는 나름 티키타카가 잘 이루어지지 않았나! 라고 스스로 생각해봅니다....
그 분 의견에 반대(?)까지는 아니더라도 이런 부분이 걱정이 된다는 의견도 냈었고, 그 분 역시 이러한 제 의견을 잘 반영해주셨습니다!
3. 테스트 코드의 중요성
이렇게 거대한 오픈소스에서는 코드들이 다양한 곳에서 활용되고 있기 때문에 기존 코드를 수정하기 위해선 많은 조사와 공부가 필요합니다. 저 역시 기존 코드를 수정했다가 발생한 문제가 몇가지 있었는데요, 이 문제를 빠르게 인지할 수 있게 해주고 해결할 수 있도록 도와준게 바로 '탄탄한 테스트 코드' 입니다. 코드 수정 이후 다른 코드에서 문제가 발생해 테스트 실패가 발생했었고, 실패한 테스트를 근거로 어떤 부분이 문제인지 인지할 수 있었기 때문에 빠르게 원인을 파악하고 수정할 수 있었습니다.
이 글을 보시고 오픈소스 기여에 도전하시는 분들은 꼭 테스트 코드를 잘 작성하셔서 저 같은 실수를 하지 않으시길 바랍니다 ㅎㅎ...
지금은 line에서 개발하고 있는 central dogma와 apache에서 운영하는 sea tunnel이라는 오픈소스에 이슈를 할당받아 문제를 해결하고 있습니다.
해보기 전에는 매우 어렵다고만 생각했는데, 해보니 어떻게 해야할지 대충 감이 오는 것 같습니다 ㅎㅎ
저와 함께 고군분투해준 동료들에게 감사인사를 끝으로 글을 마무리하겠습니다!
'오픈소스' 카테고리의 다른 글
| Apache / SeaTunnel 오픈소스 기여후기 (open source contribute) (0) | 2026.05.04 |
|---|