Typescript: getter ๋ฐ setter์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ์•ก์„ธ์Šค ์ˆ˜์ •์ž

์— ๋งŒ๋“  2015๋…„ 04์›” 21์ผ  ยท  40์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: microsoft/TypeScript

getter ๋ฐ setter์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ์•ก์„ธ์Šค ์ˆ˜์ •์ž๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ์ด๋Ÿฐ ์‹์œผ๋กœ setter๋Š” ์˜ˆ๋ฅผ ๋“ค์–ด private/protected์ด๊ณ  getter๋Š” public์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” ๊ฐ’์ด ์ฝ๊ธฐ ์ „์šฉ์ผ ๋•Œ ์ •๋ง ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

class MyClass {
    private _myProp: any;
    private set myProp(value: any) {
        this._myProp = value;
    }
    public get myProp(): any {
        return this._myProp;
    }
}
Declined Suggestion Too Complex

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์–ด์จŒ๋“  ์ด๊ฒƒ์„ ์œ„ํ•ด ๋‚ด +1์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค. ๋‚˜์ค‘์— ๋‹ค์‹œ ๊ณ ๋ ค๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ ...

๋ชจ๋“  40 ๋Œ“๊ธ€

12

#12๊ฐ€ #6532๋กœ ์ข…๋ฃŒ๋˜์—ˆ์œผ๋ฏ€๋กœ ์ด์ œ ์ด ๋ฌธ์ œ๋Š” ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์ด์ œ ๋‹ค๋ฅธ ์•ก์„ธ์Šค ์ˆ˜์ •์ž๋ฅผ ๊ตฌํ˜„ํ•  ๊ณ„ํš์ด ์žˆ์Šต๋‹ˆ๊นŒ?
readonly ๋Š” ์†์„ฑ์ด ์‹ค์ œ๋กœ ํด๋ž˜์Šค ๋‚ด์—์„œ ์“ฐ๊ธฐ ๊ฐ€๋Šฅํ•˜๋‹ค๊ณ  ์—ฌ๊ธฐ์—์„œ ์„ค๋ช…ํ•˜๋Š” ๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ด€๋ จ ๋ฌธ์ œ์—์„œ ๋‚ด ์˜ˆ๋ฅผ ์—ฌ๊ธฐ๋กœ ์˜ฎ๊ฒจ์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

declare abstract class Emitter {
    new (): Emitter;
    on: (name:string, handler: (arg:any) => void) => void;
    off: (name:string, handler: (arg:any) => void) => void;
    protected emit: (name:string, arg:any) => void;
}

class Person extends Emitter {
    constructor(name:string) {
        super();
        this.name = name;
    }

    private _name:string;
    get name() {
        return this._name;
    }
    set name(value) {
        if (this._name !== value) {
            this._name = value;
            this.emit('change:name', value);
            //this way is better
            this.updatedAt = new Date();
            //than this way
            this.setUpdatedAt(new Date());
        }
    }

    ////
    private _updatedAt:Date;
    get updatedAt() {
        return this._updatedAt;
    }
    private set updatedAt(value) { //Getter and setter do not agree in visibility
                //some logic and a simple readonly (our absence of a setter) is not enough
        if (this._updatedAt !== value) {
            this._updatedAt = value;
            this.emit('change:updatedAt', value);
        }
    }

    //// method implementation - but what's the point in it?
    private setUpdatedAt(value) {
        if (this._updatedAt !== value) {
            this._updatedAt = value;
            this.emit('change:updatedAt', value);
        }
    }
}

const entity = new Person('Mike');
entity.on('change:updatedAt', console.log.bind(console));
entity.name = 'Thomas';
//but manually setting updatedAt should be forbidden
entity.updatedAt = new Date(); //restricted

์—ฌ๊ธฐ์„œ updatedAt ์†์„ฑ์€ ์‹ค์ œ๋กœ setter ๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ Person ์™ธ๋ถ€์—์„œ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค . ๊ฒŒ๋‹ค๊ฐ€ ์ด setter๋Š” ๋ณต์žกํ•œ ๋กœ์ง์„ ํฌํ•จํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ๋‹จ์ˆœํ•œ readonly ๋˜๋Š” setter์˜ ๋ถ€์žฌ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

private setter๋Š” ์ถ”๊ฐ€ ๋…ผ๋ฆฌ(์˜ˆ: ๋ฐฉ์ถœ)๊ฐ€ ์žˆ๋Š” private ๋ฉ”์„œ๋“œ์— ๋Œ€ํ•œ ๊ตฌ๋ฌธ ์„คํƒ•์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•˜์ง€๋งŒ ํ•„๋“œ์™€ ๊ด€๋ จ๋œ ๋…ผ๋ฆฌ์˜ ์ผ๋ถ€๊ฐ€ ์†์„ฑ(getter)์— ์žˆ๊ณ  ๋‹ค๋ฅธ ๋…ผ๋ฆฌ๊ฐ€ ๋ฉ”์„œ๋“œ(private setter)์— ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” ์ผ๊ด€์„ฑ์ด ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. .

