Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr

델파이에서 Try-Finally 블록을 어떻게 사용하면 리소스 여러개를 보호할 수 있는가?


Recommended Posts

마르코 칸투 (Marco Cantu)"Try-Finally Blocks for Protecting Multiple Resources in Delphi" 을 번역했습니다. (원문 작성: 2018년 1월, 최종 번역: 2023년 2월)

델파이 언어는 예외가 발생할 경우 리소스가 적절하게 해제되는 것을 확실하게 할 수 있도록 하는 표준 리소스 할당 패턴을 다른 많은 언어와 공유한다.  여기에서 리소스(resources)란 메모리 오브젝트, 파일, 운영 체제의 오브젝트와 핸들 등등을 의미한다. 델파이에서는 메모리 관리 고려라는 측면에서 , 가비지 컬렉터가 있는 다른 언어에 비해, 리소스 해제와 더 밀접하게 관련된다.

목차


1 오브젝트 1개를 보호하기

간단한 경우, 대부분 아래와 같은 코드를 작성할 것이다.

리소스를 할당한다 (allocate resource)
try
  리소스를 사용한다 (use resource)
finally
  리소스를 해제한다 (free resource)
end;

보다 구체적인 예문:

A1 := TTest.Create;
try
  A1.DoSomething;
finally
  A1.Free;
end;

여기까지는 좋다. 위 코드에서는, 생성자(constructor)가 실행되는 도중에 만약 에러가 발생하는 경우에, 델파이는 일부가 초기화된 오브젝트 (이것은 별도의 주제에서 다루기로 한다)의 파괴자(destructor)를 자동으로 실행할 것이므로 안전하다는 점을 알아두자.

 

2 오브젝트 2개를 보호하기: 코드를 이렇게 작성하면 안된다

이 글에서 집중하려는 문제는, 만약 리소스 2개를 할당(allocate)하고 폐기(dispose)하고 싶은 경우라면 코드를 어떻게 작성해야 하는 지를 살펴보는 것이다. 선택할 수 있는 여러가지 방법이 있다. 먼저, 그렇게 하면 안되는 (하지만, 주변에서 상당히 흔하게 보이는) 코드는 다음과 같다.

A1 := TTest.Create;
A2 := TTest.Create;
try
  A1.DoSomething;
  A2.DoSomething (A1);
finally
  A2.Free;
  A1.Free;
end;

위 코드는 만약 A2를 생성하는 코드가 실패하는 (많은 이유가 있을 수 있다) 경우에는, A1 오브젝트가 메모리에 남아있게 된다. 그렇다고 해서 2번째 오브젝트를 생성하는 코드를 아래와 같이 try 블록 안으로 옮기는 것 역시 좋지 않다.

A1 := TTest.Create;
try
  A2 := TTest.Create;
  A1.DoSomething;
  A2.DoSomething (a);
finally
  A2.Free;
  A1.Free;
end;

위 코드는 만약 A2 오브젝트의 생성자(constructor)가 호출되는 중에 실패하는 경우에는, 초기화되지 않는 오브젝트(로컬 오브젝트 참조 값은 기본이 undefinde 즉 정의되지 않음이다)를 Free 하려는 시도를 finally 블록 안에서 하게 된다 .

해법을 보자. 위 코드에서 A2 변수를 nil로 지정하고, A2 오브젝트의 리소스 생성 코드는 try 블록 안에서 넣는 방법이 있다 - finally 블록 안 있는 Free 코드가 실행될텐데, 이때 nil인 오브젝트에서 호출하는 Free는 아무런 효력이 없기 때문이다. 또는 A2 뿐만아니라 모든 오브젝트 참조를 nil로 지정할 수 있다. 그러면 단순하고 통일성을 유지할 수 있다. 또는 try 블록을 중첩하여 리소스를 각각 보호할 수도 있다.

3 오브젝트 2개를 보호하기: 3가지 해법 이야기

앞에 길게 이야기한 내용을 바탕으로 이 글의 요점으로 가보자. 방금 언급한 것처럼 하나의 코드 블록에서 사용되는 리소스 2개를 모두 보호하는 문제에 대한 해법은 적어도 3가지이다. 아래 그림은 RAD Studio R&D 아키텍트 중 한 명인 Bruneau Babet가 정리한 3가지 해법 그림을 가져온 것이다.

protecting2objects.png

어떠한 경우에도 리소스를 올바르게 보호한다는 측면에서 이 3개 해법 모두 옳다. 그러면 이 3가지 해법 각각의 장점과 단점은 무엇일까? 이 예문에서는 보호해야 할 리소스가 2개 이지만, 그 이상 즉 3개, 4개 또는 10개가 넘는 경우도 고려해야 한다는 점이 중요하다. 

4 그 중 어느 것을 선택할까?

첫 번째 해법은 try 블록을 중첩해 사용한다. 상당히 정돈되어 있지만 보다 더 장황하다(코드 줄이 더 많다). 보호해야 할 리소스가 더 많아지면 중첩도 더 많아지므로 짜증이 날 수 있다. 또한 try 블록을 처리하기 위한 런타임 비용 있다는 점도 약점이다. try 블록 처리 비용이 비록 작고 제한인 것은 분명하지만 그렇다고 해서 0은 아니다.

두 번째 해법은 코드 줄이 가장 적고 런타임 비용도 가장 적다. A2를 nil로 지정하는 코드만 추가하면 되기 때문이다. 보호해야 할 리소스가 많아져도 코드를 읽을 수 있다. 그러나 코드의 "균형이 맞지 않고" 이해하기에 다소 혼란스러울 수 있다.

세 번째 해법은 접근 방식이 두번째 해법과 같긴 하지만, (A1에) 기술적으로 쓸모없는 nil을 할당하는 코드를 추가했다. 그 결과 코드는 더 깨끗하고 균형이 잡힌다. 결국 더 읽기 쉬운 코드가 된다.

그래서 가장 좋은 해법은 무엇일까? 이것은 정말 말하기 어렵다. 나는 개인적으로 내 책에서 주로 #1을 사용했지만, Embarcadero는 라이브러리를 작성할 때 더 깨끗하고 빠른 코드(즉, #2 또는 #3)를 선호하는 경향이 있다. 물론 여러분의 의견은 무엇인지에 대해서도 관심이 있다.

이 댓글 링크
다른 사이트에 공유하기

  • 어드민 changed the title to 델파이에서 Try-Finally 블록을 어떻게 사용하면 리소스 여러개를 보호할 수 있는가?
  • Kori pinned this 토픽(기고/질문)
  • Kori unpinned this 토픽(기고/질문)

이 토의에 참여하세요

지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.

Guest
이 토픽(기고/질문)에 답하기

×   서식있는 텍스트로 붙여넣기.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   이전에 작성한 콘텐츠가 복원되었습니다..   편집창 비우기

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.