SuitsDocs
콘텐츠데이터모델

수식

수식을 사용하여 자동 계산을 설정하세요.

수식 기본 사용법

수식 속성 추가

  1. + 속성 추가수식(Formula) 선택
  2. 수식 편집기에서 수식 입력
  3. 저장

기본 구문

prop("속성이름")

prop() 함수로 다른 속성의 값을 가져와 계산합니다.

// 총 금액 계산
prop("단가") * prop("수량")

속성 참조

prop()

다른 속성의 값을 가져옵니다.

prop("속성이름")
속성 타입반환 값
텍스트문자열
숫자/통화숫자
날짜날짜 객체
체크박스true/false
선택선택된 값 문자열
다중 선택값 배열

연산자

산술 연산자

기본적인 수학 계산을 수행합니다.

연산자설명예시
+덧셈prop("A") + prop("B")
-뺄셈prop("A") - prop("B")
*곱셈prop("A") * prop("B")
/나눗셈prop("A") / prop("B")
%나머지prop("A") % prop("B")
// 총 금액
prop("단가") * prop("수량")

// 할인 적용 가격
prop("정가") * (1 - prop("할인율") / 100)

// 세금 포함 가격
prop("금액") * 1.1

비교 연산자

두 값을 비교하여 true/false를 반환합니다.

연산자설명예시
==같음prop("상태") == "완료"
!=다름prop("상태") != "취소"
>크다prop("점수") > 80
>=크거나 같다prop("점수") >= 80
<작다prop("재고") < 10
<=작거나 같다prop("재고") <= 10

논리 연산자

조건을 조합합니다.

연산자설명예시
andANDprop("A") and prop("B")
orORprop("A") or prop("B")
notNOTnot prop("완료")
// 두 조건 모두 만족
prop("상태") == "진행중" and prop("우선순위") == "높음"

// 둘 중 하나 만족
prop("상태") == "완료" or prop("상태") == "취소"

// 조건 부정
not prop("취소됨")

조건문

if()

조건에 따라 다른 값을 반환합니다.

if(조건, 참일때값, 거짓일때값)
// 상태 이모지
if(prop("완료"), "✅", "⏳")

// 재고 상태
if(prop("재고") <= 10, "⚠️ 저재고", "정상")

// 등급 계산
if(prop("점수") >= 90, "A", "B 이하")

중첩 조건

여러 조건을 순차적으로 검사합니다.

if(prop("점수") >= 90, "A",
  if(prop("점수") >= 80, "B",
    if(prop("점수") >= 70, "C",
      if(prop("점수") >= 60, "D", "F"))))

중첩이 깊어지면 가독성이 떨어집니다. 간단한 조건을 먼저 검사하세요.


텍스트 함수

concat()

텍스트를 연결합니다.

concat(텍스트1, 텍스트2, ...)
// 이름 결합
concat(prop("성"), " ", prop("이름"))
// 결과: "김 철수"

// 주소 조합
concat(prop("시"), " ", prop("구"), " ", prop("동"))
// 결과: "서울시 강남구 역삼동"

// 라벨 생성
concat("[", prop("카테고리"), "] ", prop("제목"))
// 결과: "[버그] 로그인 오류 수정"

length()

텍스트의 길이를 반환합니다.

length(텍스트)
// 제목 길이
length(prop("제목"))

// 글자 수 제한 확인
if(length(prop("설명")) > 100, "⚠️ 너무 김", "✅ 적정")

contains()

텍스트에 특정 문자열이 포함되어 있는지 확인합니다.

contains(텍스트, 검색어)
// 이메일 도메인 확인
if(contains(prop("이메일"), "@gmail.com"), "Gmail", "기타")

// 키워드 포함 여부
if(contains(prop("제목"), "긴급"), "🚨 긴급", "일반")

숫자 함수

round(), floor(), ceil()

숫자를 반올림/내림/올림합니다.

// 반올림
round(prop("평균점수"))  // 85.4 → 85

