CleanCode TIL (2022.01.30)

Henry Choยท2022๋…„ 1์›” 30์ผ
0

๋…ธ๊ฐœ๋ถ

๋ชฉ๋ก ๋ณด๊ธฐ
10/31

DAY 10

๐Ÿ”–ย ์˜ค๋Š˜ ์ฝ์€ ๋ฒ”์œ„ : 5. ํ˜•์‹ ๋งž์ถ”๊ธฐ (96~116p)


๐Ÿค“ย ์ฑ…์—์„œ ๊ธฐ์–ตํ•˜๊ณ  ์‹ถ์€ ๋‚ด์šฉ

ํ˜•์‹์„ ๋งž์ถ”๋Š” ๋ชฉ์ 

  • ๋Œ์•„๊ฐ€๋Š” ์ฝ”๋“œ vs ํ˜•์‹์„ ๋งž์ถ˜ ์ฝ”๋“œ ์˜ค๋Š˜ ๊ตฌํ˜„ํ•œ ๊ธฐ๋Šฅ์€ ๋‹ค์Œ ๋ฒ„์ „์—์„œ ๋ฐ”๋€” ํ™•๋ฅ ์€ ์•„์ฃผ ๋†’๋‹ค. ์˜ค๋Š˜ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ์˜ ๊ตฌํ˜„ ์Šคํƒ€์ผ๊ณผ ๊ฐ€๋…์„ฑ์€ ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด์„ฑ๊ณผ ํ™•์žฅ์„ฑ์— ๊ณ„์† ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.

์ ์ ˆํ•œ ํ–‰ ๊ธธ์ด๋ฅผ ์œ ์ง€ํ•˜๋ผ

  • ์„ธ๋กœ ๊ธธ์ด 500์ค„์„ ๋„˜์ง€์•Š๋Š” ํ‰๊ท  200์ค„์˜ ํŒŒ์ผ๋กœ๋„ ์ปค๋‹ค๋ž€ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค

์‹ ๋ฌธ ๊ธฐ์‚ฌ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ผ

  • ์•„์ฃผ ์ข‹์€ ์‹ ๋ฌธ์€ ์ตœ์ƒ๋‹จ์— ๊ธฐ์‚ฌ๋ฅผ ๋ช‡๋งˆ๋””๋กœ ์š”์•ฝํ•˜๋Š” ํ‘œ์ œ, ์ฒซ ๋ฌธ๋‹จ์€ ์ „์ฒด ๊ธฐ์‚ฌ๋‚ด์šฉ์„ ์š”์•ฝ, ๋‚ด๋ ค๊ฐˆ์ˆ˜๋ก ์„ธ๋ถ€์‚ฌํ•ญ(๋‚ ์งœ,์ด๋ฆ„,๋ฐœ์–ธ,์ฃผ์žฅ) ๋ณด์—ฌ์คŒ
  1. ์†Œ์ŠคํŒŒ์ผ ์ฒซ ๋ถ€๋ถ„์€ ๊ณ ์ฐจ์› ๊ฐœ๋…๊ณผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๋ช…
  2. ์•„๋ž˜๋กœ ๋‚ด๋ ค๊ฐˆ์ˆ˜๋ก ์˜๋„๋ฅผ ์„ธ์„ธํ•˜๊ฒŒ ๋ฌ˜์‚ฌ
  3. ์ตœ ํ•˜๋‹จ์— ๊ฐ€์žฅ ์ €์ฐจ์› ํ•จ์ˆ˜์™€ ์„ธ๋ถ€ ๋‚ด์—ญ