์ด ๋ฐฉ๋ฒ•์œผ๋กœ getters/setters๋Š” C# ์—์„œ ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. ์ด ๊ณ„์•ฝ์€ ๋Ÿฐํƒ€์ž„์— ์†์‹ค๋˜์ง€๋งŒ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ๋‹ค๋ฅธ ๊ฐ€์‹œ์„ฑ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ๊ถŒ์žฅํ•˜๋Š” ๊ฒƒ์€ ๊ณต๊ฐœ ์ฝ๊ธฐ ์ „์šฉ getter์™€ ๊ฐœ์ธ/๋ณดํ˜ธ๋œ ์ง€์› ํ•„๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ ‘๊ทผ์ž๋Š” ์œ ํ˜• ์‹œ์Šคํ…œ์˜ ์†์„ฑ๊ณผ ๋Œ€์นญ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ•˜๋Š” ๋ชจ๋“  ์ผ์€ ์œ ํ˜•์— ๋ช…์‹œ๋˜์–ด์•ผ ํ•˜๊ณ  ์†์„ฑ์— ํ‘œํ˜„ ๊ฐ€๋Šฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. private_set/public_get์„ ํ™œ์„ฑํ™”ํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ์ ‘๊ทผ ์ˆ˜์ •์ž๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ์–ธ์–ด์˜ ๋ณต์žก์„ฑ๊ณผ ํ•™์Šต ๊ณก์„ ์ด ์ฆ๊ฐ€ํ•˜๊ณ  ์—ฌ๊ธฐ์„œ ์–ป์€ ๊ฐ’์€ ์ถ”๊ฐ€๋œ ๋ณต์žก์„ฑ๊ณผ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์–ด์จŒ๋“  ์ด๊ฒƒ์„ ์œ„ํ•ด ๋‚ด +1์„ ์ถ”๊ฐ€ํ•˜์‹ญ์‹œ์˜ค. ๋‚˜์ค‘์— ๋‹ค์‹œ ๊ณ ๋ ค๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ ...

๋‚˜๋Š” ์•„์ง๋„ ์ด๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ๋‹ค. C#์—๋Š” ์ด ๊ธฐ๋Šฅ์ด ์žˆ์œผ๋ฉฐ ํŠนํžˆ ํด๋ž˜์Šค ์™ธ๋ถ€์—์„œ ์ฝ๊ณ  ์‹ถ์ง€๋งŒ ๋‚ด๋ถ€์ ์œผ๋กœ๋งŒ private/protected๋กœ ์„ค์ •๋˜๋Š” ํ”Œ๋ž˜๊ทธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ๋งŽ์€ ์ƒํ™ฉ์—์„œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ž์ฃผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ œ์•ˆ์€ ํŒจํ„ด์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์—์„œ ํฌ๊ทน์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์–ธ์–ด์— ์ข‹์€ ์ถ”๊ฐ€ ์‚ฌํ•ญ์ž…๋‹ˆ๋‹ค. (ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํ”„๋กœ๊ทธ๋ž˜๋จธ์˜ ๊ด€์ ์—์„œ) ์ถ”๊ฐ€๋˜๋Š” ๋ณต์žก์„ฑ์˜ ์–‘์€ ์ ์Šต๋‹ˆ๋‹ค. ๊ฐœ๋…์€ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋ฒ”์œ„ ์ง€์ •์œผ๋กœ ์ธํ•ด getter ๋˜๋Š” setter์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†๋Š” ์ด์œ ๋ฅผ ์•”์‹œํ•˜๋Š” ์ข‹์€ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์œ„์˜ ์‚ฌ์šฉ์ž์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„์˜ ๋‹ค๋ฅธ ์–ธ์–ด์˜ ํ‘œ์ค€์ž…๋‹ˆ๋‹ค. ์ด์— ๋Œ€ํ•œ ์ฃผ์žฅ์€ ์ค‘์š”ํ•˜์ง€ ์•Š์œผ๋ฉฐ ๊ตฌํ˜„์„ ์žฌ๊ณ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ์‹ค์ œ๋กœ ๋‹น์‹ ์ด TS์—์„œ ์ด๊ฒƒ์„ ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์— ๋†€๋ž์Šต๋‹ˆ๋‹ค ... ๋ฌธ์ œ์— +1.
์ด๊ฒƒ์œผ๋กœ ํ•™์Šต ๊ณก์„ ์ด ์ฆ๊ฐ€ํ•ด์„œ๋Š” ์•ˆ๋ฉ๋‹ˆ๋‹ค.

private get x() { ... }
public set x(value) { ... }

์˜์–ด๋ฅผ ์ฝ์„ ์ˆ˜ ์žˆ๋‹ค๋ฉด ์—ฌ๊ธฐ์—์„œ private(protected)/public์ด ๋ฌด์—‡์„ ์˜๋ฏธํ•˜๋Š”์ง€ ์ž๋ช…ํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์ฒ˜์Œ์— ์ ‘๊ทผ์ž๋ฅผ ์ •์˜ํ•˜๋Š” ๊ฒฝ์šฐ - ์ด๋ฏธ ์ ‘๊ทผ์ž๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ๊ณ  ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ถ”์‹  ์˜ค๋ฅ˜ ์ •๋ณด: "Getter ๋ฐ setter ์ ‘๊ทผ์ž๊ฐ€ ๊ฐ€์‹œ์„ฑ์— ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค." - ๊ธ€์Ž„: ์ด๊ฒƒ์ด ๋ฐ”๋กœ ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์€ ์ด๊ฒƒ์ด ํŽธ๋ฆฌํ•œ ๋‘ ๊ฐ€์ง€ ์‚ฌ์šฉ ์‚ฌ๋ก€์ž…๋‹ˆ๋‹ค.