// 내림
floor(prop("평균점수"))  // 85.9 → 85

// 올림
ceil(prop("평균점수"))   // 85.1 → 86

abs()

절대값을 반환합니다.

abs(prop("차이"))  // -10 → 10

min(), max()

최소값/최대값을 반환합니다.

// 최소값
min(prop("예산"), prop("실제비용"))

// 최대값
max(prop("시작일"), prop("종료일"))

날짜 함수

now()

현재 날짜와 시간을 반환합니다.

now()  // 현재 날짜/시간

dateBetween()

두 날짜 사이의 차이를 계산합니다.

dateBetween(날짜1, 날짜2, 단위)
단위설명
"years"연 단위
"months"월 단위
"days"일 단위
"hours"시간 단위
"minutes"분 단위
// 마감일까지 남은 일수
dateBetween(prop("마감일"), now(), "days")

// 근무 기간 (년)
dateBetween(now(), prop("입사일"), "years")

// 경과 시간
dateBetween(now(), prop("시작시간"), "hours")

dateAdd()

날짜에 기간을 더합니다.

dateAdd(날짜, 숫자, 단위)
// 7일 후
dateAdd(now(), 7, "days")

// 1개월 후
dateAdd(prop("시작일"), 1, "months")

formatDate()

날짜를 특정 형식의 문자열로 변환합니다.

formatDate(날짜, 형식)
// 년-월-일
formatDate(prop("날짜"), "yyyy-MM-dd")  // "2024-01-15"

// 월/일
formatDate(prop("날짜"), "MM/dd")  // "01/15"

// 요일 포함
formatDate(prop("날짜"), "MM월 dd일 (EEE)")  // "01월 15일 (월)"

빈 값 처리

empty()

값이 비어있는지 확인합니다.

empty(prop("속성이름"))  // 비어있으면 true
// 담당자 미지정 표시
if(empty(prop("담당자")), "❌ 미지정", prop("담당자"))

// 마감일 없으면 "미정"
if(empty(prop("마감일")), "미정", formatDate(prop("마감일"), "MM/DD"))

실전 예시

기본 계산

// 총 금액
prop("단가") * prop("수량")

// 할인가
prop("정가") * (1 - prop("할인율") / 100)

// 부가세 포함
prop("금액") * 1.1

// 수수료 계산
prop("매출") * 0.03

진행률

// 백분율 진행률
round(prop("완료 수") / prop("전체 수") * 100)

// 진행률 바 (텍스트)
concat(
  "▓".repeat(round(prop("진행률") / 10)),
  "░".repeat(10 - round(prop("진행률") / 10)),
  " ",
  prop("진행률"),
  "%"
)
// 결과: "▓▓▓▓▓▓░░░░ 60%"

D-Day 표시

// 마감일 D-Day
if(prop("마감일") < now(),
  concat("D+", dateBetween(now(), prop("마감일"), "days")),
  if(prop("마감일") == now(),
    "D-Day",
    concat("D-", dateBetween(prop("마감일"), now(), "days"))
  )
)
// 결과: "D-3" 또는 "D+2" 또는 "D-Day"

상태 이모지

// 상태별 이모지
if(prop("상태") == "완료", "✅",
  if(prop("상태") == "진행중", "🔄",
    if(prop("상태") == "대기", "⏳",
      if(prop("상태") == "취소", "❌", "📋"))))

우선순위 점수

// 긴급도와 중요도로 우선순위 계산
if(prop("긴급") and prop("중요"), "🔴 1순위",
  if(prop("긴급") or prop("중요"), "🟡 2순위",
    "🟢 3순위"))

재고 상태

// 재고 상태 자동 표시
if(prop("재고") <= 0, "🔴 품절",
  if(prop("재고") <= prop("안전재고"), "🟡 저재고",
    "🟢 정상"))

근무일 계산