๊ฐœ๋…์„ ๋นˆ ํ–‰์œผ๋กœ ๋ถ„๋ฆฌํ•˜๋ผ

  • ๊ฐ ํ–‰์€ ์ˆ˜์‹์ด๋‚˜ ์ ˆ์„ ๋‚˜ํƒ€๋‚ด๊ณ , ์ผ๋ จ์˜ ํ–‰ ๋ฌถ์Œ์€ ์™„๊ฒฐ๋œ ์ƒ๊ฐ ํ•˜๋‚˜๋ฅผ ํ‘œํ˜„
  • ์ƒ๊ฐ ์‚ฌ์ด์—๋Š” ๋นˆ ํ–‰์„ ๋„ฃ์–ด ๋ถ„๋ฆฌํ•ด์•ผ ๋งˆ๋•…
    package fitnesse.wikitext.widgets;
    
    import java.util.regex.*;
    
    public class BoldWidget extends ParentWidget {
        public static final String REGEXP = "'''.+?'''";
        private static final Pattern pattern = Pattern.compile("'''(.+?)'''",
            Pattern.MULTILINE + Pattern.DOTALL);
        public BoldWidget(ParentWidget parent, String text) throws Exception {
            super(parent);
            Matcher match = pattern.matcher(text);
            match.find();
            addChildWidgets(match.group(1));
        }
        public String render() throws Exception {
            StringBuffer html = new StringBuffer("<b>");
            html.append(childHtml()).append("</b>");
            return html.toString();
        }
    }
    ๋นˆ ํ–‰์€ ์ƒˆ๋กœ์šด ๊ฐœ๋…์„ ์‹œ์ž‘ํ•œ๋‹ค๋Š” ์‹œ๊ฐ์  ๋‹จ์„œ

์„ธ๋กœ ๋ฐ€์ง‘๋„

  • ์„œ๋กœ ๋ฐ€์ ‘ํ•œ ์ฝ”๋“œ์˜ ํ–‰์€ ์„ธ๋กœ๋กœ ๊ฐ€๊นŒ์ด ๋†“์—ฌ์•ผ ํ•œ๋‹ค.
    public class ReporterConfig {
        /**
         * ๋ฆฌํฌํ„ฐ ๋ฆฌ์Šค๋„ˆ์˜ ํด๋ž˜์Šค ์ด๋ฆ„
         */
        private String m_className;
        /**
         * ๋ฆฌํฌํ„ฐ ๋ฆฌ์Šค๋„ˆ์˜ ์†์„ฑ */
        private List < Property > m_properties = new ArrayList < Property > ();
        public void addProperty(Property property) {
            m_properties.add(property);
        }
    }
    ์œ„ ์ฒ˜๋Ÿผ ์ฃผ์„์œผ๋กœ ๋‘ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋ฅผ ๋–จ์–ด๋œจ๋ ค ๋†“์•„์„œ๋Š” ์•ˆ๋œ๋‹ค.

์ˆ˜์ง ๊ฑฐ๋ฆฌ

  • ์„œ๋กœ ๋ฐ€์ ‘ํ•œ ์ƒˆ๋…์€ ์„ธ๋กœ๋กœ ๊ฐ€๊นŒ์ด ๋‘ฌ์•ผ ํ•œ๋‹ค.
  • ๋‘ ๊ฐœ๋…์ด ์„œ๋กœ ๋‹ค๋ฅธ ํŒŒ์ผ์— ์žˆ๋‹ค๋ฉด ์–ด์ฉ”์ˆ˜ ์—†์œผ๋‚˜, ํƒ€๋‹นํ•œ ๊ทผ๊ฑฐ๊ฐ€ ์—†๋‹ค๋ฉด ๋ฐ€์ ‘ํ•œ ๊ฐœ๋…์€ ํ•œ ํŒŒ์ผ์— ์žˆ์–ด์•ผ ํ•œ๋‹ค โ†’ protected ๋ณ€์ˆ˜๋ฅผ ํ”ผํ•ด์•ผ ํ•˜๋Š” ์ด์œ 
  • ์—ฐ๊ด€์„ฑ: ํ•œ ๊ฐœ๋…์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋‹ค๋ฅธ ๊ฐœ๋…์ด ์ค‘์š”ํ•œ ์ •๋„

