A complete answer will require a long, long, long answer. And it could turn into opinion based examples (which is unpopular/forbidden on SO). But below I have written a few of the many things that you new to consider.
You are mixing two unrelated things together. Using a structure (a struct) doesn't prevent you from making the stack a global variable. Not using a structure doesn't prevent you from using local stack.
int stack_data[N];     // Global stack
int stack_size = 0;    // without a struct
struct stack {
    int data[N];
    int size;
};
struct stack stack = {0};   // Global stack using struct
void foo(void) {
    int foo_stack_data[N];     // Local stack
    int foo_stack_index = 0;   // without a struct
    ...
    ...
}
void bar(void) {
    struct stack bar_stack = {0};  // Local stack using struct
    ...
    ...
}
In other words - whether the stack is global or local hasn't anything to do with the use of struct.
There are several reasons for using struct. Gathering closely related variables like "stack data" and "stack size" in a struct will in many cases make you code easier to read and maintain.
As an example assume your program needs 100 stacks. Without the struct you would need 2 * 100 = 200 lines of code. With a struct stack you'll only need 100 lines (plus 4 for the definition). And this would just get worse as the number of variables related to the data structure increased.
And if you need a dynamic allocated stack a single call of malloc would do using struct while you would need 2 calls of malloc without struct.
Global variables.... hmmm, there are situations where a (few) global variables makes sense. But extensive use of global variables (nearly) always leads to a mess. A good rule is to avoid globals unless you have a very strong argument.
Look at this:
int stack_data[N];     // Global stack
int stack_size = 0;    // without a struct
void push(int value) {
    // error check omitted
    stack_data[stack_size] = value;
    stack_size = stack_size + 1;
}
void bar(void) {
    push(42);
}
Well... it will work. But... what if I need two stacks or 8 stacks. Should I then write 8 version of the push function? Doesn't sound like fun to me...
So I do:
void push(int value, int* d, int* sz) {
    // error check omitted
    d[*sz] = value;
    *sz = *sz + 1;
}
void bar(void) {
    push(42, stack_data, &stack_size);
    push(65, another_stack_data, &another_stack_size);
}
Passing the stack related variable allows me to have multiple stacks.
But I had to pass both the data and the size. Two arguments. And what if I need 5 variables to describe my data structure.... then I would have to pass 5 arguments.
Besides all the typing, it would/could also hurt performance.
By using the struct method I could do with a single argument, i.e. a pointer to a struct variable:
void push(int value, struct stack *s) {
    // error check omitted
    s->data[s->size] = value;
    s->size = s->size + 1;
}
void bar(void) {
    struct stack stack1 = {0};
    push(42, &stack1);
    struct stack stack2 = {0};
    push(65, &stack2);
    ...
}