구성은 이렇습니다.
프로젝트 구성
A 프로젝트: .NET 9 Console 프로젝트 (ConsoleAppFramework)
B 프로젝트: .NET 8 Class Library 프로젝트 (MiniExcel Nuget Package 설치)
C 프로젝트: .NET 8 Console 프로젝트 (CommandLineParser)
의존 관계
A → B
C → B
위와 같은 상황에서 A, C 프로젝트에서 B 프로젝트의 MiniExcel을 사용하는 기능을 호출할 예정입니다. 이 기능을 Func 라고 하겠습니다.
증상
A 프로젝트에서 Func를 호출하면 의도한대로 정상 동작합니다.
C 프로젝트에서 Func를 호출하면 정상 동작하다가 프로세스가 종료됩니다.
꼭 MiniExcel 기능을 호출할 때만 오류가 나며, 특정 Excel File을 읽는 부분 또는 Excel 을 DataTable로 만드는 QueryAsDataTable 함수에서 문제가 발생합니다. (이것도 특정이 안되고 매번 다른데 이유는 모르겠습니다.)
try-catch를 잡아도 안 잡히며, UnHandledException에도 안잡히고, Windows Event Viewer 에서도 오류로 안 잡힙니다.
해본 것
MiniExcel을 Nuget Package가 아니라 프로젝트를 Clone하여 직접 참조. (디버그 포인터에 들어오지 않고 종료되던 데서 그냥 종료됨)
.NET Assembly의 Lazy Loading 같은게 의심되는 것 같아서 AI에 질문 후 아래 내용을 프로젝트 파일에 추가
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
C 프로젝트에 같은 버전의 MiniExcel 패키지 참조
try catch나 UnHandledException에 잡히지 않는 것을 보면 코드가 문제 되는 것은 아닌 듯한데, 같은 파일을 A 프로젝트로 읽으면 정상동작이 되는 점이 의문스러운 부분입니다.
필요하시다면 추가 설명 남기겠습니다.
감사합니다.
1개의 좋아요
B의 누겟 패키지 버전을 한 단계 씩 롤백 해보는 것은 어떠실지요.
2개의 좋아요
의견 감사합니다. 제가 이걸 미처 못 적었네요. 말씀하신 방법도 조금은 해봤습니다.
Obsolete 직전 버전까지 3개가 있는데 3버전 다 C 프로젝트에서는 안되네요. A 프로젝트에서는 잘 됩니다.
1개의 좋아요
디버거 연결 상태에서 비정상 종료될 때 출력창에 표시되는 "exit code"를 확인해보셨나요?
The program '[26904] xxxx.exe: Program Trace' has exited with code 0 (0x0).
The program '[26904] xxxx.exe' has exited with code 0 (0x0).
2개의 좋아요
홀랭… '예외설정’창의 모든 예외를 체크해도 안되나요?
2개의 좋아요
답변 감사합니다.
디버깅 콘솔이 종료될 때 나오는 메세지가 아래와 같습니다.
{실행 파일 경로}(프로세스 706144)이(가) -1 코드(0xffffffff)와 함께 종료되었습니다.
디버깅이 중지될 때 콘솔을 자동으로 닫으려면 [도구] → [옵션] → [디버깅] > [디버깅이 중지되면 자동으로 콘솔 닫기]를 사용하도록 설정합니다.
이 창을 닫으려면 아무 키나 누르세요…
이걸 보니 -1 인 것…같습니다. 혹시나 싶어서 다시 해봤는데 0 이네요 …뭐지
{실행 파일 경로}(프로세스 727780)이(가) 0 코드(0x0)와 함께 종료되었습니다.
디버깅이 중지될 때 콘솔을 자동으로 닫으려면 [도구] → [옵션] → [디버깅] > [디버깅이 중지되면 자동으로 콘솔 닫기]를 사용하도록 설정합니다.
이 창을 닫으려면 아무 키나 누르세요…
1개의 좋아요
답변 감사합니다.
모든 예외를 전부 체크했지만 Exception에 걸리지 않네요…ㅠㅠ
2개의 좋아요
-1
이면 디버거 중단, 0
이면 정상 종료인데… A와 C의 코드는 동일한가요? await
같은걸 잘못 사용해서 정상 종료된 것이 아닐까 의심됩니다.
기초적인 것이지만 혹시 async Task Main()
에서 async Task
함수가 아닌 void Main()
에서 async void
함수가 호출되고 있는 상황은 아닌지요?ㅋ
5개의 좋아요
A, B는 제가 생성한 프로젝트이고, Microsoft.Extensions.DependencyInjection이 적용되어 있고, 기본 Microsoft.Extensions.Logging.Console이 적용된 상태입니다.
C는 다른 분께서 만드실 프로젝트이고 의존성 주입 없이 개발된 프로젝트이면서 Serilog 를 사용한 프로젝트입니다.
위에서 언급한 Func를 호출하는 것은 같지만, A는 Func를 하기 위해 사전에 서비스들을 AddSingleton 형태로 등록해 둔 상태입니다. (Service 내에 Field, Property 없으므로 Singleton으로 등록해도 독립적으로 동작 가능)
C의 경우 Microsoft.ExtentionsDependencyInjection이 없기 때문에 제가 객체들을 하나씩 만들어서 각 서비스마다 생성자의 인자로 넣어줬습니다. 이런 식입니다.
using ILoggerFactory loggerFactory = LoggerFactory.Create(builder =>
{
//builder.AddConsole();
builder.AddSerilog(logger);
builder.SetMinimumLevel(LogLevel.Information);
});
var gitBranchService = new GitBranchService(
logger: loggerFactory.CreateLogger<GitBranchService>());
var excelService = new ExcelService(
logger: loggerFactory.CreateLogger<ExcelService>());
var abcdService = new ABCDService(
logger: loggerFactory.CreateLogger<ABCDService>(),
excelService: excelService,
gitBranchService: gitBranchService);
var efghService = new EFGHService(
logger: loggerFactory.CreateLogger<EFGHService>(),
excelService: excelService,
efghService: efghService);
코드에서 보신 것처럼 이 과정에서 Serilog를 Microsoft.Extensions.Logging과 통합해야했기 때문에 LoggerFactory를 이용했습니다.
1개의 좋아요
아…A 프로젝트는 ConsoleAppFramework 기반이라 Program.cs 코드가 아래처럼 생겼습니다.
using A.Commands;
using B;
var app = ConsoleApp.Create()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddZLoggerConsole();
logging.SetMinimumLevel(LogLevel.Information);
})
.ConfigureServices(services =>
{
services.AddSingleton<ExcelService>();
services.AddSingleton<GitBranchService>();
services.AddSingleton<ABCDService>();
services.AddSingleton<EFGHService>();
});
app.Add<FilterCommand>();
await app.RunAsync(args);
C 프로젝트는 그냥 Top-Level 프로그래밍 형태…입니다. 말씀하신대로 이게 문제였을 수도 있을 것 같네요 ㄷㄷㄷㄷㄷㄷ 한번 트라이해보겠습니다. 이게 문제가 맞았으면 좋겠는데 맞으면 좀 허탈하고 웃긴 상황이네요.
async void 인 걸 async Task로 고치긴했는데…똑같이 오류가 발생하네요…ㅠㅠㅠ
죄송합니다. 이게 정답이네요…아 이런걸 놓치다니…
감사합니다…
4개의 좋아요
시간 아껴주셔서 감사합니다…
남의 소스도 당연히 제 기반이라고만 생각해서 뭐 온갖 프로젝트 설정부터해서 다 봐도 아무것도 차이점이 없는데 안되서 돌아버리는 줄 알았는데 진짜 기본이 정답이었네요…
정말 감사합니다. 킹갓마제스티충무공엠페러 @al6uiz 님!!!
다른 답변 주신 분들도 감사합니다…ㅋㅋ
허무
다시보니 이 부분이 힌트였을 수 있겠네요. 사실 옆자리 분께 과거에 이 소스 다루면서 전역으로 종료되는 타임아웃같은게 걸린 소스냐고 물어 봤었거든요…어쩐지 특정이 안되더라 ㅡㅡ;;;
4개의 좋아요
너무 허무했…습니다…ㅋㅋ 좋은 경험이라고 해 주셔서 감사합니다. 부끄럽네요…
2개의 좋아요
suwoo
7월 16, 2025, 1:06오전
14
가끔 보면 사소한 부분이 잘 안 보일 때가 있더라고요 ㅎㅎㅎ
옆 사람이랑 같이 보면 이런 부분에서 보완이 잘 되는 것 같습니다.
그래서 한때 2인 코딩이 유행했나 봐요.
5개의 좋아요