면접 질문

2026. 4. 8. 11:31·📖TIL/🎤Interview

C# 23년 ~ 24년 면접 질문


 

▼ Question 다음 코드의 출력값은 무엇인가요?

using System;

class Program
{
    static void Main(string[] args)
    {
        string a = "잘";
        string b = a;

        b = "모르겠습니다";

        Console.WriteLine(a + b);
    }
}

 

▼ Answer

더보기

출력 값 : 잘모르겠습니다

 

풀이 : string a = "잘"

  •  a 에는 "잘"이 들어간다.

string b = a;

  • 이 시점의 b 도 "잘"이 됀다.

b = "모르겠습니다";

  • 이제 b 는 "모르겠습니다" 로 바뀐다.
  • 하지만 a 는 그대로 "잘" 이다.

Console.WriteLine( a + b )

  • a 와 b 를 이어 붙여서 출력하므로
  • "잘" + "모르겠습니다"
  • 결과는 잘모르겠습니다

헷갈리기 쉬운 포인트

b = a 했다고 해서 이후에 b 를 바꾸면 a 도 같이 바뀌는게 아니다.



String 의 특성에 대하여 설명해주세요.

  • 참조형이지만 Immutable ( 불변성 ) 을 가지고 있다는 점을 포함해서 답하면 좋다.

불변, Immutable 에 대하여 설명해주세요.

  • String 변수에 다른 값을 대입하면 생기는 일 ( 새로 불변 객체를 만들고 참조 등 )
    이런 과정을 설명하는 것도 좋고, 사전적인 의미를 설명해도 좋다.

정수형은 + 기호로 덧셈이 일어나고, 문자열은 합쳐진 문자열이 나오는 이유에 대해 설명해주세요.

  • 연산자 ( + 혹은 == 등 ) 오버로딩을 아는지 묻는 문제이다.
  • 이어서 단순히 string 들을 더하는 식으로 제작하면 어떤 최적화 문제가 있을 수 있는지 언급해도 좋다.

StringBuilder 에 대하여 설명해주세요.

  • 무엇인지, 왜 사용하면 좋은지, string 대신 사용해서 얻는 이점을 말하면 좋다.

▼ Question 다음 코드의 결과를 예상하고, 원인을 서술하세요.

using System;

namespace InterviewQuestion
{
    class Program
    {
        static void Main(string[] args)
        {
            int num = 1;

            for (int i = 0; i < 35; i++)
            {
                num *= 2;
                Console.WriteLine(num);
            }
        }
    }
}

 

▼ Answer

더보기

▼ 출력 값 : 
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728
268435456
536870912
1073741824
-2147483648
0
0
0
0

▼ 풀이 :

1. 반복문이 하는 일

  • num 은 처음에 1
  • 반복할 때마다 num *= 2 이므로 2배씩 커진다.
  • 출력 값은 기본적으로 2, 4, 8, 16 ... 형태로 증가한다. 

2. 갑자기 음수가 되는 이유

  • int 는 C# 에서 4바이트 ( 32비트 ) 정수형이고, 표현할 수 있는 범위는 다음과 같다.
  • 최소 값 : -2147483648
  • 최대 값 : 2147483648

그런데 값이 계속 2배가 되다가

  • 1073741824 다음에 한 번 더 2배 하면
  • 수학적으로는 2147483648

이 되어야 한다.

하지만 이 값은 int 의 최대 값 2147483647 을 넘어서기 때문에 오버플로우가 발생

그래서 실제 출력은 2147483648 이 아니라 - 2147483648 이 나온다.

 

3. 그 다음부터 0 이 되는 이유

이후 값은 이미 - 2147483648 인 상태이다.

여기서 다시 2배를 하게 되면 - 2147483648 * 2 이 된다.

32 비트 정수 범위를 다시 넘으면서 비트가 밀려나고 결과는 0 이 된다.

 

이후 0 에 2를 계속 곱해도 결과는 0 이므로 0 만 출력하게 된다.

 

4. 핵심 정리

이 코드의 핵심 원인

  • int 의 범위를 초과했기 때문
  • 정소 오버플로우 발생


출제자의 의도

  • 자료형이 런타임 도중 초과되는 숫자를 담을 경우 어떤 일이 발생하는지?

