프론트엔드

URL을 상태로 관리한 방법: TanStack Router

인턴 기간 동안 백오피스 프로젝트에서 React Router 기반 레거시 코드를 마이그레이션 하는 작업을 맡았다. 단순히 마이그레이션 하기 보다는, 기존 JavaScript의 상태를 TypeScript로 마이그레이션 하면서 어떻게 런타임과 컴파일 타임 둘다 안정성을 잡을 수 있을지에 대한 고민이 많았다. 레거시 React Router 구조 기존 구조에서는 많은 필터 값을 url에 올리지 않고, 내부 상태로만 관리하고 있었다. 여기에서의 문제점은 사용자가 새로고침 시, 설정해놓은 필터 값들이 사라진다는 것이다. 따라서 UX를 향상하기 위해 사용자가 필터 값들을 새로고침 시에도 상태가 변경되지 않게 URL에 올리기로 결정하였다. URL로 상태를 옮기며 마주한 문제 ① 타입 안정성 저하 예를 들어 이런 URL이 들어올 수 있다 page, size는 number 타입이어야 하지만 실제로 사용자가 임의로 주소창에 입력한 값은 string이다. 사용자가 직접 값을 주입하였을 때, 서버로 값이 들어갈 수 있다는 점에서 라우터 단의 타입 관리가 필요해보였다. ② 상태의 기준점 모호 URL에 필터값을 올리는 방식을 채택하였을 때 필터 상태가 다음과 같이 여러 군데에 흩어져 있는 문제가 있다. useState로 관리되는 내부 상태 서버 요청 시 사용하는 query 객체 URL search 파라미터 따라서 이 기준점을 어디에 잡아야할지도 논의 및 합의가 필요한 부분이었다. 라우터 단에서 상태를 정규화하기 TanStack Router는 React Router와 달리 라우터 단에서 validateSearch를 제공한다. search 파라미터를 읽는 것과 동시에, 컴파일 및 런타임에서 zod로 검증 및 정규화를 수행할 수 있다. 라우터 단에서 다음의 기능을 수행하였다. 허용된 값만 통과 타입 자동 추론 실패 시 기본값 정규화 잘못된 쿼리는 서버에 전달되지 않음 상태 업데이트 규칙을 통일하기 URL 쿼리 값 정규화 문제는 해결하였지만, 가장 큰 문제는 필터가 있는 화면에서 코드가 계속 반복된다는 점이었다. 부분 업데이트 로직 기본값 처리 URL과 useState, URL과 서버 상태의 동기화 로직 이런 로직들이 페이지마다 반복되고 있었으며, 개발자마다 다른 로직을 사용하여 코드를 알아보기에도 쉽지 않았다. 이 문제는 useSearchParams 커스텀 훅을 만들어 해결하였다. useSearchParams Custom Hook 이 훅의 목적은 단순하다. search는 항상 타입 안전해야 하고 업데이트 방식은 팀 내에서 동일해야 한다. ① URL에 들어갈 수 있는 타입 제한 Date, 객체, Map 같은 값은 애초에 타입 단계에서 차단했다. search는 URL 직렬화 가능한 원시값만 가진다는 규칙을 강제했다. ② 업데이트 방식을 통일 이 구조로 인해서 페이지에서 search를 다루는 방식이 완전 동일해졌다. 부분 업데이트는 applySearch 전체 리셋은 resetSearch undefined는 무시 defaultSearch는 항상 기준점 적용 이후의 변화 이 커스텀 훅을 사용함으로써 다음의 변화가 생겼다. 프론트엔드 개발자 3명이 동일한 navigation 규칙 사용 필터 로직 중복 코드 약 40% 감소 공유, 새로고침, 뒤로가기 상황에서 상태 유지 신규 페이지 추가 시, navigation 로직 추가 간편화 회고 URL을 상태로 쓰는 건 생각보다 까다롭다. 페이지 내부 상태로만 관리할 때는 "내가 넣은 값만 존재한다"는 가정이 가능하지만, URL로 올리는 순간부터는 “누군가 아무 값이나 넣을 수 있다” 는 전제가 시작된다. 그래서 오히려 상태가 더 불안정해질 수도 있다. 재미있게도, 이런 종류의 문제는 결국 라이브러리 선택보다 팀 규칙의 문제다. 정규화 지점이 어디인지, 기본값이 무엇인지, 업데이트가 어떤 규칙을 따르는지. 이걸 문서가 아니라 코드로 강제했을 때 팀 생산성이 가장 크게 달라졌다. 전체 useSearchParams 코드 ts const { search, applySearch, resetSearch } = useSearchParams({ defaultSearch: { page: 1, keyword: '' }, Route, }) applySearch({ keyword: 'abc', page: 1 }) applySearch({ keyword: '' }) // keyword 제거 의도 applySearch({ tags: ['a', '', 'b'] }) // tags -> ['a','b'] applySearch({ tags: [] }) // tags 제거 의도 resetSearch() *

