쪽지발송 성공
Click here
재능넷 이용방법
재능넷 이용방법 동영상편
가입인사 이벤트
판매 수수료 안내
안전거래 TIP
재능인 인증서 발급안내

🌲 지식인의 숲 🌲

🌳 디자인
🌳 음악/영상
🌳 문서작성
🌳 번역/외국어
🌳 프로그램개발
🌳 마케팅/비즈니스
🌳 생활서비스
🌳 철학
🌳 과학
🌳 수학
🌳 역사
해당 지식과 관련있는 인기재능

안녕하세요. 개발경력10년차 풀스택 개발자입니다. java를 기본 베이스로 하지만, 개발효율 또는 고객님의 요구에 따라 다른언어를 사용...

안녕하세요, 6년차 머신러닝, 딥러닝 엔지니어 / 리서처 / 데이터 사이언티스트 입니다. 딥러닝 코딩을 통한 기술 개발부터, 오픈소스 ...

    단순 반복적인 업무는 컴퓨터에게 맡기고 시간과 비용을 절약하세요!​ 1. 소개  ​업무자동화를 전문적으로 개발/유...

c언어c++,   erwin을 이용한 데이터베이스 설계java,    jsp,     javascript,      c#  ...

Clojure.spec을 이용한 생성 테스팅: 버그 잡기의 혁명

2024-12-11 21:09:35

재능넷
조회수 559 댓글수 0

Clojure.spec을 이용한 생성 테스팅: 버그 잡기의 혁명 🐞🚀

 

 

안녕, 친구들! 오늘은 정말 흥미진진한 주제로 여러분과 함께 이야기를 나눠볼 거야. 바로 Clojure.spec을 이용한 생성 테스팅에 대해서 말이야. 이게 뭐냐고? 간단히 말하면, 버그를 잡는 초강력 무기라고 할 수 있지! 😎

우리가 프로그램을 만들 때 가장 골치 아픈 게 뭘까? 바로 버그지! 이 짜증나는 녀석들을 잡으려고 우리는 밤낮으로 고생하곤 해. 근데 말이야, Clojure.spec이라는 녀석을 이용하면 이 과정이 훨씬 더 쉬워질 수 있다고! 어떻게 그럴 수 있는지 함께 알아보자고.

🤔 잠깐! Clojure가 뭐였더라?

Clojure는 Lisp 계열의 함수형 프로그래밍 언어야. 자바 가상 머신(JVM) 위에서 동작하고, 동시성 프로그래밍을 쉽게 할 수 있도록 설계됐어. 간결하고 강력한 문법으로 유명하지!

자, 이제 본격적으로 Clojure.spec과 생성 테스팅에 대해 알아보자. 준비됐어? 그럼 출발! 🚀

Clojure.spec이 뭐야? 🤷‍♂️

Clojure.spec은 Clojure 1.9 버전부터 도입된 라이브러리야. 이 녀석의 주요 목적은 데이터의 구조와 함수의 입출력을 명확하게 정의하는 거야. 쉽게 말해서, 우리가 다루는 데이터가 어떤 모양이어야 하는지, 함수에 어떤 값이 들어가고 나와야 하는지를 정확하게 알려주는 거지.

예를 들어볼까? 우리가 사용자의 정보를 다루는 프로그램을 만든다고 생각해보자. 사용자의 이름, 나이, 이메일 주소를 저장해야 해. 그럼 Clojure.spec을 이용해서 이렇게 정의할 수 있어:


