■ 개요
○ 오늘 계획
[x] 스테이지 머스트두잇(SO) 하기
[x] 스테이지 클리어, 실패, 이동 포탈(씬이동)
[x] 포탈 스크립트, 프리펩만듬
[x] 인터렉션으로 포탈 이동
[x] 몬스터 벨패
[x] 몬스터 테스트씬 빼기
[x] 골드 보상, 명성치 계산 추가
[x] 보스 더미 넣기
■ 면접 질문 준비
1. 객체란 무엇인가요? 클래스와 어떤 연관이 있나요?
- 객체는 클래스의 인스턴스(실제 구현체)로, 데이터와 그 데이터를 조작하는 메서드를 포함하는 프로그래밍의 기본 단위입니다.
- 클래스는 객체를 생성하기 위한 설계도 또는 틀로, 객체의 속성(필드)과 동작(메서드)을 정의합니다.
- 객체(Object) : 특정한 기능을 가지고 실체하는 것. 프로그래밍에선 클래스를 기반으로 생성된 실제 데이터로 보기도 함. 클래스라는 설계도를 바탕으로 메모리에 생성된 실체
- 클래스(Class) : 클래스는 설계도 또는 청사진. 객체를 만들기 위한 틀이나 구조를 정의하는 것. 객체가 가져야 할 데이터와 그 데이터를 처리하는 방법을 클래스 안에 정의함
- 인스턴스(Instance) : 클래스를 기반으로 생성되어 메모리에 할당 된 객체.
2. 생성자에 대해 간단하게 설명해주세요.
- 생성자는 클래스가 객체로 인스턴스화될 때 호출되는 특별한 메서드로, 객체 초기화를 하는 역할로 객체가 생성될 때 자동으로 호출되며, 필드를 초기화 하는 등의 작업을 수행 함
- 생성자의 이름은 클래스 이름과 같으며 반환형이 없습니다.
- 매개변수를 통해 객체의 초기 상태를 설정할 수 있습니다.
- 객체를 생성할 때 new 키워드와 함께 호출 됩니다.
- 특징
- 객체를 초기화하는 과정에서 필요한 작업을 수행할 수 있음
- 생성자는 여러 개 정의할 수 있으며, 매개변수의 개수와 타입에 따라 다른 생성자를 호출할 수 있음. 이를 생성자 오버로딩이라고 함
- 기본적으로 매개변수가 없는 디폴트 생성자가 클래스에 자동으로 생성되지만, 사용자가 직접 정의한 생성자가 있는 경우 디폴트 생성자가 자동으로 생성되지 않음
3. 접근제한자란 무엇이며, 각각 어떤 차이가 있는지 비교해서 설명해주세요.
- 접근제한자는 클래스, 필드, 메서드 등의 접근 범위를 정의합니다
- public: 모든 클래스에서 접근 가능.
- private: 해당 클래스 내부에서만 접근 가능.
- protected: 해당 클래스와 이를 상속한 클래스에서만 접근 가능.
- internal: 같은 어셈블리 내에서 접근 가능.
- protected internal: 상속 관계 또는 같은 어셈블리에서 접근 가능.
- private protected: 상속 관계 내에서만 접근 가능하되, 같은 어셈블리 안에서만 허용.
4. static 한정자에 대해 설명해주세요.
○ 개념
- static은 클래스나 메서드, 필드가 특정 객체의 인스턴스가 아닌 클래스 자체에 속하도록 만듭니다.
- static 멤버는 객체가 아니라 클래스 자체에 속하기 때문에 객체를 생성하지 않고 접근 가능.
- 모든 인스턴스가 동일한 static 멤버를 공유합니다.
- 값은 프로그램의 실행 동안 유지됩니다(클래스가 메모리에서 해제되기 전까지).
- static 멤버는 비static 멤버(인스턴스 멤버)와 독립적으로 작동합니다.
- 비static 멤버에서는 static 멤버에 접근할 수 있지만, 반대는 불가능합니다.
○ 예시
- static 생성자
- 클래스가 처음 사용될 때 한 번만 실행되는 특별한 생성자입니다.
- static 필드의 초기화나 클래스 수준 설정에 유용합니다.
- 반환형이나 접근 제한자(public, private)를 가질 수 없습니다.
public class Database
{
public static string ConnectionString;
// static 생성자
static Database()
{
ConnectionString = "DefaultConnection";
Console.WriteLine("Static constructor called!");
}
}
// 사용
Console.WriteLine(Database.ConnectionString); // 출력: Static constructor called!
// DefaultConnection
- static 속성
- static 필드와 연결된 get 및 set 접근자를 제공합니다.
public class Configuration
{
private static string _configValue;
public static string ConfigValue
{
get { return _configValue; }
set { _configValue = value; }
}
}
// 사용
Configuration.ConfigValue = "Production";
Console.WriteLine(Configuration.ConfigValue); // 출력: Production
○ 제약 사항
- 인스턴스 멤버 접근 불가
static
메서드나 생성자에서는 인스턴스 멤버(비static 필드/메서드 등)에 접근할 수 없습니다.
- 이유:
static
멤버는 클래스 차원에서 동작하며, 특정 인스턴스와 관련되지 않기 때문입니다.
public class Example
{
public int InstanceValue = 10;
public static void StaticMethod()
{
// Console.WriteLine(InstanceValue); // 오류 발생
}
}
- static 클래스는 인스턴스화할 수 없음
- static 클래스는 직접 객체로 만들 수 없습니다
public static class Utils
{
// 메서드만 포함
}
// Utils util = new Utils(); // 오류 발생
- 상속 불가
static
클래스는 다른 클래스에서 상속받거나, 상속할 수 없습니다.
○ 개념 요약static 멤버의 메모리 할당 과정
-
클래스 로드 시점:
static 멤버는 해당 클래스가 처음 참조될 때 정적 메모리(Data Memory)에 할당됩니다.
클래스에 대한 첫 번째 접근 시, CLR이 해당 클래스의 static 생성자를 실행하면서 초기화합니다.
-
유지 기간:
프로그램 실행 동안 동일한 값을 유지하며, 프로그램이 종료되면 해제됩니다.
이로 인해 static 멤버는 전역 상태를 관리하거나 공통 데이터를 저장하는 데 적합합니다.
5. SOLID 원칙에 대해 설명해주세요.
○ 개념 요약
객체지향 설계 원칙으로 유지보수성과 확장성을 높이는 것을 목표로 합니다.
- S: 단일 책임 원칙 (SRP) - 클래스는 하나의 책임만 가져야 합니다.
- O: 개방-폐쇄 원칙 (OCP) - 기존 코드를 변경하지 않고 기능을 확장할 수 있어야 합니다.
- L: 리스코프 치환 원칙 (LSP) - 자식 클래스는 부모 클래스를 대체할 수 있어야 합니다.
- I: 인터페이스 분리 원칙 (ISP) - 필요한 인터페이스만 구현해야 합니다.
- D: 의존성 역전 원칙 (DIP) - 고수준 모듈이 저수준 모듈에 의존하지 않도록 설계.
○ 상세 설명
-
단일 책임 원칙 (Single Responsibility Principle, SRP)
- 하나의 클래스는 하나의 책임(책임이라는 것은 변경의 이유)을 가져야 함
- 클래스는 하나의 기능만 수행해야 하고, 그 기능에만 집중해야 함
- 여러 가지 역할을 수행하는 클래스를 만들면, 수정할 때 의도하지 않은 오류가 발생할 가능성이 높음
-
개방-폐쇄 원칙 (Open-Closed Principle, OCP)
- 소프트웨어 구성 요소(클래스, 모듈 등)는 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 함
- 새로운 기능을 추가할 때 기존 코드를 수정하는 대신, 기존 코드를 확장해서 기능을 추가해야 함
- 기존 기능에 영향을 주지 않으면서 새로운 기능을 쉽게 추가할 수 있음
-
리스코프 치환 원칙 (Liskov Substitution Principle, LSP)
- 하위 클래스는 상위 클래스로 치환할 수 있어야 함
- 상위 클래스의 객체를 사용하는 프로그램에서, 하위 클래스를 대신 사용해도 프로그램이 정상적으로 작동해야 함
- 하위 클래스는 상위 클래스의 계약(메서드 및 속성)을 준수해야 함
- 상위클래스가 할 줄 아는 것은 하위 클래스도 다 할 줄 알아야 함
-
인터페이스 분리 원칙 (Interface Segregation Principle, ISP)
- 클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 함
- 하나의 거대한 인터페이스를 여러 개의 작은 인터페이스로 나누어, 클라이언트가 자신에게 필요한 기능만 제공하는 인터페이스에 의존하도록 해야 함
- 인터페이스에 내용이 너무 많으면 불필요한 의존성이 생기고, 불필요한 메서드를 구현해야 할 수 있음
- 세분화 해서 꼭 필요한 기능들만 쏙쏙 빼서 쓸 수 있는 것
-
의존 역전 원칙 (Dependency Inversion Principle, DIP)
- 상위 모듈은 하위 모듈에 의존해서는 안 됨. 둘 다 추상화에 의존해야 함
- 구체적인 클래스가 아닌, 인터페이스나 추상 클래스에 의존함으로써 코드가 더 유연해지고, 의존성이 줄어듬
- 클래스 간 결합도를 낮출 수 있어, 유지 보수가 쉬워짐
6. 다형성과 이를 활용한 설계의 장점에 대해 설명해주세요.
○ 개념 요약
- 다형성(Polymorphism): 다형성은 하나의 인터페이스나 메서드를 다양한 방식으로 구현하거나 사용할 수 있는 능력을 의미
- 활용 장점:
- 코드 재사용성 증가.
- 유연한 설계 및 확장성.
- 변경이 용이한 유지보수성.
○ C#에서의 다형성
- 가상 (Virtual) 메서드
- 가상 메서드는 기본적으로 부모 클래스에서 정의되고 자식 클래스에서 재정의할 수 있는 메서드
- 가상 메서드는
virtual
키워드를 사용하여 선언되며, 자식 클래스에서 필요에 따라 override
키워드로 재정의될 수 있음
- 이를 통해 자식 클래스에서 부모 클래스의 메서드를 변경하거나 확장할 수 있음
- 추상 (Abstract) 클래스와 메서드
- 추상 클래스는 직접적으로 인스턴스를 생성할 수 없는 클래스
- 주로 상속을 위한 베이스 클래스로 사용
- 추상 클래스는
abstract
키워드를 사용하여 선언되며, 추상 메서드를 포함할 수 있음
- 추상 메서드: 구현부가 없는 메서드로, 자식 클래스에서 반드시 구현되어야 함
7. override와 overload에 대해 설명해주세요.
○ 개념 요약
- 오버라이드 (Override)
- 부모 클래스에서 이미 정의된 메서드를 자식 클래스에서 재정의하는 것을 의미
- 이는 상속 관계에 있는 클래스 간에 발생하며, 메서드의 이름, 매개변수 및 반환타입이 동일해야 함
- 객체 지향 프로그래밍의 핵심 개념인 다형성(Polymorphism)을 구현하는 데 사용
- 오버라이딩을 통해 자식 클래스는 부모 클래스의 메서드를 재정의하여 자신에게 맞는 동작을 구현할 수 있음
- 오버로드(overload)
- 동일한 메서드 이름을 가지고 있지만, 매개변수의 개수, 타입 또는 순서가 다른 여러 개의 메서드를 정의하는 것을 의미. 반환형은 오버로드 조건에 영향을 주지 않음
- 오버로딩을 통해 동일한 이름을 가진 메서드를 다양한 매개변수 조합으로 호출할 수 있음
- 하나의 메서드 이름으로 여러 동작을 수행할 수 있게 함. 오버로드를 사용하면 동일한 이름의 메서드가 다양한 타입의 데이터를 처리할 수 있음
- 오버로드를 통해 코드의 재사용성과 가독성을 높일 수 있음
○ 차이점
- 오버로드는 메서드 이름의 재사용으로 다양한 입력을 처리할 수 있게 합니다.
- 오버라이드는 상속을 통해 동작을 재정의하여 기반 클래스의 동작을 수정하거나 확장합니다.
- 오버라이드는 런타임 다형성, 오버로딩은 컴파일 타임 다형성
○ 주요 사용 사례
- 오버로드
- 동일한 작업을 수행하지만, 입력값의 타입이나 개수가 다를 때.
- 코드의 가독성과 재사용성을 높임.
- 주로 유틸리티 메서드에서 사용.
- 오버라이드
- 부모 클래스의 동작을 특정 요구사항에 맞게 수정하거나 확장할 때.
- 상속 관계에서 런타임 시 다형성(Polymorphism)을 구현.
- 주로 객체 지향 설계의 기반 클래스와 파생 클래스에서 사용.
8. 확장 메서드에 대해 설명하고 어떻게 활용했는지 알려주세요.
○ 개념
- 확장 메서드는 기존 클래스에 새로운 메서드를 추가하는 방법으로, 해당 클래스의 소스를 수정하지 않고도 기능 확장이 가능.
- 기존 타입에 새로운 메서드를 추가하는 것처럼 보이지만, 실제로는 정적 메서드(Static Method)를 활용하여 구현
- 라이브러리 확장이나 재사용성 향상에 유용하게 사용
- 활용: LINQ 메서드 추가 구현, 유틸리티 함수 정의.
○ 확장 메서드의 특징
- 정적 클래스에서 정의해야 합니다.
- 첫 번째 매개변수는 반드시 this 키워드를 사용하여 확장 대상 타입을 지정해야 합니다.
- 기존 클래스나 구조체를 변경하지 않고도 새로운 메서드를 추가하는 것처럼 사용할 수 있습니다.
- 컴파일러는 확장 메서드를 정적 메서드로 변환하여 호출합니다.
- 네임스페이스를 포함하여 호출하는 곳에서 using 지시문으로 가져와야 사용할 수 있습니다.
○ 확장 메서드 정의와 사용법
- 정의
확장 메서드는 정적 클래스로 정의되어야 하며, 첫 번째 매개변수 앞에 this 키워드를 붙여서 확장할 대상 타입을 지정합니다.
public static class StringExtensions
{
// 문자열에 단어 수를 세는 메서드 추가
public static int WordCount(this string str)
{
if (string.IsNullOrWhiteSpace(str))
return 0;
return str.Split(' ', StringSplitOptions.RemoveEmptyEntries).Length;
}
}
- 사용
확장 메서드는 해당 타입의 인스턴스 메서드처럼 사용할 수 있습니다.
using System;
class Program
{
static void Main()
{
string sentence = "Hello world from C#";
// 확장 메서드 호출
int count = sentence.WordCount();
Console.WriteLine($"Word count: {count}"); // 출력: Word count: 4
}
}
○ 확장 메서드의 동작 원리
- 확장 메서드는 실제로는 정적 메서드로 호출됩니다.
- 위의 예제에서 sentence.WordCount()는 다음과 같이 변환됩니다
int count = StringExtensions.WordCount(sentence);
- 즉, 컴파일러가 자동으로 확장 메서드를 정적 메서드 호출로 변환합니다.
○ 주요 사용 사례
(1) 기존 클래스의 기능 확장
- .NET의 기본 제공 클래스(System.String, System.Int32 등)에 새로운 기능을 추가할 때 사용됩니다.
public static class IntExtensions
{
// 정수의 제곱 계산 메서드 추가
public static int Square(this int number)
{
return number * number;
}
}
class Program
{
static void Main()
{
int value = 5;
// 확장 메서드 호출
Console.WriteLine(value.Square()); // 출력: 25
}
}
(2) 컬렉션 클래스와 LINQ에서 활용
- LINQ의 많은 기능은 확장 메서드를 기반으로 구현되어 있습니다.
using System;
using System.Linq;
class Program
{
static void Main()
{
var numbers = new[] { 1, 2, 3, 4, 5 };
// LINQ 확장 메서드 사용
var evenNumbers = numbers.Where(n => n % 2 == 0);
Console.WriteLine(string.Join(", ", evenNumbers)); // 출력: 2, 4
}
}
(3) 코드 가독성 향상
- 특정 타입에 자주 사용되는 동작을 캡슐화하여 더 직관적인 코드 작성을 돕습니다.
public static class DateTimeExtensions
{
public static bool IsWeekend(this DateTime date)
{
return date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday;
}
}
class Program
{
static void Main()
{
DateTime today = DateTime.Now;
// 오늘이 주말인지 확인
Console.WriteLine(today.IsWeekend() ? "It's weekend!" : "It's a weekday.");
}
}
○ 장점
-
상속 없이 기능 확장:
기존 클래스를 상속하지 않고도 메서드를 추가할 수 있습니다.
특히, sealed 클래스(System.String 등)에도 적용 가능합니다.
-
기존 코드 수정 불필요:
기존 타입이나 클래스 코드를 수정하지 않고도 새로운 기능을 추가할 수 있습니다.
-
가독성과 코드 재사용성 향상:
자주 사용되는 기능을 메서드 형태로 캡슐화하여 간결하고 직관적인 코드를 작성할 수 있습니다.
9. 콜백이란 무엇인가요? 콜백을 사용해본 경험이 있을까요?
○ 개념
- 다른 메서드에 인수로 전달된 메서드가 특정 조건이 만족되었을 때 다시 호출되는 방식을 의미. 즉, 콜백 함수는 다른 함수에 의해 호출되는 함수
- 콜백은 일반적으로 위임(delegate), 이벤트(event), 또는 표준 델리게이트를 사용하여 구현
- 콜백을 사용하면 메서드를 더 유연하게 만들 수 있고, 다른 메서드가 끝난 후에 실행할 작업을 지정할 수 있습니다.
○ 장점
- 비동기 작업 처리: 긴 작업을 실행하면서, 완료 후에 수행할 작업을 콜백으로 전달하여 효율적인 비동기 처리가 가능합니다.
- 유연성 증가: 콜백을 사용하면 동적으로 실행될 메서드를 변경할 수 있기 때문에 코드의 유연성과 재사용성을 높일 수 있습니다.
- 이벤트 기반 프로그래밍: 이벤트와 콜백을 함께 사용하면, 상태 변경에 따른 동작을 관리하는 데 유리합니다.
○ 단점
- 디버깅 어려움: 콜백이 사용되는 코드 흐름이 간접적이기 때문에, 디버깅이 어려워질 수 있습니다.
- 콜백 중첩: 콜백 메서드가 계속해서 중첩될 경우, 코드가 복잡해지고 가독성이 떨어질 수 있습니다.
○ 요약
- 콜백은 다른 함수나 메서드에 인수로 전달된 함수가 특정 조건에서 호출되는 방식입니다.
- C#에서는 위임(Delegate)을 사용하여 콜백을 구현합니다.
- 비동기 처리, 이벤트, 데이터 처리 등 다양한 상황에서 활용됩니다.
- 콜백은 코드의 유연성을 높이고, 동적 작업 실행을 가능하게 합니다.
10. 델리게이트(delegate; 대리자)란 무엇인가요?
○ 개념
- 델리게이트는 메서드를 참조할 수 있는 타입으로, 메서드를 동적으로 호출하거나 전달하는 데 사용.
- 델리게이트를 이용하면 메서드를 매개변수로 전달하거나 변수에 할당할 수 있음
- 델리게이트는 여러 메서드를 연결할 수 있으며, 필요에 따라 다른 메서드를 호출할 수 있음
○ 특징
- 델리게이트에 지정할 수 있는 메서드는 델리게이트 타입과 매개변수 타입 및 반환 타입이 일치해야 합니다.
- 다중 캐스팅이 가능합니다. 즉, 하나의 델리게이트 인스턴스에 여러 메서드를 추가하여 순차적으로 실행할 수 있습니다.
- 델리게이트는 메서드를 변수처럼 다루는 방법을 제공합니다.
○ 장점
- 유연성: 델리게이트는 메서드를 변수처럼 다룰 수 있어서, 메서드의 동적 할당 및 실행이 가능합니다.
- 이벤트 및 콜백 처리: 델리게이트는 이벤트와 콜백 처리를 쉽게 구현할 수 있도록 돕습니다.
- 다중 메서드 호출: 델리게이트는 여러 메서드를 하나에 묶어 순차적으로 호출할 수 있습니다.
○ 단점
- 디버깅 어려움: 델리게이트를 사용하는 코드 흐름이 간접적이기 때문에, 디버깅 시 추적이 어려울 수 있습니다.
- 콜백의 복잡성: 여러 개의 메서드를 델리게이트에 추가하거나, 콜백을 중첩하면 코드가 복잡해질 수 있습니다.
○ 요약
- 델리게이트는 메서드를 변수처럼 다루는 객체로, 메서드를 다른 메서드에 전달하거나 동적으로 호출할 수 있습니다.
- 델리게이트는 타입 안전한 함수 포인터로서, 이벤트와 비동기 처리, 동적 메서드 실행 등에 유용하게 사용됩니다.
델리게이트는 다중 캐스팅을 지원하여 여러 메서드를 순차적으로 호출할 수 있습니다.
11. C#의 event란 무엇인가요?
○ 개념
- event는 특정 조건이 만족되었을 때 등록된 메서드를 호출하는 방식으로 사용, 델리게이트를 기반으로 동작.
- 델리게이트와 비슷하지만, 더 제한적인 방식으로 동작함
- 이벤트 구독자는 이벤트 핸들러 메서드를 추가하거나 제거할 수 있지만, 이벤트 자체를 외부에서 직접 호출할 수 없음. 호출은 이벤트를 선언한 클래스 내에서만 가능함
- 보통 클래스 외부에서는 이벤트에 메서드를 구독(subscribe)하거나 해지(unsubscribe)만 할 수 있음
○ 델리게이트와 이벤트 차이점
- 델리게이트는 좀 더 유연하고 자유롭게 메서드를 다룰 수 있음
- 이벤트는 [구독-발행] 패턴에서 좀 더 안전하고 제한된 방법으로 동작하게 설계된 것
12. Unity에서 사용하는 델리게이트 혹은 이벤트에는 어떤 것이 있나요?
- Unity에서 주로 사용되는 델리게이트/이벤트:
- UnityAction과 UnityEvent: Unity 이벤트 시스템의 핵심.
- MonoBehaviour 이벤트 메서드: Update(), OnCollisionEnter(), 등.
- Custom Event: 게임 로직에 필요한 사용자 정의 이벤트.