티스토리 뷰

C#

폴더관리 프로그램

takim 2022. 10. 20. 21:46

개요

이 프로그램을 만든 이유

전 직장 다닐 때 FTP로 이미지 저장 시 날짜 폴더를 자동으로 만들 필요가 있었습니다.

다른 현장들은 한개의 폴더에 이미지 명으로 관리 했었지만 고객사에서 날짜 폴더를 만들고 

6개월 전 이미지는 자동으로 지워달라는 내용의 요구가 있었습니다.

 

초기에는 별다른 설정없이 자동으로 실행되게 해두었는데 쓰다보니 다른 현장에서도 사용할 필요가 있어 설정하는 것도 추가 했었는데요 (폴더 생성 시작 및 중지, 삭제 시작 및 중지, 최소화 할 경우 notify icon으로 표시)

 

마지막 수정이 2020년 6월 이었는데 프로그램 실행하고 몇달이 지나면 폴더가 제대로 안 만들어 진다는 이야기를 들었습니다. 그때 당시에는 왜 그런지 파악하지 못해서 다른 방식으로 해결 했었습니다.

 

문제를 수정하다..

윈도우에 FolderWatcher 라는 라이브러리가 있었습니다.

그래서 그걸 활용해서 FTP로 이미지 저장되는 위치는 한곳으로 지정해 두고 이미지가 들어왔을 때 Folder에서 파일이 들어 왔다는 이벤틀를 받아서 이미지를 날짜별로 분류한 폴더에 옮기는 것을 했습니다.

 

기존 작업에서 bmp 이미지로 원본이미지가 5MB, 2MB가 되는데 하루에 이미지가 1만~4만개가 쌓이게 되어 용량 문제가 있었습니다. 그래서 이미지 저장은 jpg로 변환하는 방식을 채택했습니다.

 

 

그래도 문제가 있다...

이 앞까지 이야기가 2021년 2월까지 이야기입니다.

그 뒤에도 이미지가 누락 되는 문제가 발생 했었습니다.

알아낸 이유로는 초당 6개의 이미지가 들어오는데 허브의 초당 전송속도가 빠르지 않아서 다음 이미지가 덮어 씌여지는 문제도 있었습니다.

그걸 알아내고 이미지 파일명이 동일하지 않게하고 초당 6개 들어오는 것을 3개로 줄여서 확인 했는데도 근본적인 해결이 되지 않았습니다. 기존에 이미지 누락이 4만개 중 1천개에서 40개로 줄어든 정도 였습니다.

수치로는 기존 2.5% 누락이 발생 되던걸 하드웨어 교체(허브 교체) 및 트래픽 감소를 했음에도 0.1%씩 이미지 누락이 발생 했습니다.

 

시간 순으로 정리하자면

1. 이미지 누락이 하루에 1천개 정도 누락 발생

 

2. 초당 이미지 6개 이던 것을 3개로 변경 -> 400개 정도 누락 발생

 

3. 허브 스펙을 확인하고 변경(허브 스펙에 의문을 품게 된 계기 : 2개의 라인이 있었는데 1개의 라인에서는 40개정도만 누락 발생 했는데 다른 라인은 10배 넘게 차이가 나서 스펙에 의문이 생김)

 

4. 허브 스펙을 40개 정도 이미지 누락 발생하는 곳이랑 동일하게 변경

 

5. 2개 라인 전부다 40개 정도 이미지 누락 발생 오차는 있었습니다. 10개 가량 평균 40개 정도 였습니다.

 

※ 위 3번 4번에서 허브 스펙 변경하면 문제 해결 될것이라 단정 했던 이유는 제품 생산이 당일 8시 ~ 익일 8시까지여서 제가 확인한 날짜에 당일에는 이미지 누락이 발생하지 않아서 이미지 누락이 없는 것으로 확인 했었습니다.

 

그래서 다시 정리 하자면

6. 누락 없는 라인에 허브가 A라고 할때 이미지 누락을 확인하기 위해 

https://github.com/takim52/SHT_TEST

 

GitHub - takim52/SHT_TEST: Share SHT program source

Share SHT program source . Contribute to takim52/SHT_TEST development by creating an account on GitHub.

github.com