int, char 등 담을 수 있는 숫자 범위에 대해 설명해주세요.

  • 대략적인 범위를 답해도 좋고, 몇 바이트짜리인지 답하는 것도 좋다.

Uint 와 int 의 차이에 대하여 설명해주세요.

  • 사전적인 설명과 더불어 Unsigned 의 뜻과, Sign 의 뜻은 무엇인지 언급 해주는 것이 좋다.
  • 정수의 표현 방식을 설명할 수 있어야 한다

비트시프트에 대하여 설명해주세요.

  • 단어 설명도 좋지만 숫자의 2배 또는 반토막을 구현할 때 비트시프트를 사용해서 어떻게, 왜 최적화가 가능했는지 설명하면 좋다.

▼ Question 다음 코드의 출력 값 및 이유를 서술하세요.

using System;

namespace ConsoleApp2
{
    internal class Program
    {
        static void Main(string[] args)
        {
            double PI = 3.14f;

            if (PI * 2 == 6.28)
            {
                Console.WriteLine("PI의 2배는 6.28");
            }
        }
    }
}

 

▼ Answer

더보기

출력 결과 :

아무것도 출력되지 않을 가능성이 높다.

 

풀이 :

핵심은 실수 비교이다.

 

double PI = 3.14f;

 

여기서 3.14f 는 float 타입 리터널이다.

먼저 float 값으로 저장된 뒤, 그 값을 double 변수 PI 에 넣었다.

 

문제는 float 와 double 은 실수를 정확히 저장하지 못할 수 있다는 점이다.

컴퓨터는 실수를 2진수로 저장하는데, 3.14 같은 값은 내부적으로 정확히 떨어지지 않는 경우가 많다.

그래서 실제 내부 값은 우리가 눈으로 보는 3.14 , 6.28 과 미세하게 다르다.

 

PI * 2 == 6.28

 

겉보기에는 같아 보여도, 실제로는

  • PI * 2 의 내부 값
  • 6.28 의 내부 값

이 정확히 일치하지 않을 수 있어서 false 가 된다.

그래서 if 문 안으로 들어가지 못하고, 출력이 되지 않을 수 있다.

 

  • 3.14f 를 float 에 저장
  • 그 값을 double 에 대입
  • PI * 2 계산
  • 6.28 과 정확히 같은지 비교

이 과정에서 부동소수점 오차가 생길 수 있다.

 

이 문제의 핵심

  • float / double 같은 실수형은 오차가 생길 수 있다
  • 그래서 실수끼리 == 비교는 주의해야 한다


출제자의 의도

  • 부동소수점 표현 방식을 알고 있는지?

부동소수점에 대하여 설명해주세요.

  • 지수부, 가수부로 외우는 것도 좋지만, 컴퓨터는 표현을 할 때 부동소수점 방식을 왜 사용하는지 이유도 답하면 좋다.

고정소수점 방식과 부동소수점 차이에 대하여 설명해주세요.

  • 차이점 설명과 더불어, 고정소수점을 사용하면 좋은 상황을 추가로 설명하면 좋다.

▼ Question 다음 코드를 보고 출력과 그 이유를 서술하세요.

using System;

public class MyClass
{
    public delegate void MyDel();
    public MyDel OnRunning;

    public MyClass() // 생성자
    {
        int a = 0; // 지역 변수
        OnRunning = () =>
        {
            a++;
            Console.WriteLine(a);
        };
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyClass mc = new MyClass();

        mc.OnRunning?.Invoke();
        mc.OnRunning?.Invoke();
        mc.OnRunning?.Invoke();
    }
}

 

▼ Answer

더보기

출력 값 :

1

2

3

 

 

풀이 :

이유는 a 가 생성자 안의 지역 변수인데, 람다식이 그 변수를 캡처하고 있다.

 

int a = 0;
OnRunning = () =>
{
    a++;
    Console.WriteLine(a);
};

 

여기서 OnRunning 에 들어간 람다는 단순히 그 순간의 a 값을 복사해 두는 게 아니라,

변수 a 자체를 참조해서 계속 사용한다.

그래서 호출할 때마다

  • 첫 번째 호출 : a = 1
  • 두 번째 호출 : a = 2
  • 세 번째 호출 : a = 3

