private void Tick()
        {
            if (CheckTickCondition() == false)
            {
                return;
            }

            Boolean workThisTick = false;

            // ConcurrentQueue지만 락을 사용한다.
            // 락을 사용하지 않고 여러 스레드가 큐에서 로그를 가져가면, 배치 안의 로그 수가 줄어들어 효율이 떨어진다.
            // 다른 스레드에서의 Push는 큐 뒤에 쌓이므로 상관없다.
            // 다른 스레드에서의 Pop은 강제로 큐를 비우는 경우에 발생할 수 있다(팝하고 개수가 0보다 큰지 확인).
            lock (_tickLock)
            {
                _threadLocalStopwatch.Value.Restart();

                Int64 nowMS = Now.TimestampMS();
                if (IsLongTimePut(nowMS))
                {
                    UpdateLastWorkTime(nowMS);

                    // 로그가 충분하지 않을수도 있지만 보낸지 오래 되었으므로 모인 것을 보낸다.
                    Int32 popCount = CalculatePopCount();
                    workThisTick = 0 < ClearAndPopLogToThreadLocal(popCount);
                }
                else
                {
                    workThisTick = TryPopLogToThreadLocal();
                    if (workThisTick)
                    {
                        UpdateLastWorkTime(nowMS);
                    }
                }

                _threadLocalStopwatch.Value.Stop();
            }

            if (workThisTick)
            {
                ProcessThreadLocal();
            }
        }
        private void StartImpl()
        {
            lock (_lock)
            {
                if (Config == null)
                {
                    throw new LoggerStartException(StartResultType.InvalidConfig);
                }

                if (State != StateType.Stop)
                {
                    throw new LoggerStartException(StartResultType.NotStopped);
                }

                State = StateType.Starting;

                StartTime = DateTime.UtcNow;

                GenerateInstanceID();

                CreateLoggerParts();

                CreateLoggerComponents();
                InitializeLoggerComponents();
                StartLoggerComponents();

                CreateAndStartLoggerThread();

                _lastWorkTimeMS = Now.TimestampMS(StartTime);

                State = StateType.Start;
            }

            Reporter.Fatal("*Start Logger!*\n" +
                           $"Assembly Version: `{Config.AssemblyVersion}`\n" +
                           $"Build: `{BuildType}`\n" +
                           $"InstanceID: `{InstanceID}`\n" +
                           $"```Config\n{Config.ConfigStringPretty}```");
        }