// 근속 연수
concat(
  dateBetween(now(), prop("입사일"), "years"),
  "년 ",
  dateBetween(now(), prop("입사일"), "months") % 12,
  "개월"
)
// 결과: "3년 5개월"

이메일 도메인 추출

// @ 이후 도메인
slice(prop("이메일"), indexOf(prop("이메일"), "@") + 1)

수식 작성 팁

1. 작게 시작하기

복잡한 수식은 단계별로 작성하고 테스트하세요.

// 1단계: 기본 계산
prop("단가") * prop("수량")

// 2단계: 할인 적용
prop("단가") * prop("수량") * (1 - prop("할인율") / 100)

// 3단계: 최소 금액 적용
max(prop("단가") * prop("수량") * (1 - prop("할인율") / 100), 10000)

2. 빈 값 처리

속성이 비어있을 수 있으면 항상 처리하세요.

// ❌ 빈 값 미처리
prop("단가") * prop("수량")  // 빈 값이면 에러

// ✅ 빈 값 처리
if(empty(prop("수량")), 0, prop("단가") * prop("수량"))

3. 가독성 유지

긴 수식은 줄바꿈과 들여쓰기로 가독성을 높이세요.

// 가독성 좋은 중첩 조건
if(prop("점수") >= 90, "A",
  if(prop("점수") >= 80, "B",
    if(prop("점수") >= 70, "C",
      "D")))

4. 단위 주의

숫자 계산 시 단위를 확인하세요.

// 할인율이 0~100 범위인 경우
prop("정가") * (1 - prop("할인율") / 100)

// 할인율이 0~1 범위인 경우
prop("정가") * (1 - prop("할인율"))

목록/배열 함수

count()

배열의 항목 수를 반환합니다.

count(배열)
// 다중 선택 항목 수
count(prop("태그"))  // ["버그", "긴급", "UI"] → 3

unique()

배열에서 중복을 제거한 고유 값 목록을 반환합니다.

unique(배열)
// 중복 제거
unique(prop("카테고리"))  // ["A", "B", "A", "C"] → ["A", "B", "C"]

includes()

배열에 특정 값이 포함되어 있는지 확인합니다.

includes(배열, 값)
// 태그 포함 여부
if(includes(prop("태그"), "긴급"), "🚨 긴급!", "일반")

join()

배열의 항목들을 구분자로 연결하여 문자열로 반환합니다.

join(배열, 구분자)
// 태그 표시
join(prop("태그"), ", ")  // ["버그", "UI"] → "버그, UI"

slice()

배열의 일부분을 추출합니다.

slice(배열, 시작인덱스, 끝인덱스)
// 처음 3개만
slice(prop("목록"), 0, 3)

at()

특정 인덱스의 요소를 반환합니다.

at(배열, 인덱스)
// 첫 번째 항목
at(prop("목록"), 0)

// 마지막 항목 (-1은 뒤에서 첫 번째)
at(prop("목록"), -1)

listMin(), listMax()

배열의 최소값/최대값을 반환합니다.

listMin(배열)
listMax(배열)
// 점수 배열에서 최저점
listMin(prop("점수들"))  // [85, 92, 78, 95] → 78

// 최고점
listMax(prop("점수들"))  // [85, 92, 78, 95] → 95

전체 함수 목록

수학 함수

함수설명예시
add(a, b)덧셈add(1, 2)3
subtract(a, b)뺄셈subtract(10, 3)7
multiply(a, b)곱셈multiply(3, 4)12
divide(a, b)나눗셈divide(10, 2)5
mod(a, b)나머지mod(10, 3)1
pow(x, y)거듭제곱pow(2, 3)8
abs(x)절대값abs(-10)10
round(x, decimals?)반올림round(3.14159, 2)3.14
floor(x)내림floor(3.7)3
ceil(x)올림ceil(3.2)4
min(a, b, ...)최소값min(5, 3)3
max(a, b, ...)최대값max(5, 3)5
sqrt(x)제곱근sqrt(9)3
cbrt(x)세제곱근cbrt(27)3
exp(x)e의 거듭제곱exp(1)2.718...
ln(x)자연로그ln(e())1
log10(x)상용로그log10(100)2
log2(x)밑이 2인 로그log2(8)3
sign(x)부호 (-1, 0, 1)sign(-5)-1
sin(x)사인 (라디안)sin(0)0
cos(x)코사인 (라디안)cos(0)1
tan(x)탄젠트 (라디안)tan(0)0
pi()원주율pi()3.14159...
e()자연상수e()2.71828...
toNumber(x)숫자 변환toNumber("123")123