이전 값이 유지되면서 증가한다.

 

핵심 개념은 클로저 ( Closure ) 이다.

  • a 는 원래 생성자 안에서만 존재하는 지역 변수처럼 보이지만
    람다가 a 를 사용하고 있기 때문에 메서드가 끝난 뒤에도 a 가 살아 있는 것처럼 동작한다.

즉, 이 코드는

  • 지역 변수를 람다가 캡처
  • 그 상태가 유지되면서
  • Invoke() 할 때마다 같은 a 를 계속 증가시키는 구조이다.


▼ Question 다음 코드를 보고 출력과 그 이유를 서술하세요.

using System;
using System.Collections.Generic;

class Program
{
    static void Main(string[] args)
    {
        List<Action> actions = new List<Action>();
        for (int i = 0; i < 3; i++)
        {
            actions.Add(() => Console.WriteLine(i));
        }

        foreach (var action in actions)
        {
            action();
        }
    }
}

 

▼ Answer

더보기

출력 값 :

3

3

3

 

 

풀이 :

이유는 람다가 i 값을 그때그때 복사해서 저장한 것이 아니라 i 변수 자체를 캡처하기 때문이다.

 

for (int i = 0; i < 3; i++)
{
    actions.Add(() => Console.WriteLine(i));
}

 

겉으로 보기에는 

  • 첫 번째는 0
  • 두 번째는 1
  • 세 번째는 2

가 저장될 것처럼 보인다.

하지만 실제로는

  • 0, 1, 2 라는 값이 각각 저장되는 게 아니라
  • 같은 i 변수 하나를 참조하는 람다 3개가 리스트에 들어간다.

for 문이 모두 끝나면 i 는 3 이 됀다.

그래서 나중에 foreach 에서 각 액션을 실행할 때는 모두 같은 i 를 보고 있고, 그 값이 이미 3 이므로 3만 출력하게 됀다.

 

핵심 개념

이 문제의 핵심

  • 람다식의 클로저 ( Closure )
  • 반복문의 변수 캡처

람다는 변수의 값을 저장하는 게 아니라, 변수 자체를 캡처할 수 있다.



출제자의 의도

  • C# 언어의 Delegate 의 깊숙한 이해도가 있는지?

캡처와 클로저를 설명해주세요.

  • 캡처와 클로저에 대한 기본 설명 및, ( 만약 해당이 된다면 ) 지역변수의 변화된 생명주기까지 같이 언급하면 좋다.

사용 사례에 대해 알려주세요.

  • 특정 디자인 패턴을 사용할 때 어떤 목적으로 사용했는지, 클로저 관련하여 오작동 및 그로 인한 사례를 언급해도 좋다.

▼ Question 다음 코드를 보고 출력과 그 이유를 서술하세요.

using System;

class Program
{
    static void Main(string[] args)
    {
        Parent pc = new Child(10, 20);
    }
}

public class Parent
{
    protected Parent(int value)
    {
        Console.WriteLine("부모생성자" + value);
    }
}

public class Child : Parent
{
    public Child(int firVal, int secVal) : base(secVal)
    {
        Console.WriteLine("자식생성자" + firVal);
    }
}

 

▼ Answer

더보기

출력 값 :

부모생성자20

자식생성자10

 

 

풀이 :

 

Parent pc = new Child(10, 20);

1. main 에서 Child 객체를 생성한다.

 

 

2. 생성자는 부모가 먼저 실행됀다.

Child 는 Parent 를 상속하고 있다.

 

public Child(int firVal, int secVal) : base(secVal)

 

여기서 : base(secVal) 는 부모 생성자에 secVal 값을 전달하겠다는 뜻이다.

지금 new Child(10, 20) 이므로

  • firVal = 10
  • secVal = 20

그래서 먼저 부모 생성자가 Parent(int value) 형태로 호출되고, value 에는 20 이 들어간다.

따라서 첫 출력은 부모생성자20 이 됀다.

 

 

3. 그 다음 자식 생성자 실행

부모 생성자 실행이 끝난 뒤에 자식 생성자 본문이 실행됀다.

 

Console.WriteLine("자식생성자" + firVal);

 