๋ณ€์ˆ˜ ์„ ์–ธ

  • ์‚ฌ์šฉํ•˜๋Š” ์œ„์น˜์— ์ตœ๋Œ€ํ•œ ๊ฐ€๊นŒ์ด ์„ ์–ธ
  • ํ•จ์ˆ˜๊ฐ€ ๋งค์šฐ ์งง์€ ๊ฒฝ์šฐ์— ์ง€์—ญ๋ณ€์ˆ˜๋Š” ํ•จ์ˆ˜ ๋งจ์ฒ˜์Œ์— ์„ ์–ธ ํ•ด๋„๋Œ
    private static void readPreferences() {
        InputStream is = null;
        try {
            is = new FileInputStream(getPreferencesFile());
            setPreferences(new Properties(getPreferences()));
            getPreferences().load(is);
        } catch (IOException e) {
            try {
                if (is != null) is.close();
            } catch (IOException e1) {}
        }
    }
  • ๋ฃจํ”„๋ฅผ ์ œ์–ดํ•˜๋Š” ๋ณ€์ˆ˜๋Š” ๋ฃจํ”„ ๋ฌธ ๋‚ด๋ถ€์— ์„ ์–ธ
    public int countTestCases() {
        int count = 0;
        for (Test each: tests)
            count += each.countTestCases();
        return count;
    }

์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜

  • ํด๋ž˜์Šค์˜ ๋งจ ์ฒ˜์Œ์— ์„ ์–ธ
  • ๋ณ€์ˆ˜ ๊ฐ„์— ์„ธ๋กœ๋กœ ๊ฑฐ๋ฆฌ๋ฅผ ๋‘์ง€ ์•Š์Œ
  • ์ž˜ ์„ค๊ณ„ํ•œ ํด๋ž˜์Šค๋Š” ๋Œ€๋ถ€๋ถ„์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ
  • C++์˜ ๊ฒฝ์šฐ ํด๋ž˜์Šค ๋งˆ์ง€๋ง‰์— ๋ชจ์•„๋†“์ง€๋งŒ, ์ž˜ ์•Œ๋ ค์ง„ ์œ„์น˜์— ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜๋ฅผ ๋ชจ์•„ ๋†“๋Š”๋‹ค๋Š” ์‚ฌ์‹ค์ด ์ค‘์š”
    public class TestSuite implements Test {
        static public Test createTest(Class << ? extends TestCase > theClass,
            ...
        }
        public static Constructor << ? extends TestCase > getTestConstructor(Class << ? extends TestCase > theClass) throws NoSuchMethodException {
            ...
        }
        public static Test warning(final String message) { ...
        }
        private static String exceptionToString(Throwable t) { ...
        }
        private String fName;
        private Vector < Test > fTests = new Vector < Test > (10);
        public TestSuite() {}
        public TestSuite(final Class << ? extends TestCase > theClass) { ...
        }
        public TestSuite(Class << ? extends TestCase > theClass, String name) { ...
            }
            ...............
    }
    โ†’ ์ค‘๊ฐ„์— ์ธ์Šคํ„ด์Šค ๋ณ€์ˆ˜ ์ˆจ๊ฒจ๋†“์œผ๋ฉด ์ฐพ๊ธฐ ํž˜๋“ค๋‹ค

์ข…์† ํ•จ์ˆ˜

  • ํ•œ ํ•จ์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด ๋‘ ํ•จ์ˆ˜๋Š” ์„ธ๋กœ๋กœ ๊ฐ€๊นŒ์ด ๋ฐฐ์น˜
  • ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ ๋˜๋Š” ํ•จ์ˆ˜๋ณด๋‹ค ๋จผ์ € ๋ฐฐ์น˜

๊ฐœ๋…์  ์œ ์‚ฌ์„ฑ

  • ์–ด๋–ค์ฝ”๋“œ๋Š” ๊ฐœ๋…์ ์ธ ์นœํ™”๋„๊ฐ€ ๋†’์•„์„œ ๊ฐ€๊นŒ์ด ๋ฐฐ์น˜ํ•ด์•ผํ•จ
  • ๋น„์Šทํ•œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์ผ๊ตฐ์˜ ํ•จ์ˆ˜
    public class Assert {
        static public void assertTrue(String message, boolean condition) {
            if (!condition) fail(message);
        }
        static public void assertTrue(boolean condition) {
            assertTrue(null, condition);
        }
        static public void assertFalse(String message, boolean condition) {
            assertTrue(message, !condition);
        }
        static public void assertFalse(boolean condition) {
            assertFalse(null, condition);
        }
        ...
    }