.get() ๋ฐ .set() ํ˜ธ์ถœ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด Backbone.js:

class Whatever {
    public get rotation(): number {
        return this.get('rotation');
    }
    private set rotation(rotation: number) {
        this.set('rotation', rotation);
    }
}

์„œ๋ธŒํด๋ž˜์Šค๊ฐ€ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ:

class ExtendMe {
    public get someProperty(): string {
        // some stuff
    }
    protected set someProperty(prop: string) {
        // some stuff
    }
}

TypeScript๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ•œ ์ดํ›„๋กœ ์ €๋ฅผ ๊ดด๋กญํžˆ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์„ ์š”์ฒญํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์˜ ์˜๊ฒฌ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฉ๊ธˆ ๊ณต๊ฐœ get() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ–ˆ๊ณ  ๋‚ด ์ง‘ํ•ฉ๊ณผ get์ด ๊ฐ€์‹œ์„ฑ์— ๋Œ€ํ•ด ๋™์˜ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์— ๋†€๋ž์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๊ทธ๊ฒƒ์ด ๋„ˆ๋ฌด ๋ณต์žกํ•˜๋‹ค๊ณ  ์ฃผ์žฅํ•˜๋Š” ๋‹น์‹ ๋“ค์„ ์ฝ์—ˆ์Šต๋‹ˆ๋‹ค. "C++ ๋ฐฉ์‹"์ด ๋‹ค์Œ๊ณผ ๋‹ค๋ฅธ ์ด์œ ๋ฅผ ๊ธฐ์–ตํ•˜์‹ญ์‹œ์˜ค.

private _myAttribute: string;
get myAttribute(): string {...}
setMyAttribute(value: string) {...}

๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ๋งŽ์€ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์ œ๊ฐ€ ์ง€๊ธˆ ์—ฌ๊ธฐ ์žˆ์Šต๋‹ˆ๋‹ค.
myAttribute๋ฅผ ๊ณต๊ฐœ์ ์œผ๋กœ ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ํ•ด๋‹น ํด๋ž˜์Šค ๋‚ด์—์„œ๋งŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?
์†์„ฑ์ด ์ˆ˜์ •๋  ๋•Œ๋งˆ๋‹ค ์ผ๋ถ€ ์‚ฌ์šฉ์ž ์ •์˜ ๋…ผ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ฉ๋‹ˆ๊นŒ?
๋น„์ฆˆ๋‹ˆ์Šค ๊ทœ์น™์ด ๋  ์ˆ˜๋„ ์žˆ๊ณ  ๋””๋ฒ„๊น… ๋ชฉ์ ์„ ์œ„ํ•œ ์ค‘๋‹จ์  ์กฐ๊ฑด๊ณผ ํ•จ๊ป˜ ํŠน์ • ๊ฐ’์ด ํ• ๋‹น๋œ ์ด์œ ๋ฅผ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•œ ๋กœ๊น…์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋Œ€์‹  ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ด๊ฒŒ ํ•˜๋Š” ๊ตฌ๋ฌธ ์„คํƒ•๊ณผ ํ•จ๊ป˜ ์†์„ฑ์„ ์ˆ˜์ •ํ•  ๋•Œ๋งˆ๋‹ค ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค.
C#์€ ์ด์— ๋Œ€ํ•œ ์†์„ฑ์˜ ๊ฐœ๋…์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  TS๊ฐ€ ๊ทธ ๊ฐœ๋…์„ ๊ณ„์Šนํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ๋‹ค๋ฅธ ์ ‘๊ทผ์„ฑ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์€ ๋‚˜์™€ ๊ฐ™์€ ์ƒ๊ฐ์„ ํ•˜๊ณ  ์šฐ๋ฆฌ๋ฅผ "C++ ์Šคํƒ€์ผ"๋กœ ๋˜๋Œ์•„๊ฐ€๊ฒŒ ๋งŒ๋“œ๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํฐ ํ•œ๊ณ„์ž…๋‹ˆ๋‹ค.

"๋„ˆ๋ฌด ์–ด๋ ค์›Œ"๋ผ๊ณ  ํ•ด์„œ ์—„์ฒญ๋‚˜๊ฒŒ ์œ ์šฉํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์„ ์ด์œ ๊ฐ€ ๋˜์–ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

๋‚ด +1์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๋ฉด์—์„œ ๋„ˆ๋ฌด๋„ ์™„์ „ํ•œ ์–ธ์–ด๋กœ ๋‹น์‹ ์ด ์ด๊ฒƒ์„ ํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด ์ œ๊ฒŒ๋Š” ๋งค์šฐ ์ด์ƒํ•˜๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๊ฐ€ ์ข…๋ฃŒ๋œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜์–ด ๋†€๋ž์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์€ ์ปค๋ฎค๋‹ˆํ‹ฐ์—์„œ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. ๋‹ค์‹œ ์—ด์–ด์ฃผ์„ธ์š”.
+1