2026년 02월 12일 03:56

프론트엔드

🧨 우당탕탕 Axios 인터셉터 만들기

-- 토큰 만료와의 혈투 기록 -- 프론트엔드를 하다보면, 그 어떤 api보다도 나를 가장 괴롭히는게 등장한다 바로 토큰 만료(401) 이번 글은 “처음에 대충 회사 코드 ctrl c + ctrl v 했다가 혼나서 결국 프로젝트 갈아엎고 다시 처음부터 axios 인터셉터 설계하게 된 이야기” 시작은 항상 \복붙이었다. 솔직히 말하면 인터셉터 만들 여유보다는 화면 구성하고싶은 맘이 조급했다. 백오피스를 마이그레이션 하라는 지시를 받았고, 인터셉터 그까이거 그냥 사용하던거 쓰면 되는거 아님? 당연히 이렇게 시작했다. 나는 그냥 옛날 코드 가져와 붙였고, 아무 생각 없이 진행하고 있었다. 근데 코드리뷰에서 멘토님이 한 말씀 기존거 가져다쓰지 마시고 처음부터 머리 박아가면서 만들어보시죠. 네..? 다시요..? 그렇게 나는 다시 401을 맞았다. 그래서 진짜로 인터셉터가 어떤 구조로 작동해야 하는지, 토큰 로직은 어떻게 구성해야 하는지 기본부터 다시 뜯어보기로 했다. 사실 이번 인턴 면접에서 토큰 기반 인증에 관한 질문이 있었고, (현 멘토님이 내 면접관이셨다) 한 페이지에서 여러 요청이 동시에 401 에러가 나오면 어떻게 해결하는지에 대해 여쭤보셨다. 나는 그것까지는 생각을 해본 적이 없어서 잘 모르겠다고 답 했었고?? 두고두고 맘에 남았다. 그래서 기존 프로젝트 axios 인터셉터 보고 “오 이렇게 만드는구나. 설계가 잘 되어있구나” 하고 그대로 갖다 썼던 마음이 큰 것 같다. 첫 삽질: 401 해결하려다 403 맞기 나는 빠르게 at 만료 감지를 만들고, refresh api도 붙였다. 그리고 좀 기다려서 만료되었을 때 나의 시나리오 오래된 at로 api 호출 서버가 401 던짐 인터셉터가 refresh 호출 새 토큰으로 요청 재시도 … 되어야 하는데 만료된 at로 api 호출 -> 401 err 자동적으로 refresh api 호출 -> 403 err 아니 왜 재발급 한번도 못했는데 왜 403 나옴? 이 악몽같은 현상으로 하루종일 삽질만 했다. 재발급 시마다 alert도 띄워보고, Authorization 헤더도 다시 붙여보고, 인터셉터 바깥에서 refresh 호출 성공하는것도 확인했는데,, 원인이 걍 퐝당했음. at와 rt의 유효기간이 같았던 것임!!! 아!뿔!싸! 기존 인터셉터도 이거 처리가 안되어있더라! 너무 모르겠어서 jwt.io에서 token 까보고 알았다. at가 만료되었을 때 rt도 만료가되어 refresh를 할 수 있는 시간이 없었던 것이다. accessToken 만료 → refresh 요청 시도 근데 refreshToken도 이미 만료 → 403 그래서 당연히 403이 나는 구조였다. 근데 백엔드를 바꿔달라고 할 수가 없는 상황 이걸 계기로 오랜만에 조금 머리를 굴려보았다. 자동 재발급? 그건 좀 아닌것같아요. 처음에는 이런 식의 자동 로직을 생각했다. 사용자가 뭘 하든 at 만료 5분전에 자동으로 refresh 하자 근데 이 생각을 말씀드렸더니 멘토님이 말씀하셨다. 사용자가 아무 행동도 안하는데 알아서 재발급 하는건 아닌 것 같아요! 맞말임. 아무래도 백오피스다보니까 보안적인 부분도 고려를 했어야했다. 그래서 방향을 바꿨다. 사용자가 실제 api 요청 시 만료 시간이 5분 이하라면 그때 refresh 하자 즉 활성 사용자만 재발급 → 비활성 사용자 세션은 종료 동시 요청 문제 → Pending Queue 도입 다음 문제는 이거였다. 이거는 내가 면접 때 질문을 받고 대답을 못했던 그 문제이기도 한데 A API 요청 시 → 토큰 만료 → refresh 시작 그 사이에 B API 요청 → 또 토큰 만료 → refresh 또 호출 이러면 refresh api가 동시에 여러번 호출되며 경합이 발생한다. 그래서 필수적으로 refresh 중엔 다른 요청을 멈춰서 줄세우는 로직이 필요하였다. 그것이 바로 pending queue ~~내가 자료구조 수업에서 듣고 코테 풀때만 쓰던 큐를 진짜 써보는 날이 오다니~~ 요약하자면 refresh 중이면 → 요청을 queue 에 쌓아둠 refresh 끝나면 → queue에 있던 요청들을 새 토큰으로 재요청 이렇게 하면 동시 재발급 요청 문제는 해결된다. 세션 만료 경고가 여러 번 뜨는 문제 아 근데 산넘어 산이라더니 에베레스트가 나옴 refresh 실패(401/403) → 로그아웃 처리할 때 다음과 같은 코드가 있었다. 근데 api 여러개가 동시에 터지면서 alert이 여러개가 떴던것임! alert 확인 버튼 연타함 그래서 로그아웃이 한 번만 실행되게 하기 위해서 zustand에 isLoggingOut state를 추가하여 해결하였다. 근데 왜 isLoggingOut 초기화가 안돼요? 문제 발생 두번째 세션 만료 로그아웃 때, 401 떴는데 로그아웃이 안되더라 그건 내가 isLoggingOut 상태값을 zustand persist 미들웨어에 넣어놨기 때문이었다. 그래서 persist partialize 설정해서 해결하였다. ㅎㅎ 바보 최종 Axios 인터셉터 코드 삽질 끝에 만들어진 인터셉터 구조는 다음과 같다. 토큰 만료 5분 이하 → refresh refresh 동안 다른 요청은 pending queue refresh 실패 → 로그아웃 alert 중복 방지 → isLoggingOut accessToken, refreshToken 상태는 zustand에서 관리 Authorization 헤더 자동 주입 정리하자면.. 이번에 인터셉터를 처음부터 설계하면서 느낀 점: 토큰 구조를 이해해야 한다 세션 만료 UX까지 고려해야 한다 동시 요청 문제까지 잡아야 한다 상태관리까지 연계해야 한다 인터셉터는 그냥 훅 두 개가 아니라 프로젝트의 전체 인증 흐름을 담당하는 중요한 부분임을 깨달았다. 그리고 무엇보다: 절대… 생각 안하고 코드 복붙부터 시작하지 말자.