텍스트 함수

함수설명예시
concat(a, b, ...)문자열 연결concat("Hello", " ", "World")
join(arr, sep)배열을 구분자로 연결join(["a", "b"], ",")"a,b"
split(text, sep)문자열 분리split("a,b,c", ",")["a", "b", "c"]
contains(text, sub)포함 여부contains("Hello", "ell")true
indexOf(text, sub)위치 찾기indexOf("hello", "l")2
startsWith(text, sub)시작 여부startsWith("hello", "he")true
endsWith(text, sub)끝 여부endsWith("hello", "lo")true
slice(text, start, end?)부분 문자열slice("Hello", 0, 2)"He"
substring(text, start, end?)부분 문자열substring("Hello", 1, 3)"el"
left(text, count)왼쪽에서 추출left("Hello", 2)"He"
right(text, count)오른쪽에서 추출right("Hello", 2)"lo"
length(text)문자열 길이length("Hello")5
upper(text)대문자 변환upper("hello")"HELLO"
lower(text)소문자 변환lower("HELLO")"hello"
capitalize(text)첫 글자 대문자capitalize("hello")"Hello"
trim(text)양쪽 공백 제거trim(" hi ")"hi"
trimStart(text)왼쪽 공백 제거trimStart(" hi")"hi"
trimEnd(text)오른쪽 공백 제거trimEnd("hi ")"hi"
replace(text, old, new)첫 번째 치환replace("abc", "b", "x")"axc"
replaceAll(text, old, new)전체 치환replaceAll("aba", "a", "x")"xbx"
test(text, regex)정규식 검사test("abc123", "[0-9]+")true
match(text, regex)정규식 매치match("abc123", "[0-9]+")"123"
repeat(text, count)문자열 반복repeat("ab", 3)"ababab"
padStart(text, len, char?)왼쪽 패딩padStart("5", 3, "0")"005"
padEnd(text, len, char?)오른쪽 패딩padEnd("5", 3, "0")"500"
format(template, ...)포맷팅format("{0}님", "홍길동")"홍길동님"
toString(value)문자열 변환toString(123)"123"

논리 함수

함수설명예시
if(cond, then, else)조건문if(true, "A", "B")"A"
ifs(c1, v1, c2, v2, ..., default?)다중 조건 (switch 대용)ifs(x=="A", "우수", x=="B", "양호", "보통")
and(a, b, ...)논리 ANDand(true, false)false
or(a, b, ...)논리 ORor(true, false)true
not(x)논리 NOTnot(true)false
equal(a, b)동등 비교equal(1, 1)true
unequal(a, b)부등 비교unequal(1, 2)true
larger(a, b)크다larger(5, 3)true
largerEq(a, b)크거나 같다largerEq(5, 5)true
smaller(a, b)작다smaller(3, 5)true
smallerEq(a, b)작거나 같다smallerEq(3, 3)true
empty(x)빈 값 확인empty("")true
ifEmpty(value, default)빈 값이면 기본값 반환ifEmpty(prop("메모"), "없음")
isNumber(x)숫자 여부isNumber(123)true
isText(x)텍스트 여부isText("hello")true
isBoolean(x)불리언 여부isBoolean(true)true
isDate(x)날짜 여부isDate(now())true
isArray(x)배열 여부isArray([1, 2])true

날짜 함수

