매개변수 (컴퓨터 프로그래밍)
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
매개변수는 함수 정의에 사용되는 변수이며, 전달인자는 함수 호출 시 함수에 제공되는 값이다. 프로그래밍 언어에 따라 매개변수와 전달인자는 동일하거나 다른 의미로 사용될 수 있다. 매개변수에 값을 할당하는 방식인 "인수 전달"은 평가 전략에 따라 달라지며, 값 전달, 참조 전달, 이름 전달, 지연 평가 등의 방식이 있다. 또한, 기본 전달인자, 가변 길이 전달인자 목록, 명명된 매개변수, 출력 매개변수와 같은 고급 매개변수 기법이 존재한다.
매개변수(parameter)와 전달인자(argument)는 종종 섞어서 쓰이기도 하는데, 이 경우 문맥에 따라 의미를 달리해서 해석되기도 한다. 하지만 엄밀히 말해서 ''매개변수''는 함수의 정의부분에 나열되어 있는 변수들을 의미하며, ''전달인자''는 함수를 호출할 때 전달되는 실제 값을 의미한다.[5] 이같은 의미를 명확히 하기 위해 매개변수는 '''변수'''(variable)로, 전달인자는 '''값'''(value)으로 보는 것이 일반적이다.
C 언어로 구현된 아래의 프로그램에서 `sales_tax`는 함수의 이름이며, 이 함수가 가지고 있는 `price`라는 이름의 변수가 바로 매개변수이다. `price` 매개변수의 타입은 부동소수점 자료형인 `double`이며, 이 함수의 반환 타입 또한 `double`이다.
함수 호출 시 전달인자를 매개변수에 할당하는 방식을 '평가 전략'이라고 한다. 매개변수에 인수를 할당하는 정확한 메커니즘은 "인수 전달"이라고 하며, 이는 해당 매개변수에 사용되는 평가 전략에 따라 달라진다.[5]
2. 매개변수와 전달인자
매개변수는 함수의 정의 부분에서 볼 수 있으며, 전달인자는 함수를 호출하는 부분에서 볼 수 있다. `f(x) = x*x`와 같은 함수 정의에서 변수 'x'는 매개변수이고, `f(2)`와 같은 함수 호출에서 값 '2'는 전달인자이다.
C 언어로 구현된 아래 프로그램에서 "sales_tax"는 함수의 이름이며, 이 함수가 가지고 있는 "price"라는 변수가 매개변수이다.
```c
double sales_tax(double price)
{
return 0.05 * price;
}
```
위와 같이 함수를 정의한 후, `sales_tax(10.00);`과 같이 함수를 호출할 수 있다. 이 예제에서 sales_tax 함수를 호출하면서 숫자 10.00을 전달인자로 전달했으며, 10.00이 price라는 변수에 대입되고 sales_tax 함수는 이를 이용하여 결과값을 계산하게 된다.
2. 1. 매개변수 목록과 전달인자 목록
함수 정의에서 매개변수들을 나열한 것을 '매개변수 목록(parameter list)'이라 하고, 함수 호출 시 전달인자들을 나열한 것을 '전달인자 목록(argument list)'이라 한다.[5][6]
일반적으로 함수는 매개변수의 개수에 제한이 없으며, 매개변수가 하나도 없을 수도 있다. 함수가 매개변수를 가질 경우, 각각의 매개변수에 대한 정의를 나열해 놓은 것을 '매개변수 목록'이라고 한다.
함수를 호출하는 부분에서 전달인자를 나열해 놓은 것을 '전달인자 목록'이라고 한다. 전달인자는 함수가 호출될 때 제공되는 값들을 말하며, 함수 정의의 한 부분으로 바뀌지 않는 매개변수와는 달리 호출할 때마다 값이 바뀔 수 있다.
다음은 C 언어로 작성된 함수를 통해 차이점을 보여주는 예시이다.
int Sum(int addend1, int addend2)
{
return addend1 + addend2;
}
함수 ''Sum''에는 ''addend1''과 ''addend2''라는 두 개의 매개변수가 있다. 이 함수는 매개변수로 전달된 값을 더하고, 그 결과를 서브루틴 호출자에게 반환한다.
''Sum'' 함수를 호출하는 코드는 다음과 같다.
int value1 = 40;
int value2 = 2;
int sum_value = Sum(value1, value2);
변수 ''value1''과 ''value2''는 값으로 초기화된다. 여기서 ''value1''과 ''value2''는 모두 ''Sum'' 함수의 전달인자이다.
런타임에, 이러한 변수에 할당된 값은 전달인자로 함수 ''Sum''에 전달된다. ''Sum'' 함수에서 매개변수 ''addend1''과 ''addend2''가 평가되어 각각 전달인자 40과 2가 생성된다. 이후 전달인자의 값이 더해지고 결과가 호출자에게 반환되어 변수 ''sum_value''에 할당된다.
3. 사용 예
```c
double sales_tax(double price)
{
return 0.05 * price;
}
```
이렇게 함수를 정의한 후, 다음과 같은 방법으로 함수를 호출할 수 있다.
```c
sales_tax(10.00);
```
이 예제에서 `sales_tax` 함수를 호출하면서 숫자 10.00을 인자로 전달해 주었다. 따라서 10.00이 `price`라는 변수에 대입되고, `sales_tax` 함수는 이를 이용하여 결과값을 계산하게 된다. `sales_tax` 함수 내부에서 `{}`로 둘러싸여진 부분에서 `0.05 * price`는 `price` 값에 0.05를 곱하라는 의미이며, `return`은 해당 함수가 `return` 뒤에 나오는 `0.05 * price`의 계산 값을 반환하라는 의미이므로, 최종적인 결과는 0.50이 된다.[21]
4. 평가 전략
4. 1. 값 전달 (Call by Value)
값 전달(call by value영어)은 실인수로서 변수를 전달하더라도 그 값만 전달되는 방법이다.[5] 즉시 값이나 복잡한 식을 전달하는 것도 가능하며, 식의 평가 결과가 전달된다. 값 전달에서는 독립적인 새 변수가 함수 내에 준비되어 원래 값이 복사되므로, 변수를 전달하더라도 원래 변수는 변경되지 않는다.[5]
이는 "함수가 부작용을 가지지 않는다"는 관점에서 계산 중심 언어에서 바람직한 동작이다. 대입 개념이 없는 함수형 프로그래밍 언어에서는 인수가 반드시 값으로 전달된다고 생각할 수 있다(대입이 없으면 복사할 필요도 없다).
C 언어, ML, APL, Scheme, Java 등이 값 전달 방식을 채택한다. C 언어는 값 전달만 지원하지만, 변수의 포인터(메모리 주소)를 얻을 수 있어 변수의 포인터를 값으로 전달하여 원래 변수를 변경할 수 있다. 배열이나 구조체의 일부분을 참조하는 코드도 오프셋 계산을 통해 쉽게 작성할 수 있다.[5]
그러나 이는 실제 변수 영역을 벗어난 부분까지 참조할 수 있게 하므로, 값 전달을 통한 참조 전달 에뮬레이트일 뿐이다. 참조 전달을 지원하는 언어에서도 내부적으로 유사한 조작을 하지만, 이는 언어의 보호를 받는 참조이다.[5]
4. 2. 참조 전달 (Call by Reference)
'''참조 전달'''(call by reference)은 실인수의 참조(메모리 주소)를 전달하는 방식이다.[23] 함수 내에서 매개변수를 변경하면 원래 변수에도 영향을 미친다. 이는 언어 차원에서 자동 수행된다. (\[\[C (프로그래밍 언어)|C 언어]]처럼 명시적으로 주소 연산자를 사용하는 것은 참조 전달이라고 부르지 않는다.)
C++, C#, 파스칼 등에서 참조 전달을 지원한다.[5]
참조 전달에서 말하는 "참조"와 특정 언어에서 "참조"라고 불리는 것이 반드시 같지 않다는 점에 주의해야 한다. 예를 들어, Java는 참조형을 다루기 위한 'Java의 "참조"'를 가지고 있지만, 이는 파스칼 등의 포인터에 상당하며, '참조 전달의 "참조"'와는 개념이 다르기 때문에 'Java의 "참조"'를 전달한다고 해서 참조 전달이라고 할 수 없다. C 언어의 "포인터의 값 전달"과 같다[24] . 이는 Java의 참조형과 유사한 참조형과 Java의 기본형에 가까운 값형을 가진 C#을 보면 이해하기 쉽다. C#에서는 특별히 지정하지 않으면 참조형도 값형도 값 전달되지만, 인수에 `ref` 또는 `out`을 사용함으로써 참조 전달로 할 수 있다. 'C#의 값형'을 전달하므로 값 전달, 'C#의 참조형'을 전달하므로 참조 전달이 되는 것은 아니다.
값 전달과 비슷하게, 복사본을 전달하고 함수/서브루틴에서 반환할 때 원래 변수에 변경 결과를 다시 복사하는 방법도 있다 (이는 변수의 공유(별칭)나 재귀 호출이 있으면 이상한 결과가 나올 수 있다). PL/I에서는 어느 방법으로 구현해도 좋다고 규정되어 있다.
원시적인 언어인 FORTRAN은 기계어의 주소 조작을 반영한 참조 전달만을 가지고 있었다. 이는 특히 call by index라고 불린다.
4. 2. 1. 포인터 전달 (Call by Address)
C 언어나 C++가 가지는 값은 객체에 대한 참조(메모리 주소)이며, 후술할 '''참조 전달'''의 참조와 비슷한 성질을 가진다. 이 때문에 포인터 변수를 값으로 전달하면 값 전달이면서 참조 전달과 비슷한 효과를 얻을 수 있다. 그래서 포인터(=메모리 주소)를 값으로 전달하는 것을 단순한 값 전달과 구분하여 '''포인터 전달'''이라고 부르기도 한다.[5]
C 언어는 값 전달만 지원하지만, 변수의 포인터(메모리 주소)를 얻는 것이 가능하기 때문에, 변수의 포인터를 값으로 전달하여 원래 변수를 변경할 수 있다. 오프셋 계산을 통해 배열이나 구조체의 일부분을 참조하는 코드도 쉽게 작성할 수 있다.
하지만 이는 실제 변수 영역을 벗어난 부분까지 참조할 수 있으므로, 어디까지나 값 전달에 의한 참조 전달의 에뮬레이트이다. 참조 전달을 지원하는 언어에서도 내부적으로는 유사한 조작을 하고 있지만, 그것은 어떤 의미에서 언어의 보호를 받는 참조가 된다.
4. 2. 2. 변수 전달 (Call by Variable)
변수 전달(Call by Variable)은 변수 자체(좌변값)를 전달하는 방식이며, 가인수에 대한 조작이 실인수(전달된 변수)에 직접 영향을 미친다.[23]
대부분의 언어에서는 반환값으로 하나의 값만 반환할 수 있다. 하지만 데이터베이스 검색 등에서 검색 여부와 검색된 값을 모두 알려야 하는 경우, 검색 여부는 반환값으로 하고 검색 결과는 인수를 변경하는 방식으로 사용할 수 있다.
참조 전달(Call by Reference)은 변수 전달의 구현 수단 중 하나로 볼 수 있다.[23] 참조 전달은 변수에 대한 참조(주소 정보)를 전달하는 방식이다. (이는 언어 차원에서 자동 수행된다. C 언어처럼 주소 연산자를 명시적으로 사용하는 것은 참조 전달이라고 부르지 않는다.)
값 전달과 비슷하게, 복사본을 전달하고 함수/서브루틴에서 반환될 때 원래 변수에 변경 결과를 다시 복사하는 방법도 있다. (이는 변수의 공유(별칭)나 재귀 호출이 있는 경우 예상치 못한 결과가 발생할 수 있다.) PL/I에서는 두 가지 방법 중 어느 것으로 구현해도 좋다고 규정한다.
FORTRAN은 기계어의 주소 조작을 반영한 참조 전달만 지원했다. 이는 call by index라고도 불린다.
변수 전달을 지원하는 다른 언어로는 파스칼, Perl, C++, C#, Quick BASIC 등의 구조적 BASIC 등이 있다.
변수 전달에서 함수/서브루틴에 실인수로 변수 외(우변값)를 전달했을 때 어떻게 되는지는 언어마다 다르다.
파스칼의 프로시저(`procedure`)나 함수(`function`)에서는 원시 타입(`integer`, `real` 등)의 값 전달과 변수 전달을 모두 수행할 수 있다. 변수 전달의 경우, 프로시저/함수의 인수에 `var`를 붙인다.
```pascal
{ 프로시저 swap 내에서 a, b의 값을 바꾼다.
sample의 i, j는 변수 전달되며, a와 i, b와 j는 같은 주소를 가리키므로,
i, j의 값은 바뀐다. }
procedure swap(var a,b:integer); { var를 붙이면 변수 전달 }
var tmp:integer;
begin
tmp := a; a := b; b := tmp
end;
procedure sample();
var i, j:integer;
begin
i := 5;
j := 10;
swap(i, j);
... { i는 10, j는 5가 된다 }
end;
4. 3. 이름 전달 (Call by Name)
ALGOL에서 채택된 특징적인 기능 중 하나이다. 이름 넘겨주기는 값도 참조도 아닌, 식이 그대로 전달된다. 기본적으로는 참조 넘겨주기처럼 동작하지만, 식을 참조할 때마다 값을 계산하여 가져오는 것이 특징이다. C 언어의 프리프로세서의 매크로 전개와 비슷하지만, 인수와 지역 변수가 충돌하지 않도록 배려한다.[22]
다음은 이름 넘겨주기의 특징적인 동작을 보여주는 예시이다.
```
swap(x,y) {
tmp = x;
x = y;
y = tmp;
}
```
위 예시에서 `x=i, y=a[i]`라는 "식"을 전달한다고 가정하고, `i=2`였다고 하면 다음과 같이 동작한다.
이러한 복잡성 때문에, ALGOL 외에 이름 넘겨주기가 채택된 사례는 거의 없다.[22]
4. 4. 지연 평가 (Lazy Evaluation)
하스켈과 같은 지연 평가형 함수형 프로그래밍 언어에서 볼 수 있는 형태로, 값이 실제로 필요해질 때까지 계산을 수행하지 않는 방법이다. 개념상으로는, 계산 방법을 지연시킨 '''thunk'''라고 불리는 객체가 전달되는 것으로 생각할 수 있다.
5. 고급 매개변수 기법
고급 매개변수 기법에는 다음과 같은 것들이 있다.
- 기본 전달인자 (Default Arguments): 에이다, C++, 클로저, 공통 리스프[9], 포트란 90[10], 파이썬, 루비, Tcl, Windows PowerShell 등 일부 프로그래밍 언어에서는 함수 선언 시 기본 인수를 설정할 수 있다. 함수 호출 시 인수를 생략하면 기본값이 사용된다.
- 가변 길이 전달인자 목록 (Variable-length Parameter Lists): 가변 인자 함수는 정해지지 않은 개수의 전달인자를 받을 수 있다. C, Python, Java 등에서 지원한다.
- 명명된 매개변수 (Named Parameters): 에이다나 Windows PowerShell 같은 일부 프로그래밍 언어에서는 함수가 명명된 매개변수를 가질 수 있다.[7] 명명된 매개변수는 호출 코드를 자기 문서화하고, 전달인자 순서 변경이나 생략을 가능하게 한다.
5. 1. 기본 전달인자 (Default Arguments)
에이다, C++, 클로저, 공통 리스프[9], 포트란 90[10], 파이썬, 루비, Tcl, Windows PowerShell과 같은 일부 프로그래밍 언어에서는 서브루틴 선언에서 기본 인수를 명시적 또는 암시적으로 제공할 수 있도록 허용한다. 이를 통해 호출자는 서브루틴을 호출할 때 해당 인수를 생략할 수 있다. 기본 인수가 명시적으로 주어지면, 호출자가 값을 제공하지 않은 경우 해당 값이 사용된다. 기본 인수가 암시적일 경우 (때로는 ''Optional''과 같은 키워드를 사용하여) 언어는 호출자가 값을 제공하지 않으면 잘 알려진 값 (예: ''null'', ''Empty'', 0, 빈 문자열 등)을 제공한다.PowerShell 예시:
function doc($g = 1.21) {
"$g 기가와트? $g 기가와트? 훌륭해!"
}
PS > doc
1.21 기가와트? 1.21 기가와트? 훌륭해!
PS > doc 88
88 기가와트? 88 기가와트? 훌륭해!
기본 인수는 가변 길이 인자 목록의 특별한 경우로 볼 수 있다.
5. 2. 가변 길이 전달인자 목록 (Variable-length Parameter Lists)
함수는 정해지지 않은 개수의 전달인자를 받을 수 있다. 이러한 함수를 가변 인자 함수라고 부르며, C, Python, Java 등에서 지원한다.PowerShell 예시:
```powershell
function marty {
$args | foreach { "back to the year $_" }
}
```
```ps1con
PS > marty 1985
back to the year 1985
PS > marty 2015 1985 1955
back to the year 2015
back to the year 1985
back to the year 1955
5. 3. 명명된 매개변수 (Named Parameters)
에이다나 Windows PowerShell 같은 일부 프로그래밍 언어에서는 서브루틴이 명명된 매개변수를 가질 수 있도록 허용한다.[7] 명명된 매개변수를 사용하면 호출 코드를 더 자기 문서화할 수 있다. 또한 호출자는 필요에 따라 전달인자의 순서를 변경하거나 전달인자를 생략할 수 있는 유연성을 얻게 된다.PowerShell 예시를 살펴보자.
```powershell
function jennifer($adjectiveYoung, $adjectiveOld) {
"Young Jennifer: I'm $adjectiveYoung!"
"Old Jennifer: I'm $adjectiveOld!"
}
```
위 함수 `jennifer`는 `$adjectiveYoung`와 `$adjectiveOld`라는 두 개의 명명된 매개변수를 가진다.
```ps1con
PS > jennifer 'fresh' 'experienced'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!
PS > jennifer -adjectiveOld 'experienced' -adjectiveYoung 'fresh'
Young Jennifer: I'm fresh!
Old Jennifer: I'm experienced!
```
`jennifer` 함수를 호출할 때 전달인자를 순서대로 전달할 수 있다. 또는 `-adjectiveOld 'experienced' -adjectiveYoung 'fresh'`와 같이 매개변수 이름을 명시하여 전달인자를 전달할 수도 있으며, 이때는 순서에 제약받지 않는다.
6. 출력 매개변수 (Output Parameters)
출력 매개변수는 함수에서 결과를 반환하는 데 사용되는 매개변수로, 일반적인 입력 매개변수와는 반대되는 개념이다. C, C++, C#, Ada, 포트란 등 다양한 프로그래밍 언어에서 지원된다.[11][12][13][14][15]
매개변수는 입력, 출력, 입/출력의 세 가지 유형으로 나뉜다. 입력 매개변수는 값을 전달하고, 출력 매개변수는 결과를 반환하며, 입/출력 매개변수는 값을 전달하고 결과를 반환하는 데 모두 사용된다. C#에서는 `void f(out int x)`와 같이 함수 선언에 `out` 키워드를 사용하여 출력 매개변수를 명시한다.
출력 매개변수는 주로 함수에서 여러 값을 반환할 때 유용하며, 특히 세미 술어 문제를 해결하는 데 사용된다. 예를 들어, C#의 `TryParse` 메서드는 문자열을 정수로 변환하고 성공 여부를 부울 값으로 반환한다.[17] 이 메서드는 다음과 같이 사용될 수 있다.
```csharp
int result;
if (!Int32.TryParse(s, result)) {
// 예외 처리
}
6. 1. 출력 매개변수의 대안
출력 매개변수는 현대 프로그래밍에서 권장되지 않는 경우가 많다. 그 이유는 본질적으로 어색하고, 혼란스러우며, 너무 낮은 수준이기 때문이다. 일반적인 반환 값을 이해하고 사용하기가 훨씬 쉽다.[18] 출력 매개변수는 부작용(출력 매개변수 수정)이 있는 함수를 포함하며 참조와 의미론적으로 유사하여 혼란을 야기할 수 있다. 또한, 일반적인 프로그래밍 스타일에서는 대부분의 매개변수가 입력 매개변수이므로 출력 매개변수는 드물고 오해를 받기 쉽다.출력 및 입/출력 매개변수는 함수 합성을 방지한다. 출력은 표현식의 값이 아닌 변수에 저장되기 때문이다. 따라서 먼저 변수를 선언해야 하며, 함수 체인의 각 단계는 별도의 문장이 되어야 한다.
함수에서 여러 값을 반환해야 하는 경우, 튜플을 반환하는 것이 대안이 될 수 있다. Go나 Python처럼 자동 시퀀스 언패킹과 병렬 할당을 사용할 수 있다면 구문적으로 더 명확해진다.
여러 유형 중 하나의 값을 반환해야 하는 경우에는 태그된 유니온을 대신 사용할 수 있다. 가장 일반적인 경우는 반환 값이 실패를 나타내기 위해 null일 수 있는 nullable type(옵션 타입)이다.
객체 지향 언어에서는 입력/출력 매개변수를 사용하는 대신 호출에 의한 공유를 사용할 수 있다. 객체에 대한 참조를 전달한 다음 객체를 변경하는 방식이지만, 변수가 참조하는 객체는 변경하지 않는다.[18]
참조
[1]
웹사이트
Passing Information to a Method or a Constructor (Learning the Java Language > Classes and Objects)
https://docs.oracle.[...]
2021-09-09
[2]
서적
C primer plus
Sams
2004
[3]
웹사이트
Working Draft, Standard for Programming Language C++
http://www.open-std.[...]
2018-01-01
[4]
웹사이트
Subprograms and Parameter Passing
http://rowdysites.ms[...]
2018-01-01
[5]
웹사이트
Passing Arguments by Value and by Reference (Visual Basic)
https://docs.microso[...]
2018-10-27
[6]
웹사이트
The GNU C Programming Tutorial
http://crasseux.com/[...]
2018-10-27
[7]
서적
Object-Oriented Software Construction, 2nd Edition
Prentice Hall
1997
[8]
문서
[9]
웹사이트
Functions
https://gigamonkeys.[...]
2021-06-02
[10]
웹사이트
optional arguments
http://www.netlib.or[...]
2021-06-02
[11]
웹사이트
8.2 Parameter Modes
http://archive.adaic[...]
[12]
웹사이트
8. PL/SQL Subprograms: Specifying Subprogram Parameter Modes
http://docs.oracle.c[...]
[13]
웹사이트
Why does C# have both 'ref' and 'out'?
http://msdn.microsof[...]
[14]
웹사이트
ParameterDirection Enumeration
http://msdn.microsof[...]
[15]
웹사이트
Functions — The Swift Programming Language (Swift 4.2)
https://docs.swift.o[...]
[16]
웹사이트
8. PL/SQL Subprograms: Passing Large Data Structures with the NOCOPY Compiler Hint
http://docs.oracle.c[...]
[17]
웹사이트
Int32.TryParse Method (String, Int32)
http://msdn.microsof[...]
[18]
웹사이트
CA1021: Avoid out parameters
http://msdn.microsof[...]
[19]
웹사이트
KAKASI (Kanji Kana Simple inversion program)
http://web.mit.edu/b[...]
MIT
[20]
웹사이트
Javascript練習 09
http://www.cc.kyoto-[...]
京都産業大学
[21]
문서
ちなみに、上の文の結果は 579 である
[22]
문서
とはいえ中島秀之によれば、DEC 10 Prologの移植に際して、「修羅場を見た」と述べている。
[23]
문서
変数以外から成る任意の式に対して、その左辺値というものは考えづらいため。あたかも名前のない変数がテンポラリに作られるかのように振舞うものもある。
[24]
웹사이트
JavaHouse-Brewers の議論
http://java-house.jp[...]
[25]
문서
본 문서에서의 "서브루틴"은 다양한 프로그래밍 언어 각각 다른 이름을 가지고 조금씩 다른 의미를 가지고 있긴 하지만, 서브루틴과 비슷한 동작을 하는 모든 형태를 의미한다.
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com