2025년 11월 20일 00:33

프론트엔드

피크민 블룸은 어떻게 꽃길🌸을 남길까?



걷기만 했는데 꽃이 심어졌다. 어떻게 작동하는 걸까? 프론트 개발자 입장에서 추정해봤다. 위치 수집과 저장 꽃을 심기 시작하면, 앱은 사용자의 위치를 실시간으로 추적하기 시작한다. 이때 예상되는 기술 흐름은 다음과 같다: CLLocationManager를 통한 실시간 위치 수집 일정 간격으로 좌표를 샘플링하여 배열에 저장 -> 너무 가까운 위치는 무시하여 노이즈 제거 앱을 닫아도 백그라운드에서 계속 추적 (배터리 최적화 필요) 저장 포맷은 아마도? 꽃을 심은 경로는 단순 좌표가 아닌 시간 + 위치 + 심은 꽃 종류 등 메타데이터가 포함되어 있을 가능성이 높다. 지금 5월이라 또 가정의 달이라고, 이달의 꽃은 카네이션, 장미 등등.. 난리났다. 각각 꽃 이름을 다 고유명사로 짓기에는 한계가 있을테니 시즌-꽃-색상 이렇게 짓지 않았을까? 25-5-rose-red (25년 5월 시즌 빨간색 장미꽃) 지도 위 시각화 꽃을 심고 나면, 지도 위에 꽃잎들이 길을 따라 자동 배치된다. 이를 구현하려면 다음과 같은 절차가 필요하다: MKPolyline 또는 커스텀 캔버스를 이용해 라인을 그림 일정 간격으로 꽃 모양 아이콘을 offset에 따라 반복 배치 아이콘은 애니메이션 또는 이미지 뷰로 간단하게 처리 가능 성능 문제는? 꽃이 많아지면 오브젝트 수도 급격히 증가 -> 렌더링 최적화 필수 과거 기록도 남기려면 서버 측에 저장하고, 맵 확대 시에만 불러오는 식의 lazy loading 전략이 유력 그래서 아이폰 12 mini 에서는 꽃을 오래 심으면 앱이 자꾸 꺼진다 ㅜㅜ 실시간 위치 추적과 일반 걸음 기록은 다르다 피크민 블룸은 항상 걸음을 기록하지만, 꽃을 심을 때만 파란 위치 아이콘이 뜨는 것을 보면 두 기능은 서로 다르게 작동한다. 🌱 일반 걸음 기록 아이폰에서 피트니스 API 또는 HealthKit과 연동되어 걸음 수만 수집 이때는 정확한 위치 정보는 사용하지 않음 -> 아이폰 상단에 파란색 위치 아이콘이 뜨지 않음 🌸 꽃을 심을 때는 실시간 GPS 추적 사용자가 ‘꽃 심기’ 버튼을 누르는 순간부터, CLLocationManager가 실시간으로 위치를 추적하며 경로를 저장 -> 아이폰 상단에 파란 위치 추적 아이콘이 표시됨 이후 종료 버튼을 누르면 기록이 서버에 업로드되거나 저장됨 맵 전체가 아닌, 현재 위치 중심 반경 N미터만 렌더링한다 피크민 블룸을 실행하면, 꽃이 원형으로 촤라락 펼쳐지듯 한 번에 맵에 나타난다. 이걸 보면 전체 데이터를 로딩하는 게 아니라, 현재 위치 기준 반경 약 200~300m 정도만 요청하고 시각화하는 것으로 보인다. (더 넓을수도?) 예상되는 흐름 앱 실행 / 맵 이동 감지 현재 위치를 기준으로 일정 반경 (ex. 200m) 설정 서버에 꽃 정보 요청 응답 받은 꽃 데이터 기준으로 렌더링 경로 따라 꽃 아이콘 배치 종류별로 다른 텍스처 사용 일정 간격마다 반복 표시 사용자가 이동할 경우, 일정 거리 이상 벗어나면 새 요청 * 이전에 본 영역은 로컬 캐시로 보여줌 왜 반경 단위로 렌더링할까? 퍼포먼스 때문: 전체 도시 데이터를 한 번에 불러오면 부하가 너무 큼 프라이버시 때문: 다른 유저의 꽃 경로를 멀리까지 보여줄 필요 없음 인터랙션 유도: 근처만 보여줘야 걷고 이동하게 만들 수 있음 결론 피크민 블룸은 단순한 위치 기반 게임이 아니라, 실시간 GPS 추적 + 사용자 입력 이벤트 + 거리 기반 로딩 전략이 모두 섞인 정교한 구조를 갖고 있다. 이런 구조를 보면 ‘걷기’라는 일상적인 활동도 얼마나 다양하게 확장 가능한지 실감하게 된다.