여기서 firVal 은 10 이므로 자식생성자10 이 출력됀다.

 

 

핵심 정리

  • 객체 생성 시 부모 생성자가 먼저 호출된다
  • : base(secVal) 로 인해 부모 생성자에는 secVal, 즉 20이 전달된다


출제자의 의도

  • 상속을 잘 이해하고 있는지?
  • 생성자 호출 순서를 아는지?
  • Base 를 아는지?

다형성에 대하여 설명해주세요.

  • 사전적인 뜻을 설명해도 좋고, 더 나아가서 필요에 따라 부모형, interface 또는 추상형으로 형을 바꿔 활용한 예시를 언급해도 좋다.

▼ Question 다음 코드를 보고, 출력 값과 이유를 서술하세요.

using System;

class Car
{
    public void doWork()
    {
        Console.WriteLine("단순주행");
    }
}

class Tractor : Car
{
    public new void doWork()
    {
        Console.WriteLine("밭갈기");
    }
}

internal class Program
{
    static void Main(string[] args)
    {
        Car car1 = new Car();
        car1.doWork();

        Car tractor1 = new Tractor();
        tractor1.doWork();
    }
}

 

▼ Answer

더보기

출력 값 :

단순주행

단순주행

 

 

풀이 :

1. 첫 번째 호출

 

Car car1 = new Car();
car1.doWork();

 

이건 Car 객체를 만들고 Car 의 doWork() 를 호출하므로

단순주행

이 출력됀다.

 

 

2. 두 번째 호출

 

Car tractor1 = new Tractor();
tractor1.doWork();

 

여기서 헷갈리기 쉽다.

  • 실제 객체는 Tractor
  • 하지만 변수 타입은 Car

그리고 Tractor 의 메서드는 이렇다.

 

public new void doWork()

 

여기서 new 는 오버라이드 ( override ) 가 아니라 부모의 메서드를 숨김 ( hiding ) 처리한 것이다. 

 

  • Car 타입으로 보면 Car.doWork()
  • Tractor 타입으로 보면 Tractor.doWork()

지금은 변수 타입이 Car 이므로 Car의 doWork() 가 호출한다.

 

 

핵심 개념

new 와 override 의 차이

 

new

  • 부모 메서드를 재정의하는 게 아니라 숨김
  • 호출되는 메서드는 변수 타입 기준으로 결정

override

  • 부모의 virtual 메서드를 재정의
  • 호출되는 메서드는 실제 객체 타입 기준으로 결정

 

만약 밭갈기를 출력하고 싶으면?

 

1. 변수 타입을 Tractor 로 사용

 

Tractor tractor1 = new Tractor();
tractor1.doWork();

 

 

2. 다형성으로 동작

부모를 virtual, 자식을 override 로 바꾼다

class Car
{
    public virtual void doWork()
    {
        Console.WriteLine("단순주행");
    }
}

class Tractor : Car
{
    public override void doWork()
    {
        Console.WriteLine("밭갈기");
    }
}



출제자의 의도

  • 상속을 잘 이해하고 있는지?
  • Virtual, override 를 사용하지 않으면 생기는 일을 아는지?

Virtual, override 에 대해 설명해주세요.

  • 뜻 자체는 물론, 위 코드 예시처럼 virtual 을 사용하지 않았을 경우 어떤 일이 발생하는지 언급하면 좋다.
  • virtual 을 붙이게 되면 어떤 일이 발생하는지 차이를 설명해도 좋다.

가상함수 테이블에 대해 설명해주세요.

  • 뜻 그 자체와 Virtual 키워드와 묶어서 설명하면 좋다.

▼ Question 다음 코드의 출력 값 및 이유를 서술하세요.

using System;

class StaticTest
{
    static int num;

    public StaticTest()
    {
        num++;
        Console.WriteLine("num증가 " + num);
    }

    static StaticTest()
    {
        num = 12;
        Console.WriteLine("num에 12 대입 " + num);
    }
}

class Program
{
    static void Main(string[] args)
    {
        StaticTest single = new StaticTest();
        StaticTest bungle = new StaticTest();
    }
}

 

▼ Answer

더보기

출력 값 :

num에 12 대입 12

num증가 13

num증가 14

 

 

풀이 : 

1. static 생성자가 먼저 한 번 실행

 