12์—์„œ๋Š” ์ด ๋ฌธ์ œ๋ฅผ ๋‹ค๋ฃจ์ง€ ์•Š์œผ๋ฏ€๋กœ ์ด ๋ฌธ์ œ๋ฅผ ์–ธ๊ธ‰ํ•˜๋Š” ์ฃผ์„์œผ๋กœ ์ด ๋ฌธ์ œ๋ฅผ ์ข…๋ฃŒํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

IMHO ์ด๊ฒƒ์€ ์ข‹์€ ๊ธฐ๋Šฅ์ด์ง€๋งŒ ๋‚ด๊ฐ€ ์ดํ•ดํ•˜๋Š” ํ•œ ๊ณต์ •ํ•ฉ๋‹ˆ๋‹ค. "๊ธ€์Ž„, ๋‚˜๋Š” ๋งค๋ฒˆ _property๋ฅผ ์“ฐ๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹ ์— private set ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค"๋ผ๋Š” ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค.

TypeScript ํ•ต์‹ฌ ์ฝ”๋“œ ์ž์ฒด์— ์—„์ฒญ๋‚œ ๋ณต์žก์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ์„ ํƒ์ด ์žˆ๋Š” ๊ฒฝ์šฐ(๊ธฐ์–ตํ•˜์‹ญ์‹œ์˜ค, ๋” ๋ถˆํ•„์š”ํ•œ ๋ณต์žก์„ฑ - ๊ฐœ๋ฐœ ์†๋„ ๊ฐ์†Œ, ๋””๋ฒ„๊ทธ์— ๋” ๋งŽ์€ ์‹œ๊ฐ„, ๊ฒฐ๊ตญ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ - ๋œ ๋นˆ๋ฒˆํ•œ ๋ฆด๋ฆฌ์Šค) ๊ธฐํ˜ธ 1๊ฐœ ์“ฐ๊ธฐ ๋˜๋Š” ์“ฐ๊ธฐ ๊ทธ 1 ์‹ฌ๋ณผ์„ ์ž˜ ์ฒ˜๋ฆฌํ•˜๊ณ  ... ์ฐจ๋ผ๋ฆฌ 1 ์‹ฌ๋ณผ์„ ๋งค๋ฒˆ ํ•œ ๋ฒˆ ๋” ์“ฐ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ ์ €๋Š” TS ์ฝ”์–ด์— ๊ธฐ์—ฌํ•œ ์‚ฌ๋žŒ์ด ์•„๋‹ˆ๋ฉฐ ์ด ์„คํƒ•์˜ ๊ฐ€๋Šฅํ•œ ๋ณต์žก์„ฑ์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋”œ๋ธŒ๋ ˆ์ด์ปค๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋˜ํ•œ ๊ตฌํ˜„ํ•˜๊ธฐ์— ๋„ˆ๋ฌด ๋ณต์žกํ•œ ์š”์ฒญ์„ ๋ฐœ๊ฒฌํ•˜๋Š” ๋ฐ๋Š” ์šฉ๊ธฐ์™€ ์ง€ํ˜œ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค(๊ฒฐ๊ณผ์ ์œผ๋กœ ์ „์ฒด ์ฝ”๋“œ ๋ณต์žก์„ฑ์ด ์ฆ๊ฐ€ํ•จ). ๋”ฐ๋ผ์„œ TypeScript๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ์—ฌ๋Ÿฌ๋ถ„๊ป˜ ๊ฒฝ์˜๋ฅผ ํ‘œํ•˜๊ณ  ์ž‘์—…์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค!

(ps๋Š” ์™œ ์•ˆ๋˜๋Š”์ง€ ๋ฐฐ์šฐ๊ธฐ ์œ„ํ•ด ์—ฌ๊ธฐ์— ์™”์Šต๋‹ˆ๋‹ค - ๊ฒฐ๊ตญ ๋‚ด ๋งˆ์Œ์ด ๋ฐ”๋€Œ์—ˆ๊ณ  ์ด๊ฒƒ์„ ๋‹ค๋ฃฐ ๊ฒƒ์ž…๋‹ˆ๋‹ค._property = ...
๊ทธ๋ฆฌ๊ณ  ์—ฌ์ „ํžˆ ํ–‰๋ณตํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค)

@idchlife set ์†์„ฑ ๋ชฉํ‘œ๋Š” ๊ฐ’์„ ํ• ๋‹นํ•  ๋•Œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ฐ‘์ค„ ํ•˜๋‚˜๋ฅผ ์ €์žฅํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹™๋‹ˆ๋‹ค. set ํ”„๋กœ์„ธ์Šค์— ์ผ๋ถ€ ๋…ผ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ์—ฌ์‹ญ์‹œ์˜ค. ์ด๊ฒƒ์€ ๋ถ„๋ช…ํžˆ ๋งค์šฐ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.

+1 ๋‚˜๋Š” ์ด๊ฒƒ์„ ์žฌ๊ฒ€ํ† ํ•˜๋Š” ๊ฒƒ์„ ๋ณด๊ณ  ์‹ถ๋‹ค.