2025년 05월 04일 01:53

CS

[SQLD] WHERE 절

SQLD 2과목 - WHERE 절 WHERE 절 WHERE 절은 테이블에서 원하는 조건에 맞는 데이터만 조회할때 사용하는 절이다. 여러 조건을 지정할 수 있으며, AND와 OR 연산자로 조건을 연결할 수 있다. NULL 값 조회 시 IS NULL 또는 IS NOT NULL 연산자를 사용한다. ⭐️ 집계함수(SUM, AVG, COUNT 등)는 WHERE 절에서 사용할 수 없다. ⭐️ 컬럼 별칭은 WHERE 절에서 사용할 수 없다. 주의사항 문자 또는 날짜 상수 표현 시 홑따옴표 사용 Oracle에서는 문자 상수의 대소문자 구분 SQL Server에서는 기본 설정 기준으로 문자 상수의 대소문자 구분 ❌ 논리 연산자 NOT > AND > OR 순으로 연산 우선순위가 적용됨 ① AND 연산자 모든 조건을 동시에 만족하는 교집합 반환 ② OR 연산자 조건 중 하나라도 만족하면 포함하는 합집합 반환 ③ NOT 연산자 조건 결과의 반대 집합, 즉 여집합 반환 IN 연산자 여러 상수 중 하나와 일치하는 조건 전달 BETWEEN A AND B 연산자 A 이상이고 B 이하인 조건을 만족하는 대상을 선택 ❗️ A는 반드시 B보다 작아야 하며, 반대로 작성할 경우 공집합 LIKE 연산자 정확히 일치하지 않아도 되는 패턴 조건을 전달할 때 사용하는 연산자 와일드카드 문자(%, \)와 함께 사용 %: 자리수 제한 없이 모든 문자열 의미 : 한 글자를 의미, 하나당 한 자리의 모든 값 예시 ENAME LIKE 'S%' → 이름이 ‘S’로 시작하는 조건 ENAME LIKE '%S%' → 이름에 ‘S’가 포함된 조건 ENAME LIKE '%S' → 이름이 ‘S’로 끝나는 조건 ENAME LIKE '\S%' → 이름의 두 번째 글자가 ‘S’인 조건 ENAME LIKE '\\S\\' → 이름의 가운데 글자가 ‘S’이며, 전체 길이가 5 글자인 조건 ESCAPE CHARACTER % 또는 \를 와일드카드가 아닌 일반 문자로 조회하고 싶을 때 사용 특정 문자를 ESCAPE 문자로 지정하여 그 뒤에 오는 % 또는 \를 문자 그대로 인식하게 함 예시 WHERE ENAME LIKE 'A\\\%' ESCAPE '\\' → 이름이 ‘A\’로 시작하는 조건 (\_ 를 문자로 인식) ENAME LIKE '%!%%' ESCAPE '!' → 이름에 ‘%’ 문자가 포함된 조건