- Check Count - 라고 적혀 있는 프로그램 사용해서 확인 했습니다.

 

7. 이거의 문제는 제가 받은 제품 리스트 정보가 당일 8시부터 ~ 익일 8시까지인데 익일 폴더를 검사안하는 오류를 범해서 누락이 없는 라인이라고 생각 했었습니다.

 

8. 그래서 누락이 있는 라인 허브 B를 A로 교체하고나서 익일 폴더를 확인하니 제가 테스트를 잘못 한 것을 알게 되었습니다.

 

 

 

고객사에서는 그정도면 많이 나아진거 같으니 괜찮을 거 같다고 하였습니다.

제가 생각하기에도 많이 줄였으니 괜찮지 않을까하고 생각 했는데 만약에 누락된 이미지가 꼭 필요한 상황이 나오면 어떻게 해야하는가와 근본적인 문제는 무엇인지 궁금했습니다.

 

그래서 코드를 찬찬히 확인하니 문제가 있었습니다.......😢😢😢😢😢😢😢😢

 

문제가 된 코드 확인

2020년 버전 폴더 관리 프로그램

폴더 생성관련된 반복작업을 BackgroundWorker를 사용해서 계속 반복하도록 했었습니다.

그런데 이게 문제가 된 것으로 보였습니다.

처음에는 문제가 안되었던 이유가 폴더 생성만 작업 할 때는 문제가 없을 수 있으나 다른 BackgroundWorker를 2개 더 사용 하면서(폴더 삭제, 특정 폴더 파일 삭제) 문제가 되었던 것으로 보입니다.

Thread.Sleep도 한 몫 한 것으로 보이구요..

 

BackgroundWorker와 Task 처럼 ThreadPool에 요청을 보내는 방식으로 멀티스레딩을 구현할 때 주의해야 할 점은 시간을 오래 잡아 먹는 작업은 한번에 맡겼는가라고 생각 합니다.

 

이건 제가 Task 관련한 글 확인 해보시면 이해에 도움이 되실 거 같습니다.

https://takim0070.tistory.com/16

 

Task 관련 테스트

Task의 유용성에 관하여 BackgroundWorker를 사용하다가 Task라는게 있어서 확인 해보니 보다 이해하기 쉽고 사용성도 편리하였습니다. Task와 BackgroundWorker와 Thread, 셋 중에 어떤걸 쓰는게 좋을지에 관

takim0070.tistory.com

 

Thread를 그냥 만들고 Thread.Sleep을 하면 시간은 오래 걸리지만 Thread가 개별로 진행되는 느낌을 제가 받게 해 주었습니다. 물론 윈도우에서 시분할을 엄청 잘 해주었겠지만요

그런데, Task로 테스트 했을 때 Thread.Sleep을 하니 다음 Task가 작업 진행이 되지 않았습니다.

이 걸 보고 제가 내린 결론은 ThreadPool에서 Process마다 할당하는 Thread가 제한되는건지 아니면 단순히 Thread.Sleep 때문에 다른 Thread에도 문제가 생긴거라고 판단하여 확실한 것은 Task나 BackgroundWorker를 사용할 때는 오래걸리는 작업이나 Thread.Sleep을 사용하지 않아야 한다는 결론을 내렸습니다.

 

저의 뇌피셜이지만 베스트 프랙티스는 Task, BackgroundWorker는 시간이 엄청 오래 걸리지 않고 '한번만' 작업하면 되는 것을 맡기고 '여러번' 작업해야하는 경우 Thread를 별도로 생성해서 멀티스레딩을 해줘야 한다 입니다.

 

결론은

BackgroundWorker를 목적과 달리 사용 했습니다.

코드를 수정 한다면 이렇게 수정하는게 좋아 보입니다.

이러면 ThreaPool에는 폴더 생성, 폴더 삭제, 특정 파일만 삭제라는 단순한 작업만 있게 됩니다.

 

제가 별도로 만든 Thread나 WinForm의 Control인 Timer를 사용하여 프로그램 시작부터 종료까지 계속 반복하면서 폴더 생성 설정이 되어 있다면 폴더 생성하는 Task를 실행 해주는 방식으로 작성하면 문제없이 작동 할 것으로 예상 됩니다.

 

 