๋‹ค๋ฅธ ๋งŽ์€ ์–ธ์–ด๊ฐ€ ์ด๋ฏธ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ๋•Œ "์ด๊ฒƒ์€ ํ˜ผ๋ž€์„ ์ผ์œผํ‚ฌ ๊ฒƒ"์ด๋ผ๋Š” ๋…ผ๋ฆฌ๊ฐ€ ๋งค์šฐ ์ด์ƒํ•ฉ๋‹ˆ๋‹ค.

๋ชจ๋“  ๐Ÿ‘๊ฐ€ ๋ณ„ ์ผ์„ ํ•˜๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๐Ÿ‘ ๋Œ“๊ธ€ ํ•˜๋‚˜๋งŒ ๋” ๋‹ฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋” ์ฝ๊ธฐ ์‰ฝ๊ณ  ๋น ๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ๋„์›€์ด๋˜๋Š” ๊ตฌ๋ฌธ ์„คํƒ•์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Typescript๋ฅผ ํฌํ•จํ•˜์—ฌ ๋งŽ์€ ์–ธ์–ด์— ๊ตฌ๋ฌธ ์„คํƒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ์ข‹์€ ์ด์œ ๊ฐ€ ์—†๋Š” ๊ฒƒ ๊ฐ™๊ณ  ๋„ˆ๋ฌด ๋ณต์žกํ•˜๋‹ค๊ณ  ํ•ด์„œ ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ์ข‹์€ ์ด์œ ๊ฐ€ ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋„ˆ๋ฌด ๋ณต์žกํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์€ ๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ๋žŒ๋“ค์ด ์†Œํ”„ํŠธ์›จ์–ด ์—”์ง€๋‹ˆ์–ด๋ง์— ๋Œ๋ฆฌ๋Š” ์ด์œ  ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๋ณต์žกํ•œ ๋ฌธ์ œ๋ฅผ ๊ทธ๋ ‡๊ฒŒ ๋ณต์žกํ•˜์ง€ ์•Š์€ ๋ฐฉ์‹์œผ๋กœ ํ•ด๊ฒฐํ•˜์‹ญ์‹œ์˜ค. ๋ฆฌํŒฉํ† ๋ง๊ณผ ์œ„ํ—˜ํ•œ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•ฉ๋‹ˆ๊นŒ? ์–ด์ฉŒ๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์—ฌ์ „ํžˆ ๋ฐ”๋žŒ์งํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์–ธ์–ด๋Š” get ๋ฐ set ๊ธฐ๋Šฅ์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ๊ฐ€์‹œ์„ฑ์„ ์ง€์›ํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ชจ์š•์— ์ƒ์ฒ˜๋ฅผ ์ฃผ๊ธฐ ์œ„ํ•ด Typescript๋Š” C#๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Microsoft์—์„œ ๋งŒ๋“ค์ง€๋งŒ ํ›„์ž๋Š” ์™„์ „ํžˆ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

public string myPropertyWithLimitedAccess { get; private set; }   

์ €๊ฒƒ ๋ด. ์•„๋ฆ„๋‹ต๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ๊ณ  ์ „ํ˜€ ๋ณต์žกํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/auto-implemented-properties

์ง€์›ํ•˜์ง€ ์•Š์„ ์ด์œ ๊ฐ€ ๊ฑฐ์˜ ์—†์Šต๋‹ˆ๋‹ค.

private _myProperty: string;

public get myProperty(): string { return this._myProperty; }
private set myProperty(value: string) { this._myProperty = value; }

Typescript๋Š” ์ฃผ๋กœ .NET ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ธŒ๋ผ์šฐ์ € ํ”„๋ŸฐํŠธ ์—”๋“œ ์ž‘์—…์— ๋” ์ต์ˆ™ํ•ด์ง€๋„๋ก ๋งŒ๋“ค์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์— ์ด์ƒํ•œ ๋””์ž์ธ ๊ฒฐ์ •์— ๋Œ€ํ•œ ๋ณด๋„ˆ์Šค ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.

+1
Typescript๋Š” ํ™•์‹คํžˆ ์ด ๊ธฐ๋Šฅ์˜ ์ด์ ์„ ๋ˆ„๋ฆด ๊ฒƒ์ž…๋‹ˆ๋‹ค!

TypeScript๋Š” C# ์ดํ›„์—๋„ ํ›Œ๋ฅญํ•˜์ง€๋งŒ ์ด ๋ฌด์˜๋ฏธํ•œ ์ œํ•œ์ด ๋‚˜๋ฅผ ์ž์ฃผ ์งœ์ฆ๋‚˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์‹œ ์—ด์–ด์ฃผ์„ธ์š”.

์–ธ์–ด์˜ ๋ณต์žก์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค

readonly [P in keyof T]: T[P] ์™€ ๋น„๊ตํ•  ๋•Œ ์ด๊ฒƒ์ด ์ •๋ง ๋ณต์žกํ•ฉ๋‹ˆ๊นŒ?

์ถฉ๋Œ. ๋ชจ๋‘๊ฐ€ ์ด ๊ธฐ๋Šฅ์„ ์›ํ•ฉ๋‹ˆ๋‹ค. TypeScript ์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ๊ฒฐ์ •ํ•ด์•ผ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๊นŒ?