2026년 02월 13일 18:14

CS

[SQLD] 일반 함수

SQLD 2과목 – 일반함수 일반 함수 NVL NULL 값을 다른 값으로 치환 대상 값과 치환 값은 서로 동일한 데이터 타입 NVL2 대상 값이 NULL인지 여부에 따라 서로 다른 값 반환 특징 대상 값이 NULL이 아니면 첫번째 인수인 그외치환값 반환 대상 값이 NULL이면 두번째 인수인 널치환값 반환 반환되는 두 값은 서로 동일한 데이터 타입 COALESCE NULL 값을 치환 NVL과 달리 두 개 이상의 인수 지정 가능 특징 나열된 값 중에서 가장 먼저 등장하는 NULL이 아닌 값을 반환 모든 인수는 서로 호환 가능한 데이터 타입 NULLIF 두 값을 비교하여 동일한 경우 NULL 반환 특징 두 값이 서로 같으면 NULL, 다르면 첫번째 값 반환 ISNULL NULL값을 다른 값으로 치환 SQL Server에서만 제공 특징 대상 값이 NULL이면 치환값, NULL이 아니면 원래 값 반환 DECODE 조건에 따라 서로 다른 값을 반환 Oracle에서 제공 특징 대상값이 값1과 일치하면 결과1 반환 대상값이 값2와 일치하면 결과2 반환 기본값은 모든 조건에 일치하지 않을 경우 반환 (생략 시 NULL 반환) CASE문 조건에 따라 서로 다른 결과 반환 반드시 END 키워드로 마무리 조건과 그에 대응하는 치환값 여러 개 전달 가능 축약형 특징 ELSE 절 생략 시 NULL이 반환 모든 조건의 대상이 같고 항상 동등 비교 조건일 경우 축약형 사용 가능 축약형 문법에서는 WHERE과 THEN 사이에 상수 값만 배치 가능 축약형 문법에서 값과 결과의 데이터 타입이 일치하지 않으면 에러

2026년 02월 13일 16:59

CS

[SQLD] 변환 함수