์„ธ๋กœ ์ˆœ์„œ

  • ์ผ๋ฐ˜์ ์œผ๋กœ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์ข…์†์„ฑ์€ ์•„๋ž˜ ๋ฐฉํ–ฅ์œผ๋กœ ์œ ์ง€ (๊ณ ์ฐจ์› โ†’ ์ €์ฐจ์›)
  • ์†Œ์Šค์—์„œ ์ฒซ ํ•จ์ˆ˜ ๋ช‡๊ฐœ๋งŒ ์ฝ์–ด๋„ ๊ฐœ๋…์„ ํŒŒ์•…ํ•˜๊ธฐ ์‰ฌ์›Œ์ง

๊ฐ€๋กœ ํ˜•์‹ ๋งž์ถ”๊ธฐ

  • ์ตœ๋Œ€ 120์ž ์ •๋„๊ฐ€ ์ข‹๋‹ค

๊ฐ€๋กœ ๊ณต๋ฐฑ๊ณผ ๋ฐ€์ง‘๋„

  • ๊ฐ€๋กœ ๊ณต๋ฐฑ์„ ์‚ฌ์šฉํ•ด ๋ฐ€์ ‘ํ•œ ๊ฐœ๋…๊ณผ ๋Š์Šจํ•œ ๊ฐœ๋…์„ ํ‘œํ˜„ํ•œ๋‹ค
    private void measureLine(String line) {
        lineCount++;
        int lineSize = line.length();
        totalChars += lineSize;
        lineWidthHistogram.addLine(lineSize, lineCount);
        recordWidestLine(lineSize);
    }
    ํ• ๋‹น(=) ์—ฐ์‚ฐ์ž ๊ฐ•์กฐํ•˜๊ธฐ ์œ„ํ•ด ์•ž๋’ค์— ๊ณต๋ฐฑ ํ•จ์ˆ˜์ด๋ฆ„๊ณผ ์ด์–ด์ง€๋Š” ๊ด„ํ˜ธ์—๋Š” ๊ณต๋ฐฑ ์ฃผ์ง€ ์•Š์Œ โ†’ ๋ฐ€์ ‘ํ•จ ์‰ผํ‘œ๋ฅผ ๊ฐ•์กฐํ•ด ์ธ์ˆ˜๊ฐ€ ๋ณ„๊ฐœ๋ผ๋Š” ์‚ฌ์‹ค์„ ๋ณด์—ฌ์คŒ
  • ์—ฐ์‚ฐ์ž ์šฐ์„ ์ˆœ์œ„ ๊ฐ•์กฐ์œ„ํ•ด ๊ณต๋ฐฑ ์‚ฌ์šฉ
    public class Quadratic {
        public static double root1(double a, double b, double c) {
            double determinant = determinant(a, b, c);
            return (-b + Math.sqrt(determinant)) / (2 * a);
        }
        public static double root2(int a, int b, int c) {
            double determinant = determinant(a, b, c);
            return (-b - Math.sqrt(determinant)) / (2 * a);
        }
        private static double determinant(double a, double b, double c) {
            return b * b - 4 * a * c;
        }
    }
    ๊ณฑ์…ˆ์€ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๊ฐ€์žฅ ๋†’์Œ โ†’ ์Šน์ˆ˜ ์‚ฌ์ด๋Š” ๊ณต๋ฐฑ ์—†์Œ ๋ง์…ˆ๊ณผ ๋บ„์…ˆ์€ ์šฐ์„ ์ˆœ์œ„ ๋‚ฎ์Œ โ†’ ๊ณต๋ฐฑ