์–ธ์–ด์˜ ๋ณต์žก์„ฑ์„ ์ฆ๊ฐ€์‹œํ‚ฌ ๊ฒƒ์ž…๋‹ˆ๋‹ค

readonly [P in keyof T]: T[P] ์™€ ๋น„๊ตํ•  ๋•Œ ์ด๊ฒƒ์ด ์ •๋ง ๋ณต์žกํ•ฉ๋‹ˆ๊นŒ?

๋ณต์žก์„ฑ์€ ๋‹ค๋ฅธ ์–ธ์–ด ๊ธฐ๋Šฅ์˜ ์ƒํ˜ธ ์ž‘์šฉ๊ณผ ๊ด€๋ จ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ์ฐพ์„ ์ˆ˜ ์—†์ง€๋งŒ IIRC RyanCavanaugh๋Š” ์ด ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜์—ฌ ํด๋ž˜์Šค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์†์„ ํ†ตํ•ด ๋ถˆ๋ณ€์„ฑ์„ ์„ค์ •ํ•˜๊ณ  ์œ„๋ฐ˜ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ˆ๋ฅผ ์ œ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค. ํŠน์ • ์„ ์–ธ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์‰ฝ๋‹ค๊ณ  ํ•ด์„œ ๊ทธ๊ฒƒ์ด ์‚ฌ๋ฌผ์— ์–ด๋–ค ์˜ํ–ฅ์„ ๋ฏธ์น˜๋Š”์ง€ ์ถ”๋ก ํ•˜๋Š” ๊ฒƒ์ด ํ•ญ์ƒ ์‰ฌ์šด ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ์ฃผ์–ด์ง„ ๊ธฐ๋Šฅ์ด ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์–ด๋–ค ๋ฌธ์ œ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ธ๊ฐ€ ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ „์ž๋Š” ๋Œ€๋‹ตํ•˜๊ธฐ ์‰ฝ๊ณ  ํ›„์ž๋Š” ์˜์™ธ๋กœ ๋Œ€๋‹ตํ•˜๊ธฐ ์–ด๋ ต๋‹ค. ๋ถˆํ–‰ํžˆ๋„ TS ํŒ€์€ ๋•Œ๋•Œ๋กœ ๋ฌธ์ œ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ๋Œ€์‹  "OMG ๋ณต์žก์„ฑ"์œผ๋กœ ์‘๋‹ตํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. (๊ณต์ •ํ•˜๊ฒŒ ๋งํ•˜๋ฉด, n๋ฒˆ์งธ๋กœ ์ฟผ๋ฆฌ x์— ์‘๋‹ตํ•˜๋Š” ๋ฐ ๋” ๋งŽ์€ ์‹œ๊ฐ„์„ ํ• ์• ํ• ์ˆ˜๋ก ๊ฐœ๋ฐœํ•ด์•ผ ํ•˜๋Š” ์‹œ๊ฐ„์ด ์ค„์–ด๋“ญ๋‹ˆ๋‹ค.)

๋‚˜๋Š” "์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ๊ฒฐ์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ"์ด๋ผ๋Š” ๊ฐœ๋…์— 100% ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์‹ค์ œ๋กœ ์–ธ์–ด๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ์ „๋ฌธ๊ฐ€๋“ค ์‚ฌ์ด์— ํ•ฉ์˜๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ๊ฒƒ์ด ๋‹น์‹ ์—๊ฒŒ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งํ•ด์ค„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด์™€ ๊ฐ™์ด ์š”์ฒญํ•œ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ํŒ€์—์„œ ์ ˆ์ถฉ์•ˆ์ด ๋ฌด์—‡์ธ์ง€, ์™œ ๋ฐ˜๋Œ€ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์‚ฌ๋ ค ๊นŠ์€ ์„ค๋ช…์€ ๋„ˆ๋ฌด ๋งŽ์€ ๊ฒƒ์„ ์š”๊ตฌํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐœ์ธ์ ์œผ๋กœ ์ด ๊ฒฝ์šฐ์—๋Š” ์ ˆ์ถฉ์•ˆ์ด 1000% ๊ฐ€์น˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‚ด๊ฐ€ ๊ทธ๊ฒƒ์„ ์‚ฌ์–‘ํ•˜๊ณ  ์ž‘๋™ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค๋ฉด ๋‚˜๋Š” ๋ถˆํ‰ํ•  ๊ถŒ๋ฆฌ๊ฐ€ ๋ณ„๋กœ ์—†๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ๋‹ค์‹œ ์‚ดํŽด๋ณด๋Š” ๊ฒƒ์ด ์ข‹์„๊นŒ์š”?

readonly ์ˆ˜์ •์ž๋Š” ํ›Œ๋ฅญํ•˜์ง€๋งŒ ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ณ  ์™ธ๋ถ€์—์„œ๋Š” ๋ชจ๋“  ๊ฒƒ์„ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์œ ์ง€ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

๊ฐœ์ธ ์ง€์› ํ•„๋“œ + ์†์„ฑ์ด ์ถ”๊ฐ€ํ•˜๋Š” ๋…ธ์ด์ฆˆ๊ฐ€ ๋งˆ์Œ์— ๋“ค์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์†์„ฑ์„ readonly ๋กœ ์ง€์ •ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค.