SQLD 2과목 – 변환함수 데이터 타입을 다른 함수로 변환하는 함수 변환 함수 TONUMBER 문자 타입 데이터 → 숫자 타입 데이터 특징 숫자 형태의 문자와 숫자 데이터 간 연산시 묵시적 형 변환 발생해 연산 정상적 수행 묵시적 형변환 TOCHAR 숫자/날짜 타입 데이터 → 문자 타입 데이터 반환 결과는 항상 문자 특징 반환 대상이 숫자일 경우, 숫자 변환에 필요한 FORMAT 전달 반환 대상이 날짜일 경우, 날짜 변환에 필요한 FORMAT 전달 FORMAT 생략 시 단순히 문자 타입으로만 변환 📌 숫자 FORMAT 📌 날짜 FORMAT MONTH, DAY, DY, MON 등 문자 출력 포맷은 대소문자를 구분하므로 포맷 입력 형태에 따라 출력 결과 상이 포맷을 소문자로 입력하면 소문자로, 대문자로 입력하면 대문자로 출력 TODATE 문자 타입 데이터 → 날짜 타입 데이터 날짜처럼 생긴 문자열을 날짜 데이터로 인식시키기 위함 특징 날짜처럼 생긴 날짜문자열을 지정한 FORMAT에 맞게 해석하여 날짜 타입으로 변환 FORMAT 생략 시 세션의 기본 날짜 형식 기준으로 해석 두자리 연도 YY / RR 해석 TODATE 에서 지정되지 않은 날짜 요소 처리 방식 지정되지 않은 연도와 월은 현재 날짜 기준으로 설정 지정되지 않은 일, 시, 분, 초는 초기값으로 설정 날짜 연산 날짜 타입의 값과 숫자 간 더하기, 빼기 연산 가능 숫자 1은 하루를 의미 숫자 1/24는 한시간을 의미 날짜 - 날짜 연산의 결과는 두 날짜간의 일수 차이 숫자 반환

2026년 02월 13일 16:46

CS

[SQLD] 날짜 함수

SQLD 2과목 – 날짜함수 날짜 함수 SYSDATE / SYSTIMESTAMP 현재 날짜와 시간 반환 입력값 없이 호출 가능 특징 DBMS의 날짜 포맷 설정에 따라 출력 형식 상이 SYSDATE는 DATE 타입으로 반환 (초단위까지) SYSTIMESTAM는 TIMESTAMP 타입으로 반환 (밀리초까지) EXTRACT 날짜 또는 타임스탬프 값에서 연, 월, 일 등 특정 요소 추출 출력 결과는 숫자 타입으로 반환 특징 추출 대상: YEAR, MONTH, DAY, HOUR, MINUTE, SECOND SYSDATE 같은 DATE 타입에서는 YEAR, MONTH, DAY 만 추출 가능 SYSTIMESTAMP 같은 DATE 타입에서는 YEAR, MONTH, DAY, HOUR, MINUTE, SECOND 까지 추출 가능 ROUND 날짜를 지정한 기준 단위로 반올림 특징 자리수는 YEAR, MONTH, DD, HH, MI 등 지정 가능 지정한 자리수에서 직접 반올림 ❌ 해당 자리수보다 더 작은 단위에서 반올림 수행 자리수 생략 시 기본값 DD - HOUR 기준으로 반올림 수행 TRUNC 날짜를 지정한 기준 단위로 버림 특징 자리수는 YEAR, MONTH, DD, HH, MI 지정 가능 지정한 자리수에서 직접 버림 ❌ 해당 자리수보다 더 작은 단위에서 버림 수행 자리수 생략 시 기본값 DD - HOUR 기준으로 버림 수행

2026년 02월 13일 12:10

CS

[SQLD] 숫자함수

SQLD 2과목 – 숫자함수 숫자 함수 ROUND 숫자를 반올림 특징 자리수 생략 시 소수점 첫번째 자리에서 반올림 자리수 < 0 → 정수 자리에서 반올림 TRUNC 숫자를 버림 처리 특징 자리수 생략 시 소수점 첫번째 자리에서 버림 자리수 < 0 → 정수 자리에서 버림 CEIL 주어진 값보다 크거나 같은 값 중에서 가장 작은 정수 반환 (올림) 특징 자리수 생략 시 소수점 첫번째 자리에서 버림 자리수 < 0 → 정수 자리에서 버림 FLOOR 주어진 값보다 작거나 같은 값 중에서 가장 큰 정수 반환 (버림) ABS 숫자의 절대값을 반환 양수, 음수 모두 양수 값으로 반환 MOD 특정 값으로 나눈 나머지 특징 숫자1을 숫자2로 나눈 나머지 출력 숫자2가 0이면 첫번째 인수 값 그대로 반환 SIGN 숫자의 부호 판별 양수는 1, 음수는 -1, 0은 0 반환 POWER 숫자의 거듭제곱 반환 특징 숫자1의 숫자2 거듭제곱 반환

2026년 02월 13일 11:38