๊ฐ€๋กœ ์ •๋ ฌ

  • ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฐ€๋กœ ์ •๋ ฌ์€ ์˜คํžˆ๋ ค ๋ณ€์ˆ˜๋ณ‘์— ์ง‘์ค‘๋˜๊ฒŒ ํ•˜๋Š” ๋“ฑ์˜ ์ž˜๋ชป๋œ ๊ฐ•์กฐ ๋ฐœ์ƒ
    public class FitNesseExpediter implements ResponseSender
    {
    	private    Socket      socket;
    	protected  long        requestParsingTimeLimit;
    	private    long        requestProgress;
    ...
  • ์ •๋ ฌ์ด ํ•„์š”ํ•  ์ •๋„๋กœ ๋ชฉ๋ก์ด ๊ธธ๋‹ค๋ฉด ๋ฌธ์ œ๋Š” ๊ธธ์ด์ง€ ์ •๋ ฌ ๋ถ€์กฑ์ด ์•„๋‹ˆ๋‹ค

๋“ค์—ฌ์“ฐ๊ธฐ

  • ๋ฒ”์œ„๋กœ ์ด๋ค„์ง„ ๊ณ„์ธต์„ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ๋ฅผ ๋“ค์—ฌ ์“ด๋‹ค
  • ํด๋ž˜์Šค ์ •์˜์ฒ˜๋Ÿผ ํŒŒ์ผ ์ˆ˜์ค€์ธ ๋ฌธ์žฅ์€ ๋“ค์—ฌ์“ฐ์ง€ ์•Š์Œ
  • ํด๋ž˜์Šค ๋‚ด ๋ฉ”์„œ๋“œ๋Š” ํด๋ž˜์Šค๋ณด๋‹ค ํ•œ ์ˆ˜์ค€ ๋“ค์—ฌ ์“ด๋‹ค.
  • ๋ฉ”์„œ๋“œ ์ฝ”๋“œ๋Š” ๋ฉ”์„œ๋“œ ์„ ์–ธ๋ณด๋‹ค ํ•œ ์ˆ˜์ค€ ๋“ค์—ฌ ์“ด๋‹ค.
  • ๋ธ”๋ก ์ฝ”๋“œ๋Š” ์ƒ์œ„ scope ๋ณด๋‹ค ํ•œ ์ˆ˜์ค€ ๋” ๋“ค์—ฌ์“ด๋‹ค.

๋“ค์—ฌ์“ฐ๊ธฐ ๋ฌด์‹œํ•˜๊ธฐ

  • ์งง์€ if, while ๋ฌธ์—์„œ ๋“ค์—ฌ์“ฐ๊ธฐ ๋ฌด์‹œํ•˜๊ณ ํ”ˆ ์œ ํ˜น์ด ์žˆ์–ด๋„ ๋ฌผ๋ฆฌ์ณ๋ผ ์ž˜๋ชป๋œ ๋“ค์—ฌ์“ฐ๊ธฐ ๋ฌด์‹œ์˜ ์˜ˆ
    public class CommentWidget extends TextWidget {
    public static final String REGEXP = "^#[^\r\n]*(?:(?:\r\n)|\n|\r)?";
    public CommentWidget(ParentWidget parent, String text){super(parent, text);}
    public String render() throws Exception {return ""; } }

๊ฐ€์งœ ๋ฒ”์œ„

  • ๋นˆ while ์ด๋‚˜ for๋ฅผ ๋ฐ˜๋“œ์‹œ ์จ์•ผํ•˜๋Š” ๊ฒฝ์šฐ ๋นˆ ๋ธ”๋ก์„ ๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ๊ณ  ; ๋ฅผ ์ƒˆ ํ–‰์—๋‹ค ์ œ๋Œ€๋กœ ๋“ค์—ฌ์จ์„œ ๋„ฃ์–ด์ค€๋‹ค.
    while (dis.read(buf, 0, readBufferSize) != -1) 
    	{};

ํŒ€ ๊ทœ์น™

  • ๊ฐ์ž ๊ทœ์น™์ด ์žˆ๊ฒ ์ง€๋งŒ ์šฐ๋ฆฌ๊ฐ€ ์„ ํ˜ธํ•ด์•ผ ํ•  ๊ทœ์น™์€ ํŒ€ ๊ทœ์น™ โ†’ ์ผ๊ด€์„ฑ์„ ํ•ฉ์˜

๋ฐฅ ์•„์ €์”จ์˜ ํ˜•์‹ ๊ทœ์น™

  • ์ฝ”๋“œ ์ž์ฒด๊ฐ€ ์ตœ๊ณ ์˜ ๊ตฌํ˜„ ํ‘œ์ค€ ๋ฌธ์„œ๊ฐ€ ๋˜๋Š” ์˜ˆ์‹œ
public class CodeAnalyzer implements JavaFileAnalysis {
    private int lineCount;
    private int maxLineWidth;
    private int widestLineNumber;
    private LineWidthHistogram lineWidthHistogram;
    private int totalChars;
    public CodeAnalyzer() {
        lineWidthHistogram = new LineWidthHistogram();
    }
    public static List < File > findJavaFiles(File parentDirectory) {
        List < File > files = new ArrayList < File > ();
        findJavaFiles(parentDirectory, files);
        return files;
    }
    private static void findJavaFiles(File parentDirectory, List < File > files) {
        for (File file: parentDirectory.listFiles()) {
            if (file.getName().endsWith(".java")) files.add(file);
            else if (file.isDirectory()) findJavaFiles(file, files);
        }
    }
    public void analyzeFile(File javaFile) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(javaFile));
        String line;
        while ((line = br.readLine()) != null)
            measureLine(line);
    }
    private void measureLine(String line) {
        lineCount++;
        int lineSize = line.length();
        totalChars += lineSize;
        lineWidthHistogram.addLine(lineSize, lineCount);
        recordWidestLine(lineSize);
    }
    private void recordWidestLine(int lineSize) {
        if (lineSize > maxLineWidth) {
            maxLineWidth = lineSize;
            widestLineNumber = lineCount;
        }
    }
    public int getLineCount() {
        return lineCount;
    }
    public int getMaxLineWidth() {
        return maxLineWidth;
    }
    public int getWidestLineNumber() {
        return widestLineNumber;
    }
    public LineWidthHistogram getLineWidthHistogram() {
        return lineWidthHistogram;
    }
    public double getMeanLineWidth() {
        return (double) totalChars / lineCount;
    }
    public int getMedianLineWidth() {
        Integer[] sortedWidths = getSortedWidths();
        int cumulativeLineCount = 0;
        for (int width: sortedWidths) {
            cumulativeLineCount += lineCountForWidth(width);
            if (cumulativeLineCount > lineCount / 2)
                return width;
        }
        throw new Error("Cannot get here");
    }
    private int lineCountForWidth(int width) {
        return lineWidthHistogram.getLinesforWidth(width).size();
    }
    private Integer[] getSortedWidths() {
        Set < Integer > widths = lineWidthHistogram.getWidths();
        Integer[] sortedWidths = (widths.toArray(new Integer[0]));
        Arrays.sort(sortedWidths);
        return sortedWidths;
    }
}