์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ๋ฌธ ์„คํƒ•์ด ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ:

// Option 1: C# style
public name: string { get; private set; }

// Option 2: Swift style
private(set) name: string

// Option 3: Swift struct-style
public readonly name: string

mutating changeName(name: string) {
  this.name = name
}

// Option 4: New keyword
public frozen name1: string
public readonly name2: string

์˜ต์…˜ 2๊ฐ€ ๋งˆ์Œ์— ๋“ญ๋‹ˆ๋‹ค. TypeScript ์–ธ์–ด์— ์ž˜ ๋งž์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์˜ต์…˜ 3์„ ์‚ฌ์šฉํ•˜๋ฉด mutating ๋กœ ํ‘œ์‹œ๋œ ํ•จ์ˆ˜์˜ ์ฝ๊ธฐ ์ „์šฉ ํ•„๋“œ๋งŒ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ต์…˜ 4๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด frozen ๋Š” ์ƒ์„ฑ์ž์—์„œ๋งŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ณ  readonly ๋Š” ์™ธ๋ถ€ ํด๋ž˜์Šค๋‚˜ ์ด ํด๋ž˜์Šค์—์„œ ์ƒ์†ํ•˜๋Š” ํด๋ž˜์Šค๊ฐ€ ์•„๋‹ˆ๋ผ ์ด ํด๋ž˜์Šค ๋‚ด๋ถ€์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ @yvbeek ์˜ ๋ณด๋‹ค ์œ ์—ฐํ•œ ์ˆ˜์ •์ž ์•„์ด๋””์–ด๋Š” https://github.com/microsoft/TypeScript/issues/37487์— ๋Œ€ํ•œ ๋…ผ์˜์— ๋” ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋Š” ํŠนํžˆ getter ๋ฐ setter๋ฅผ ์œ„ํ•œ ๊ฒƒ์ด๋ฉฐ ๋งค์šฐ ๋†’์€ ์ˆ˜์˜ ์ฐฌ์„ฑํ‘œ๋ฅผ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค! getter์™€ setter์— ์„œ๋กœ ๋‹ค๋ฅธ ์•ก์„ธ์Šค ์ˆ˜์ •์ž๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ์œ ์šฉํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(TypeScript ํŒ€์ด ์•ž์œผ๋กœ ๋‚˜์•„๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๊ฒฐ์ •ํ•œ ๊ฒฝ์šฐ #37487์—์„œ ๊ธฐ์กด ์ˆ˜์ •์ž ์„ธํŠธ๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค)

๋‚˜๋Š” "์ปค๋ฎค๋‹ˆํ‹ฐ๊ฐ€ ๊ฒฐ์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ"์ด๋ผ๋Š” ๊ฐœ๋…์— 100% ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์‹ค์ œ๋กœ ์–ธ์–ด๋ฅผ ๊ฐœ๋ฐœํ•˜๋Š” ์ „๋ฌธ๊ฐ€๋“ค ์‚ฌ์ด์— ํ•ฉ์˜๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ทธ๊ฒƒ์ด ๋‹น์‹ ์—๊ฒŒ ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งํ•ด์ค„ ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด์™€ ๊ฐ™์ด ์š”์ฒญํ•œ ์‚ฌํ•ญ์— ๋Œ€ํ•ด ํŒ€์—์„œ ์ ˆ์ถฉ์•ˆ์ด ๋ฌด์—‡์ธ์ง€, ์™œ ๋ฐ˜๋Œ€ํ•˜๋Š”์ง€์— ๋Œ€ํ•œ ์‚ฌ๋ ค ๊นŠ์€ ์„ค๋ช…์€ ๋„ˆ๋ฌด ๋งŽ์€ ๊ฒƒ์„ ์š”๊ตฌํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@snarfblam ์ด ์Šค๋ ˆ๋“œ๋ฅผ ๊ด€๋ จ ์—†๋Š” ๋Œ“๊ธ€๋กœ

์ด ๊ธฐ๋Šฅ์ด ์—†๋‹ค๋Š” ๊ฒƒ์€ ์ €์—๊ฒŒ ์ •๋ง ๊ณ ํ†ต์Šค๋Ÿฌ์šด ์ผ์ด๋ฉฐ (๋ฌด์—‡๋ณด๋‹ค๋„) ์ œ๊ฐ€ TS/NodeJS์—์„œ ๋”... ์œ ํ˜•์ด ์•ˆ์ „ํ•œ ๊ฒƒ์œผ๋กœ ์ „ํ™˜ํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋‘ ํ›Œ๋ฅญํ•˜๊ณ  ๋ฉ‹์ง‘๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋งŽ์€ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ(๊นŠ๊ฒŒ ์—ฌ๋Ÿฌ ๋ฒˆ ์ค‘์ฒฉ๋จ)๊ฐ€ ์žˆ๋Š” ๋ณต์žกํ•œ ํ”„๋กœ์ ํŠธ์—์„œ ์ž‘์—…ํ•  ๋•Œ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๋Œ€๋กœ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์—†์œผ๋ฉด ์ด๊ฒƒ์ด "ํฐ ์–ธ์–ด"๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๋Š๋‚Œ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค. ์†Œ๋…„๋“ค".