static StaticTest()
{
    num = 12;
    Console.WriteLine("num에 12 대입 " + num);
}

 

static 생성자는 해당 클래스가 처음 사용될 때 단 한 번만 실행

new StaticTest() 로 객체를 처음 만들기 전에 클래스 초기화가 먼저 일어나므로, 가장 먼저 이 코드가 실행

그래서 첫 출력은 : num에 12 대입 12

 

 

2. 첫 번째 객체 생성

그 다음 첫 번째 new StaticTest() 가 실행되면서 인스턴스 생성자 호출

 

public StaticTest()
{
    num++;
    Console.WriteLine("num증가 " + num);
}

 

num 은 static 생성자에서 12가 되어 있으므로 출력은 num증가 13

 

 

3. 두 번째 객체 생성

두 번째 new StaticTest() 가 실행되면 다시 인스턴스 생성자가 호출

이때 num 은 static 변수라서 객체마다 따로 있는 게 아니라 클래스 전체가 공유하는 하나의 값이다.

현재 num = 13 이므로 출력은 num증가 14

 

 

핵심 개념

static 생성자

  • 클래스가 처음 사용될 때 한 번만 실행
  • 객체를 만들 때마다 실행되는 것이 아님

static 변수

  • 인스턴스마다 따로 생기지 않음
  • 클래스 전체가 하나의 값을 공유


출제자의 의도

  • Static 을 잘 이해하고 있는지?
  • Static 변수, Static 클래스, Static 함수를 잘 이해하고 있는지?

Static 함수에서 비정적 일반 멤버변수를 사용하면 어떻게 되는지 설명해주세요.

  • Static 의 특성 및 static 함수가 활용할 수 있는 것들이 무엇이 있는지 설명하면 좋다.
  • Static 질문이 들어오면 정적 객체, 또는 변수의 생명주기 언급도 좋다.

▼ Question 다음 코드에서 생길 수 있는 문제에 대하여 서술하세요.

using System;
using System.Collections;              // Question 1
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        ArrayList list = new ArrayList();

        int number = 42;
        list.Add(number);

        int retrievedNumber = (int)list[0]; // Question 2

        Console.WriteLine("저장된 값: " + retrievedNumber);
    }
}

 

▼ Answer

더보기

1. ArrayList 사용 문제

 

ArrayList list = new ArrayList();

 

ArrayList 는 비제네릭 컬렉션이라서, 어떤 타입이든 다 넣을 수 있다.

겉보기엔 편하지만 문제가 있다.

  • 타입 안정성이 없음
    > int 만 넣는다고 보장되지 않는다.
    > 나중에 string, double 등 다른 객체를 넣어도 컴파일 에러가 발생하지 않는다.
    > 위의 이유로 꺼낼 때 캐스팅 시 문제가 발생한다.
  • 값 형식 ( int )을 넣을 때 박싱 ( Boxing ) 발생
  • 꺼낼 때 다시 언박싱 ( Unboxing ) 발생

성능 면에서도 손해가 있다.

 

 

2. 강제 형변환 시 런타임 오류 가능성

 

int retrievedNumber = (int)list[0];

 

여기서는 list[0] 의 실제 타입이 정말 int 일 때만 안전하다.

지금 코드에서는 42 를 넣었으니 정상 동작한다.

다른 타입이 들어 있으면 런타임 오류가 발생할 수 있다.

 

list.Add("42");
int retrievedNumber = (int)list[0];

 

이 경우에는 컴파일은 되더라도 실행 중에 InvalidCastException 이 발생한다.

  • 컴파일 단계에서 막히지 않고 실행하다가 터질 수 있다는 문제가 있다.

 

핵심 정리

ArrayList 는 비제네릭 컬렉션

  • 타입 안정성이 떨어진다
  • 박싱 / 언박싱이 발생할 수 있다

(int)list[0] 은 강제 형변환

  • 저장된 값이 int 가 아니면 런타임에 예외 발생


출제자의 의도

  • 제네릭을 이해하고 있는지?
  • 박싱과 언박싱에 대해 이해하고 있는지?
  • ArrayList 를 얼마나 이해하고 있는지?