함수설명예시
now()현재 날짜/시간now()
today()오늘 날짜 (시간 00:00)today()
date(year, month, day)날짜 생성date(2024, 1, 15)
dateAdd(date, num, unit)날짜 더하기dateAdd(now(), 7, "days")
dateSubtract(date, num, unit)날짜 빼기dateSubtract(now(), 1, "months")
dateBetween(d1, d2, unit)날짜 차이dateBetween(d1, d2, "days")
year(date)연도 추출year(now())2024
month(date)월 추출 (1-12)month(now())12
day(date)일 추출day(now())14
weekday(date)요일 추출 (0=일, 1=월, ...)weekday(now())
hour(date)시간 추출hour(now())15
minute(date)분 추출minute(now())30
second(date)초 추출second(now())45
startOfDay(date)해당일 시작 (00:00)startOfDay(now())
endOfDay(date)해당일 종료 (23:59)endOfDay(now())
startOfWeek(date)해당 주 시작 (월요일)startOfWeek(now())
endOfWeek(date)해당 주 종료 (일요일)endOfWeek(now())
startOfMonth(date)해당 월 시작startOfMonth(now())
endOfMonth(date)해당 월 종료endOfMonth(now())
startOfYear(date)해당 연도 시작startOfYear(now())
endOfYear(date)해당 연도 종료endOfYear(now())
isAfter(d1, d2)d1이 d2 이후인지isAfter(prop("마감일"), now())
isBefore(d1, d2)d1이 d2 이전인지isBefore(now(), prop("마감일"))
isSameDay(d1, d2)같은 날인지isSameDay(prop("날짜"), today())
formatDate(date, format?)날짜 포맷formatDate(now(), "yyyy-MM-dd")
timestamp(date)타임스탬프 변환 (ms)timestamp(now())
fromTimestamp(ts)타임스탬프 → 날짜fromTimestamp(1704067200000)
parseDate(str)문자열 → 날짜parseDate("2024-01-15")

목록 함수

함수설명예시
map(arr, callback)각 요소에 함수 적용prop("주문").map(current.금액)
filter(arr, callback)조건 만족 요소만prop("주문").filter(current.상태 == "완료")
find(arr, callback)조건 만족 첫 요소prop("담당자").find(current.역할 == "팀장")
findIndex(arr, callback)조건 만족 첫 인덱스prop("태그").findIndex(current == "긴급")
some(arr, callback)하나라도 만족하면 trueprop("체크리스트").some(current.완료)
every(arr, callback)모두 만족하면 trueprop("항목").every(current.검토완료)
sort(arr, callback?)정렬prop("점수").sort()
reverse(arr)역순prop("날짜").reverse()
flat(arr)중첩 배열 평탄화prop("태그목록").flat()
unique(arr)중복 제거unique([1, 1, 2])[1, 2]
slice(arr, start, end?)부분 배열slice([1,2,3,4], 0, 2)[1, 2]
concat(arr1, arr2)배열 연결concat(prop("태그1"), prop("태그2"))
at(arr, idx)인덱스 접근at([1, 2, 3], -1)3
first(arr)첫 번째 요소prop("담당자").first()
last(arr)마지막 요소prop("이력").last()
includes(arr, val)포함 여부includes([1, 2], 2)true
listIndexOf(arr, val)값 인덱스listIndexOf([1, 2], 2)1
sum(arr)합계sum([1, 2, 3])6
mean(arr)평균mean([2, 4, 6])4
average(arr)평균 (mean의 별칭)average([2, 4, 6])4
count(arr)항목 수count([1, 2, 3])3
listMin(arr)배열 최소값listMin([3, 1, 2])1
listMax(arr)배열 최대값listMax([3, 1, 2])3
listJoin(arr, sep?)배열 → 문자열listJoin(["a", "b"], ", ")"a, b"

다음 단계

  • 속성 - 수식에서 사용할 수 있는 속성 타입
  • 관계 - 롤업으로 관계 데이터 집계하기
  • 워크플로우 - 수식 결과 기반 자동화