(require '[clojure.spec.alpha :as s])

(s/def ::name string?)
(s/def ::age (s/and int? #(>= % 0)))
(s/def ::email (s/and string? #(re-matches #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$" %)))

(s/def ::user (s/keys :req-un [::name ::age ::email]))

이렇게 정의하면 뭐가 좋을까? 🤔

  • 데이터의 구조가 명확해져. 어떤 필드가 있어야 하는지, 각 필드의 타입은 뭐여야 하는지 한눈에 알 수 있지.
  • 잘못된 데이터를 쉽게 찾아낼 수 있어. 예를 들어, 나이에 음수가 들어오면 바로 에러를 발생시킬 수 있지.
  • 문서화의 역할도 해. 다른 개발자가 이 코드를 봤을 때, 데이터가 어떤 구조여야 하는지 바로 이해할 수 있어.

근데 말이야, Clojure.spec의 진가는 여기서 끝이 아니야. 이 녀석이 진짜 대단한 건 생성 테스팅과 만났을 때야. 어떻게 대단한지 함께 알아보자고! 🕵️‍♀️

생성 테스팅이 뭐야? 🤖

생성 테스팅(Generative Testing)은 정말 흥미로운 개념이야. 기존의 테스트 방식과는 좀 다르거든. 어떻게 다른지 한번 비교해볼까?

기존의 테스트 방식 🧪

  • 개발자가 직접 테스트 케이스를 작성해
  • 예상되는 입력과 출력을 미리 정해놓고 테스트
  • 제한된 수의 케이스만 테스트 가능

생성 테스팅 🎲

  • 테스트 프레임워크가 자동으로 테스트 데이터를 생성
  • 다양한 케이스를 무작위로 생성해서 테스트
  • 개발자가 미처 생각하지 못한 케이스도 테스트 가능

생성 테스팅의 핵심은 뭘까? 바로 무작위성(Randomness)이야. 우리가 미처 생각하지 못한 케이스, 극단적인 상황, 경계값 등을 자동으로 테스트할 수 있다는 거지. 이게 왜 중요할까?

예를 들어볼게. 우리가 숫자를 입력받아 그 제곱을 반환하는 함수를 만들었다고 해보자.


(defn square [x]
  (* x x))

기존의 테스트 방식이라면 이렇게 테스트할 거야:


(assert (= (square 2) 4))
(assert (= (square -3) 9))
(assert (= (square 0) 0))

이렇게 하면 우리가 생각한 몇 가지 케이스는 잘 동작하는지 확인할 수 있어. 하지만 큰 숫자는 어떨까? 소수는? 아주 작은 숫자는? 이런 걸 다 일일이 테스트하기는 어렵지.

반면에 생성 테스팅을 사용하면 이렇게 할 수 있어:


(require '[clojure.spec.alpha :as s])
(require '[clojure.spec.test.alpha :as stest])

(s/fdef square
  :args (s/cat :x number?)
  :ret number?
  :fn #(= (:ret %) (* (:x (:args %)) (:x (:args %)))))

(stest/check `square)

이렇게 하면 테스트 프레임워크가 자동으로 다양한 숫자를 생성해서 square 함수를 테스트해. 큰 숫자, 작은 숫자, 음수, 소수 등 우리가 미처 생각하지 못한 케이스까지 모두 테스트할 수 있는 거지.

🎭 재능넷 팁!

프로그래밍 실력을 향상시키고 싶다면, 다양한 테스팅 기법을 익히는 것이 좋아. 재능넷에서는 테스팅 전문가들의 강의를 들을 수 있어. 생성 테스팅뿐만 아니라 다양한 테스팅 기법을 배워보는 건 어떨까?

자, 이제 Clojure.spec과 생성 테스팅이 뭔지 알았으니, 이 둘을 어떻게 함께 사용하는지 자세히 알아보자고! 🚀

Clojure.spec과 생성 테스팅의 만남 💑

Clojure.spec과 생성 테스팅이 만나면 정말 멋진 일이 벌어져. 왜 그런지 하나씩 살펴볼까?

1. 자동 데이터 생성 🤖

Clojure.spec으로 데이터의 구조를 정의하면, 생성 테스팅 프레임워크가 자동으로 그 구조에 맞는 데이터를 생성할 수 있어. 예를 들어, 아까 정의한 사용자 데이터를 보자:


(s/def ::name string?)
(s/def ::age (s/and int? #(>= % 0)))
(s/def ::email (s/and string? #(re-matches #"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$" %)))

(s/def ::user (s/keys :req-un [::name ::age ::email]))

이렇게 정의해놓으면, 생성 테스팅 프레임워크는 이 구조에 맞는 다양한 사용자 데이터를 자동으로 만들어낼 수 있어. 예를 들면 이런 식이지:


{:name "John Doe", :age 25, :email "john@example.com"}
{:name "Jane Smith", :age 30, :email "jane@test.com"}
{:name "Bob", :age 0, :email "bob@mail.co.uk"}

이렇게 자동으로 생성된 데이터를 이용해서 우리의 함수들을 테스트할 수 있어. 정말 편리하지?

2. 속성 기반 테스팅 🧪

속성 기반 테스팅(Property-based Testing)은 생성 테스팅의 핵심이야. 이게 뭐냐면, 함수의 특정 속성이 항상 참이어야 한다는 걸 검증하는 거야.

예를 들어, 우리가 문자열을 뒤집는 함수를 만들었다고 해보자:


(defn reverse-string [s]
  (apply str (reverse s)))

이 함수의 속성은 뭘까? 바로 "문자열을 뒤집은 후 다시 뒤집으면 원래 문자열이 나와야 한다"는 거야. 이걸 Clojure.spec으로 이렇게 표현할 수 있어:


(s/fdef reverse-string
  :args (s/cat :s string?)
  :ret string?
  :fn #(= (:s (:args %)) (reverse-string (:ret %))))

이렇게 정의하면, 생성 테스팅 프레임워크는 다양한 문자열을 생성해서 이 속성이 항상 참인지 검증해. 멋지지 않아?

3. 경계 케이스 자동 탐지 🕵️‍♀️

생성 테스팅의 또 다른 장점은 경계 케이스(Edge Case)를 자동으로 찾아낼 수 있다는 거야. 경계 케이스란 뭘까? 프로그램이 제대로 동작하는지 확인하기 위해 극단적인 상황을 테스트하는 거야.

예를 들어, 우리가 리스트의 첫 번째 요소를 반환하는 함수를 만들었다고 해보자:


(defn first-element [lst]
  (first lst))

이 함수의 경계 케이스는 뭘까? 바로 빈 리스트야. 빈 리스트를 넣으면 어떻게 될까? nil을 반환해야 할까, 아니면 에러를 발생시켜야 할까?

Clojure.spec과 생성 테스팅을 이용하면 이런 경계 케이스를 자동으로 찾아내고 테스트할 수 있어:


(s/fdef first-element
  :args (s/cat :lst (s/coll-of any?))
  :ret (s/nilable any?)
  :fn #(or (empty? (:lst (:args %)))
           (= (:ret %) (first (:lst (:args %))))))

이렇게 정의하면, 생성 테스팅 프레임워크는 다양한 리스트(빈 리스트 포함)를 생성해서 우리의 함수를 테스트해. 경계 케이스를 놓치지 않고 테스트할 수 있는 거지.

4. 버그 재현의 용이성 🐛

생성 테스팅의 또 다른 큰 장점은 버그를 쉽게 재현할 수 있다는 거야. 테스트 중에 버그가 발견되면, 그 버그를 일으킨 정확한 입력값을 알려줘. 이게 얼마나 편리한지 알아?

예를 들어, 우리의 reverse-string 함수에 버그가 있다고 해보자:


(defn buggy-reverse-string [s]
  (if (empty? s)
    ""
    (apply str (reverse (rest s)))))  ; 첫 글자를 빼먹는 버그!

이 함수를 생성 테스팅으로 테스트하면, 이런 결과를 볼 수 있어:


{:fail [{:args ["a"], :ret "", :fail "속성이 만족되지 않음"}],
 :result false}

이렇게 정확히 어떤 입력값("a")에서 버그가 발생했는지 알려주니까, 버그를 재현하고 수정하기가 훨씬 쉬워지는 거야.

💡 재능넷 활용 팁!

버그를 효과적으로 잡는 능력은 개발자에게 정말 중요해. 재능넷에서 버그 트래킹과 디버깅에 관한 강의를 들어보는 건 어떨까? 실력 있는 개발자들의 노하우를 배울 수 있을 거야.

자, 이제 Clojure.spec과 생성 테스팅이 만나면 어떤 멋진 일이 벌어지는지 알았지? 이제 이걸 실제로 어떻게 사용하는지 자세히 알아보자고! 🚀

Clojure.spec과 생성 테스팅 실전 활용 💪

자, 이제 실제로 Clojure.spec과 생성 테스팅을 어떻게 사용하는지 자세히 알아보자. 예제를 통해 하나씩 살펴볼 거야. 준비됐어? 출발! 🚀

1. 간단한 함수 테스트하기 🧮

먼저 간단한 함수부터 시작해볼까? 두 수를 더하는 함수를 만들고 테스트해보자.


(require '[clojure.spec.alpha :as s])
(require '[clojure.spec.test.alpha :as stest])

(defn add [a b]
  (+ a b))

(s/fdef add
  :args (s/cat :a number? :b number?)
  :ret number?
  :fn #(= (:ret %) (+ (:a (:args %)) (:b (:args %)))))

(stest/check `add)

이 코드가 하는 일을 하나씩 살펴보자:

  1. add 함수를 정의해. 단순히 두 수를 더하는 함수야.
  2. s/fdef를 사용해 add 함수의 스펙을 정의해:
    • :args는 함수의 인자를 정의해. 여기서는 두 개의 숫자를 받아.
    • :ret은 함수의 반환값을 정의해. 숫자를 반환해야 해.
    • :fn은 함수의 동작을 정의해. 여기서는 반환값이 두 인자의 합과 같아야 한다고 명시했어.
  3. stest/check를 사용해 함수를 테스트해. 이 함수가 자동으로 다양한 숫자 쌍을 생성해서 add 함수를 테스트할 거야.

이 테스트를 실행하면, 생성 테스팅 프레임워크가 다양한 숫자 쌍을 만들어서 add 함수를 테스트해. 만약 문제가 없다면 테스트는 통과할 거야.

2. 복잡한 데이터 구조 다루기 🏗️

이번에는 좀 더 복잡한 데이터 구조를 다뤄보자. 온라인 쇼핑몰의 주문 정보를 표현하는 데이터 구조를 만들고 테스트해볼 거야.


(s/def ::product-id (s/and int? pos?))
(s/def ::product-name string?)
(s/def ::price (s/and number? #(>= % 0)))
(s/def ::quantity (s/and int? pos?))

(s/def ::product (s/keys :req-un [::product-id ::product-name ::price]))
(s/def ::order-item (s/keys :req-un [::product ::quantity]))
(s/def ::order (s/coll-of ::order-item :min-count 1))

(defn calculate-total [order]
  (reduce + (map #(* (:price (:product %)) (:quantity %)) order)))

(s/fdef calculate-total
  :args (s/cat :order ::order)
  :ret number?
  :fn #(>= (:ret %) 0))

(stest/check `calculate-total)

와우, 좀 복잡해 보이지? 하나씩 뜯어보자:

  1. 먼저 제품 ID, 이름, 가격, 수량 등 기본적인 데이터 타입을 정의해.
  2. 그 다음, 이 기본 타입들을 조합해서 제품, 주문 항목, 전체 주문을 표현하는 더 복잡한 데이터 구조를 만들어.
  3. calculate-total 함수는 주문의 총액을 계산해.
  4. 함수의 스펙을 정의할 때, 입력은 우리가 정의한 ::order 타입이어야 하고, 출력은 0 이상의 숫자여야 한다고 명시했어.

이렇게 하면 생성 테스팅 프레임워크가 다양한 주문 데이터를 자동으로 생성해서 calculate-total 함수를 테스트해. 정말 편리하지?

3. 상태 변화가 있는 함수 테스트하기 🔄

이번에는 좀 더 복잡한 상황을 다뤄보자. 상태 변화가 있는 함수, 예를 들어 은행 계좌의 입출금을 처리하는 함수를 테스트해볼 거야.


(def accounts (atom {}))

(s/def ::account-id uuid?)
(s/def ::balance (s/and number? #(>= % 0)))
(s/def ::account (s/keys :req-un [::account-id ::balance]))

(defn create-account []
  (let [id (java.util.UUID/randomUUID)]
    (swap! accounts assoc id {:account-id id :balance 0})
    id))

(defn deposit [account-id amount]
  (if-let [account (get @accounts account-id)]
    (do
      (swap! accounts update-in [account-id :balance] + amount)
      true)
    false))

(defn withdraw [account-id amount]
  (if-let [account (get @accounts account-id)]
    (if (>= (:balance account) amount)
      (do
        (swap! accounts update-in [account-id :balance] - amount)
        true)
      false)
    false))

(s/fdef deposit
  :args (s/cat :account-id ::account-id :amount ::balance)
  :ret boolean?
  :fn #(if (:ret %)
         (> (:balance (get @accounts (:account-id (:args %))))
            (:balance (get @accounts (:account-id (:args %)) {:balance 0})))
         true))

(s/fdef withdraw
  :args (s/cat :account-id ::account-id :amount ::balance)
  :ret boolean?
  :fn #(if (:ret %)
         (< (:balance (get @accounts (:account-id (:args %))))
            (:balance (get @accounts (:account-id (:args %)) {:balance Double/POSITIVE_INFINITY})))
         true))

(stest/check `deposit)
(stest/check `withdraw)

우와, 이건 정말 복잡해 보이지? 천천히 살펴보자:

  1. 먼저 계좌 정보를 저장할 accounts 아톰을 만들어. Clojure에서 아톰은 동시성을 관리하는 데 사용돼.
  2. 계좌 ID와 잔액에 대한 스펙을 정의해.
  3. create-account, deposit, withdraw 함수를 정의해.
  4. depositwithdraw 함수의 스펙을 정의할 때, 함수 실행 전후의 상태 변화를 검증하도록 했어:
    • deposit이 성공하면 계좌 잔액이 증가해야 해.
    • withdraw가 성공하면 계좌 잔액이 감소해야 해.

이렇게 하면 생성 테스팅 프레임워크가 다양한 계좌 ID와 금액을 생성해서 depositwithdraw 함수를 테스트해. 상태 변화까지 정확하게 검증할 수 있어. 정말 강력하지?

🏦 재능넷 실전 팁!

금융 관련 시스템을 개발할 때는 특히 테스팅이 중요해. 재능넷에서 금융 시스템 테스팅에 관한 전문가의 강의를 들어보는 건 어때? 실제 업계에서 사용하는 테스팅 기법을 배울 수 있을 거야.

4. 비동기 함수 테스트하기 ⏳

마지막으로, 비동기 함수를 테스트하는 방법을 알아보자. 웹 API를 호출하는 함수를 예로 들어볼게.


(require '[clojure.core.async :as async])

(s/def ::user-id (s/and int? pos?))
(s/def ::username string?)
(s/def ::user (s/keys :req-un [::user-id ::username]))

(defn fetch-user [user-id]
  (async/go
    (async/<! (async/timeout 1000))  ; API 호출을 시뮬레이션
    (if (even? user-id)
      {:user-id user-id :username (str "user" user-id)}
      nil)))

(s/fdef fetch-user
  :args (s/cat :user-id ::user-id)
  :ret (s/spec (s/or :user ::user :not-found nil?))
  :fn #(if-let [user (:ret %)]
         (= (:user-id user) (:user-id (:args %)))
         true))

(defn check-fetch-user []
  (let [result (stest/check `fetch-user)]
    (if (:failure result)
      (println "Test failed:" (:failure result))
      (println "All tests passed!"))))

(check-fetch-user)

이 예제에서는 비동기 함수를 테스트하는 방법을 보여줘. 주요 포인트를 살펴보자:

  1. clojure.core.async를 사용해 비동기 동작을 구현했어.
  2. fetch-user 함수는 사용자 ID를 받아 해당 사용자 정보를 비동기적으로 가져와. 짝수 ID의 경우에만 사용자 정보를 반환하도록 했어.
  3. 함수의 스펙을 정의할 때, 반환값이 사용자 정보이거나 nil일 수 있다고 명시했어.
  4. check-fetch-user 함수를 만들어 테스트 결과를 확인할 수 있게 했어.

이렇게 하면 생성 테스팅 프레임워크가 다양한 사용자 ID를 생성해서 fetch-user 함수를 테스트해. 비동기 함수도 문제없이 테스트할 수 있어!

마무리 🎬

자, 여기까지 Clojure.spec과 생성 테스팅을 실제로 어떻게 사용하는지 다양한 예제를 통해 살펴봤어. 어때? 생각보다 강력하지?

이 기술을 사용하면:

  • 다양한 입력값에 대해 자동으로 테스트할 수 있어
  • 복잡한 데이터 구조도 쉽게 정의하고 검증할 수 있어
  • 상태 변화가 있는 함수도 정확하게 테스트할 수 있어
  • 비동기 함수까지 테스트할 수 있어

물론, 이게 전부가 아니야. Clojure.spec과 생성 테스팅은 정말 다양한 상황에서 활용할 수 있어. 실제 프로젝트에 적용해보면 그 진가를 더 실감할 수 있을 거야.

🚀 재능넷 도전 과제!

지금까지 배운 내용을 바탕으로, 자신의 프로젝트에 Clojure.spec과 생성 테스팅을 적용해보는 건 어떨까? 재능넷 커뮤니티에 결과를 공유하고 다른 개발자들과 의견을 나눠보자. 함께 성장하는 좋은 기회가 될 거야!

자, 이제 Clojure.spec과 생성 테스팅의 세계로 뛰어들 준비가 됐어? 이 강력한 도구들을 활용해서 더 안정적이고 견고한 코드를 작성해보자고! 화이팅! 💪😄

관련 키워드

  • Clojure.spec
  • 생성 테스팅
  • 속성 기반 테스팅
  • 버그 탐지
  • 자동화된 테스트
  • 함수형 프로그래밍
  • 데이터 검증
  • 경계 케이스
  • 비동기 테스팅
  • 코드 품질

지적 재산권 보호

지적 재산권 보호 고지

  1. 저작권 및 소유권: 본 컨텐츠는 재능넷의 독점 AI 기술로 생성되었으며, 대한민국 저작권법 및 국제 저작권 협약에 의해 보호됩니다.
  2. AI 생성 컨텐츠의 법적 지위: 본 AI 생성 컨텐츠는 재능넷의 지적 창작물로 인정되며, 관련 법규에 따라 저작권 보호를 받습니다.
  3. 사용 제한: 재능넷의 명시적 서면 동의 없이 본 컨텐츠를 복제, 수정, 배포, 또는 상업적으로 활용하는 행위는 엄격히 금지됩니다.
  4. 데이터 수집 금지: 본 컨텐츠에 대한 무단 스크래핑, 크롤링, 및 자동화된 데이터 수집은 법적 제재의 대상이 됩니다.
  5. AI 학습 제한: 재능넷의 AI 생성 컨텐츠를 타 AI 모델 학습에 무단 사용하는 행위는 금지되며, 이는 지적 재산권 침해로 간주됩니다.

재능넷은 최신 AI 기술과 법률에 기반하여 자사의 지적 재산권을 적극적으로 보호하며,
무단 사용 및 침해 행위에 대해 법적 대응을 할 권리를 보유합니다.

© 2024 재능넷 | All rights reserved.

댓글 작성
0/2000

댓글 0개

해당 지식과 관련있는 인기재능

안녕하세요 . 고객님들이 믿고 사용할 수 있는 프로그램을 개발하기 위해 항상 노력하고있습니다.각 종 솔루션에 대한 상담이 가능하며 , &nb...

반드시 문의 먼저 부탁드려요저는 전국 기능경기대회(정보기술 분야) 금 출신 입니다 대회준비하며 엑셀에 있는 모든기능을 사용해 보았다고 ...

  Arduino로 어떤 것이라도 개발해드립니다.​개발자 경력  ​프로그래밍 고교 졸업 아주대학교 전자공학과 휴학중 ...

안녕하세요.안드로이드 앱/라즈베리파이/ESP8266/32/ 아두이노 시제품 제작 외주 및 메이커 취미 활동을 하시는 분들과 아두이노 졸업작품을 진행...

📚 생성된 총 지식 10,859 개

  • (주)재능넷 | 대표 : 강정수 | 경기도 수원시 영통구 봉영로 1612, 7층 710-09 호 (영통동) | 사업자등록번호 : 131-86-65451
    통신판매업신고 : 2018-수원영통-0307 | 직업정보제공사업 신고번호 : 중부청 2013-4호 | jaenung@jaenung.net

    (주)재능넷의 사전 서면 동의 없이 재능넷사이트의 일체의 정보, 콘텐츠 및 UI등을 상업적 목적으로 전재, 전송, 스크래핑 등 무단 사용할 수 없습니다.
    (주)재능넷은 통신판매중개자로서 재능넷의 거래당사자가 아니며, 판매자가 등록한 상품정보 및 거래에 대해 재능넷은 일체 책임을 지지 않습니다.

    Copyright © 2024 재능넷 Inc. All rights reserved.
ICT Innovation 대상
미래창조과학부장관 표창
서울특별시
공유기업 지정
한국데이터베이스진흥원
콘텐츠 제공서비스 품질인증
대한민국 중소 중견기업
혁신대상 중소기업청장상
인터넷에코어워드
일자리창출 분야 대상
웹어워드코리아
인터넷 서비스분야 우수상
정보통신산업진흥원장
정부유공 표창장
미래창조과학부
ICT지원사업 선정
기술혁신
벤처기업 확인
기술개발
기업부설 연구소 인정
마이크로소프트
BizsPark 스타트업
대한민국 미래경영대상
재능마켓 부문 수상
대한민국 중소기업인 대회
중소기업중앙회장 표창
국회 중소벤처기업위원회
위원장 표창