박싱과 언박싱에 대하여 설명해주세요

  • 참조, 값 타입, 힙 영역, 스택 영역을 담아서 설명하면 좋다.
  • Object 형식에 대한 내용까지 설명하면 좋다.

제네릭을 사용해서 얻을 수 있는 이점에 대해 설명해주세요

  • 타입 safe , 런타임 도중 결정, 박싱과 언박싱, where 키워드 등을 설명하면 좋다.

 

'📖TIL > 🎤Interview' 카테고리의 다른 글

CS, C++ 등 기타 전산 지식 질문  (0) 2026.04.08
C# / Unity 통상 질문  (0) 2026.04.08
'📖TIL/🎤Interview' 카테고리의 다른 글
  • CS, C++ 등 기타 전산 지식 질문
  • C# / Unity 통상 질문
DevHoChan
DevHoChan
맨땅에서 시작하는 코딩 도전
  • DevHoChan
    Debugging Life
    DevHoChan
  • 전체
    오늘
    어제
    • 분류 전체보기 (374)
      • 🕹️Game Life (1)
      • 🖥️Computer Science (5)
      • 📖TIL (141)
        • 🔥Projects (16)
        • 💡DevTips (5)
        • 🤔발생한 문제와 해결 (5)
        • 🔮Unity Graphics (5)
        • 🎤Interview (3)
        • ✅CodingTest (9)
      • 🚀Game Release (4)
      • 🧊Unity Basic (58)
        • 📌용어 사전 (1)
        • 에디터&인터페이스 (3)
        • 디버그 (1)
        • 라이프사이클 (4)
        • 게임오브젝트 (4)
        • 프리팹 (1)
        • 오브젝트풀링 (4)
        • 애트리뷰트 (2)
        • 트랜스폼 (4)
        • 물리&충돌 (1)
        • 프레임&델타타임 (4)
        • 코루틴&이벤트 (7)
        • 수학&보정함수 (3)
        • 디자인패턴 (9)
        • UGUI (3)
        • 벡터 ( Vector ) (3)
        • 씬 ( Scene ) (2)
        • 데이터 관리 (2)
      • ⭐C Sharp (99)
        • 📌용어 사전 (1)
        • 📌문법 사전 (6)
        • 메모리 관리 (3)
        • 00. 문법 (17)
        • 01. 변수 (3)
        • 02. 자료형 (2)
        • 03. 연산자 (6)
        • 04. 조건문 (2)
        • 05. 반복문 (2)
        • 06. 배열 (3)
        • 07. 메서드(함수) (7)
        • 08. 열거형 (3)
        • 09. 구조체 (2)
        • 10. 참조 (2)
        • 11. 객체 지향 (11)
        • 12. 델리게이트 (3)
        • 13. 디자인 패턴 (7)
        • 14. LINQ (1)
        • 📂▼자료구조 (2)
        • 15-1. 제네릭 (3)
        • 15-2. 배열 (4)
        • 15-3. 리스트 (2)
        • 15-4. 스택과 큐 (2)
        • 15-5. 딕셔너리 해시테이블 (2)
        • 15-6. 트리와 그래프 (3)
      • 📊Algorithm (16)
        • BigO (2)
        • 정렬 (4)
        • 셔플 (2)
        • 탐색 (6)
        • 최적화 (1)
      • 📝Game Design (16)
      • 🤖​AI Tools (12)
        • AI 리뷰 분석 (6)
        • Player2 (0)
        • 3D 모델링 (1)
        • 2D 스프라이트 (0)
        • 이미지 (2)
        • 사운드 (1)
        • 동영상 (1)
        • 문서 (1)
      • 🌍Network (6)
      • 🌱Github (11)
        • 기본 개념 (7)
        • 명령어 (1)
        • 도구 활용 (1)
      • ⚙️Visual Studio (5)
        • 🔧설치 및 환경설정 (2)
        • ⌨️HotKey (1)
        • 🚨디버깅 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    문법
    자료형
    gamedesign
    유니티
    unity
    자료구조
    부트캠프
    게임기획
    기획
    algorithm
    c#
    CodingTest
    til
    디자인패턴
    OOP
    메모리관리
    csharp
    객체지향
    GitHub
    게임디자인
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
DevHoChan
면접 질문
상단으로

티스토리툴바