2021년 버전 폴더 관리 프로그램

이때에 BackgroundWorker가 뭔가 문제가 있다는걸 의심은 했는데 확신이 없어서 계속 사용 했었습니다.😓😓😓😓

그래도 그나마 다행인 거는 FolderWatcher에서 이벤트 넘어 올때마다 ThreadPool에 넘기는 방식이라 그나마 나은 방식이긴 했었습니다.

 

여기에서 코드에서는 딱히 문제는 없습니다. 지금 보니까 고치고 싶은 부분은 엄청나게 많은데 그래도 작동에는 이상이 없는 코드라고 할 수 있습니다.

 

하지만 제가 간과한게 있었습니다.

만약에 파일 전송이 완료 되지 않았는데 FolderWatcher에서 File이 생겼다고 인식하면 어떻게 될까 였는데 맞았습니다.

테스트를 해보았습니다.

 

- 기존 전제 : 허브 교체로 인해 전송속도가 빨라져서 하루에 대략 40개(10개 오차 있음) 발생 -

1. 초당 10개의 5MB 이미지 전송

2. Thread를 만들어서 sleep(1000ms ~ 최대 3000ms까지 변경하며 누락 안 발생 하는 수준까지) 처리(원래는 BackgroundWorker로 했지만 Thread.Sleep을 사용하기 위함)

3. 이미지 누락 없음

4. sleep 없이 처리 

5. 기존처럼 하루에 40개 정도 누락 발생

 

이걸로 무엇이 문제인지 명확하게 알게 되었습니다.

FolderWatcher는 파일의 상태를 확인 할수 없었습니다. 그래서 이미지가 전송중일 때 이미지를 다루려고 하다가 문제가 발생했었습니다. 이미지는 복사 이동이 성공하거나 실패하거나 무조건 삭제를 하다보니 어떻게 할 방법이 없었습니다.

 

결론은 FTP Server를 직접 구성하면 파일 전송 완료 이벤트를 받을 수 없을까 했는데 FTP Client는 샘플 코드가 있는데 Sever는 좀처럼 코드가 없었습니다. 그래서 나중에 기회가 된다면 FTP Server 구성하는 방법에 대해 공부 해볼 예정 입니다.

잠깐 확인 해본 걸로는 TCP로 연결을 받는 식으로 되어있는 예제는 확인 했습니다. 아무래도 일반 FTP는 HTTP이다 보니 그 아래 계층인 TCP로 연결 하는 것으로 보입니다.

https://www.codeproject.com/Articles/380769/Creating-an-FTP-Server-in-Csharp-with-IPv6-Support

 

Creating an FTP Server in C# - with IPv6 Support

An introduction into creating a working FTP server in C# using the RFC specification.

www.codeproject.com

 

임시방편

그래도 문제가 있는 프로그램을 그대로 둘 수 없어서 이미지 누락없이 작동될 수 있도록 수정 했습니다.

Timer를 사용해서 구성 했습니다. (파일은 폴더에서 싹 긁어서 이동 시키는 방식으로 바꿨습니다.-> 에러나면 그 파일은 넘어가고 다음 Timer 때 이동 시키게 해 두었습니다.)

이때까지도 Timer가 중복으로 진행되면 어떡하지 하는 그런 불안감에 bWatcherRunning(bool) 이걸 체크하게 해 두었습니다😓😓😓😓😓😓

이때 이후로는 더 이상 이미지 누락은 발생하지 않았습니다.

 

 

 

마무리

폴더 관리는 여기서 마치겠습니다.

하지만.... 코드가 너무 너저분하고 변수 이름들이 너무 제 마음대로이고 함수가 다른 사람들이 사용한다면 잘못 사용할 염려가 있지만 지금 당장은 이대로 두겠습니다. 차차 개선 해 나가야지요!!

'C#' 카테고리의 다른 글

메모리 스트림 사용에 관해  (0) 2021.10.19
Task와 Thread와 BackgroundWorker의 관해서  (2) 2021.09.02
Task 관련 테스트  (0) 2021.07.20
C# - BackgroundWorker에 관하여  (0) 2021.06.28
C#의 역사  (0) 2021.06.20
댓글