๐Ÿค”ย ๋– ์˜ค๋ฅด๋Š” ์ƒ๊ฐ

  • ์•„์ง 100% ์™€๋‹ฟ์ง€๋Š” ์•Š์ง€๋งŒ ๊ธฐ์กด์— ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ• ๋•Œ ๊ณ ๋ฏผ์„ ํ•˜๊ณ  ๋ง์„ค์ด๋˜ ๋ถ€๋ถ„์„ ํ™•์‹คํ•˜๊ฒŒ ์ •ํ•ด์ฃผ๋Š” ๋‚ด์šฉ์ด๋ผ ์ข‹๋‹ค

๐Ÿ”Žย ์งˆ๋ฌธ

๐Ÿ“ย ์†Œ๊ฐ 3์ค„ ์š”์•ฝ

  • ์˜ค๋Š˜ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ์˜ ๊ตฌํ˜„ ์Šคํƒ€์ผ๊ณผ ๊ฐ€๋…์„ฑ์€ ์œ ์ง€๋ณด์ˆ˜ ์šฉ์ด์„ฑ๊ณผ ํ™•์žฅ์„ฑ์— ํ‰์ƒ ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.
  • 500์ค„์„ ๋„˜์ง€์•Š๋Š” ํ‰๊ท  200์ค„์˜ ํŒŒ์ผ๋กœ๋„ ์ปค๋‹ค๋ž€ ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ๋‹ค
  • ์‹ ๋ฌธ ๊ธฐ์‚ฌ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ผ: ์ถ”์ƒํ™” โ†’ ์„ธ๋ถ€์ , ์œ ์‚ฌ๊ฐœ๋…์€ ๊ฐ€๊นŒ์ด
profile
Full stack tech visionary

0๊ฐœ์˜ ๋Œ“๊ธ€