๋‚ด ํŠน๋ณ„ํ•œ ๊ฒฝ์šฐ์—๋Š” ์†์„ฑ์„ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์›ํ•˜์ง€๋งŒ ๋‚ด๋ถ€์—์„œ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ณ ... ๋˜ํ•œ JSON์œผ๋กœ ์ง๋ ฌํ™”๋ฉ๋‹ˆ๋‹ค. ๋„˜์–ด์•ผ ํ•  ๊ณจ์ด ๋„ˆ๋ฌด ๋งŽ์Šต๋‹ˆ๋‹ค.

์ด ๊ธฐ๋Šฅ์€ _์„ ํƒ์  ์—ฐ๊ฒฐ_๊ณผ ๋™์ผํ•œ ๊ฒฝ๋กœ๋ฅผ ๋”ฐ๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์€ ๋ช‡ ๋…„ ๋™์•ˆ ์ด ๊ธฐ๋Šฅ์„ ์š”๊ตฌํ•˜๊ณ  ๋งˆ์นจ๋‚ด ์–ธ์–ด์— ์ถ”๊ฐ€๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹ค์šฉ์ ์ด๊ณ  ๋‹ค๋ฅธ ์–ธ์–ด์—์„œ๋„ ๋™์ผํ•œ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ผ๋ถ€ ๊ตฌํ˜„์ด EcmaScript์˜ ์ผ๋ถ€๊ฐ€ ๋œ ๋‹ค์Œ TypeScript์— ์ ์šฉ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ตœ๊ทผ์— typescript๋กœ ์ „ํ™˜ํ–ˆ๊ณ  ์–ธ์–ด๋ฅผ ์‚ฌ๋ž‘ํ•ด ์™”์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์–ธ์–ด์— ์กด์žฌํ•˜๋Š” ์ด ์‹ค์šฉ์ ์ธ ๊ธฐ๋Šฅ์ด ์—ฌ๊ธฐ์—์„œ ๊ตฌํ˜„๋˜์ง€ ์•Š์•˜๋‹ค๋Š” ์‚ฌ์‹ค์ด ์ •๋ง ์•ˆํƒ€๊นŒ์› ์Šต๋‹ˆ๋‹ค. ์–ธ์–ด์— ์ถ”๊ฐ€๋˜๋Š” ๋ณต์žก์„ฑ์— ๊ด€๊ณ„์—†์ด ํ–ฅํ›„ ๋ฆด๋ฆฌ์Šค์— ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ์žฌ๊ณ ํ•˜์‹ญ์‹œ์˜ค.

๊ทธ๋Ÿฐ ์‹์œผ๋กœ getter๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ C#๊ณผ ๋น„์Šทํ•œ ๊ฒƒ์„ ๋‹ฌ์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

export class I18nService {
  private static ref: I18nService;

  public static get instance(): I18nService {
    if (!I18nService.ref) {
      I18nService.ref = new I18nService();
    }

    return I18nService.ref;
  }
}

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์œ ํ˜• ์˜ค๋ฅ˜๋Š” ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ๋ณต์žกํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Property 'foo' is writable only in protected scope within class 'Blah' and its subclasses.

๋˜๋Š”

Property 'foo' is readable only in protected scope within class 'Blah' and its subclasses.

๋“ฑ๋“ฑ, ๊ทธ๋ฆฌ๊ณ  private ์™€ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์†”์งํžˆ ๋ณต์žกํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

BTW, ๋‚˜๋„์ด ๋ฌธ์ œ๋ฅผ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ–ˆ์œผ๋ฉฐ ๊ทธ ๋™์•ˆ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ "ํ•ดํ‚น"์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

// somewhere.ts
declare global {
    type Writable<T> = { -readonly [P in keyof T]: T[P]; }
}

// example.ts
class Example {

    public readonly prop: number;

    public doSomething(n: number): void {
        (this as Writable<this>).prop = n;
    }
}

๊ธฐ์ˆ ์ ์œผ๋กœ ์ด๊ฒƒ์€ ๋ชจ๋“  ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ด ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ํด๋ž˜์Šค ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์˜ ์ฝ”๋“œ๋กœ ์ œํ•œ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

BTW, ๋‚˜๋„์ด ๋ฌธ์ œ๋ฅผ ์šฐ์—ฐํžˆ ๋ฐœ๊ฒฌํ–ˆ์œผ๋ฉฐ ๊ทธ ๋™์•ˆ ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ "ํ•ดํ‚น"์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด ์•„์ด๋””์–ด๋ฅผ ๊ฐ€์ง€๊ณ  ๋†€์•˜์ง€๋งŒ ๋ฌธ์ œ๋Š” "๊ณต๊ฐœ ์ฝ๊ธฐ ์ „์šฉ" ์†์„ฑ๊ณผ ์ง„์ •ํ•œ ์ฝ๊ธฐ ์ „์šฉ ์†์„ฑ์„ ๊ตฌ๋ณ„ํ•  ๋ฐฉ๋ฒ•์ด ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฒ”์šฉ ์†”๋ฃจ์…˜์œผ๋กœ๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