블로그

양성빈

[인프런 워밍업 스터디 클럽] 0기 백엔드 미션 - 어노테이션(Day1)

어노테이션 서론드디어 '인프런 워밍업 스터디 클럽 0기' 첫 날이 밝아왔다. 강의를 듣고 미션을 보니 어노테이션에 관련한 내용이었다.나는 이 미션을 보고 오히려 기쁜 마음이 들었다. 😆 내가 강의를 들으면서 어노테이션 부분이 많이 궁금하였는데 이렇게 공부하게 될 계기가 생긴 것 같아서 미션도 완성시키고 나 스스로 깊게 공부도 할 겸 미션을 시작할려고 한다. 미션 내용은 아래와 같다.진도표 1일차와 연결됩니다우리는 최초로 API를 만들어 보았습니다. GET API를 만들기 위해 사용했던 어노테이션에 익숙하지 않다면 자바 어노테이션에 대해서 몇 가지 블로그 글을 찾아보세요! 다음 질문을 생각하며 공부해보면 좋습니다! 😊 [질문]어노테이션을 사용하는 이유 (효과) 는 무엇일까?나만의 어노테이션은 어떻게 만들 수 있을까?내가 알아본 어노테이션의 정의나는 강의의 실습을 통하여 스프링 부트 프로젝트를 생성하고, GET API를 만들어보고 포스트맨을 통하여 테스트 작업도 해보았다. 나는 여기서 다양한 어노테이션들을 볼 수 있었다. @SpringBootApplication, @RestController, @GetMapping 등 여러 어노테이션들을 볼 수 있었다. 여기서 나는 어노테이션이 무엇일까 고민을 해보았다. 단순히 어노테이션은 @ 붙인거라고만 알고 있었기에 이번 기회에 미션도 수행할 겸 깊게 알아보는 것도 좋다 생각하여 공부해보기로 하겠다.먼저 어노테이션이 대체 어떤 정의가 있는지 구글링을 해보기로 하였다. 구글링을 해보니, 다양한 블로그들이 나왔지만 정의가 수록된 위키백과를 먼저 참조해보기로 하였다. 위키백과는 다음과 같이 정의를 내렸다. 자바 어노테이션은 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종이다. 보통 @ 기호를 앞에 붙여서 사용한다. JDK 1.5 버전 이상에서 사용 가능하다. 자바 어노테이션은 클래스 파일에 임베디드되어 컴파일러에 의해 생성된 후 자바 가상머신에 포함되어 작동한다. 그리고 강의 중에 코치님께서도 어노테이션에 대해 아래와 같이 언급해주셨다. 어노테이션은 어노테이션마다 너무 다양한 역할을 한다. 또한 마법같은 일을 자동으로 해준다는 것이다.예를 들어서, @SpringBootApplication 어노테이션은 스프링을 실행시킬 때 다양한 설정이 필요한데 이 설정을 모두 자동으로 해준다. 또한 이런것이 가장 핵심적인 마법같은 일이다.위키사전, 코치님의 설명을 통해 어노테이션의 정의를 알 수 있었다. 좀 더 내가 설명한 식으로 풀어보자면 다음과 같다.자바의 어노테이션은 코드에 추가 정보를 제공하는 데 사용되며, 컴파일 시간, 배포 시간, 또는 실행 시간에 해당 정보를 활용할 수 있습니다. 이를 통해 개발자는 코드에 메타데이터를 추가하여 코드의 가독성, 유지 보수성을 향상시키고, 다양한 도구와 프레임워크에서 활용될 수 있는 정보를 제공할 수 있습니다.좀 더 자세히 풀어보자.어노테이션은 자바 5부터 도입된 기능으로, 코드에 대한 메타데이터를 제공하는 방법입니다. 어노테이션은 주석과 비슷하지만, 실제로 코드에 영향을 줄 수 있으며, 컴파일러에게 정보를 제공하거나 실행 시간에 특정 동작을 하도록 할 수 있습니다. 어노테이션은 선언적 형태로 코드 안에 포함되어, 클래스, 메소드, 변수 등 다양한 요소에 적용될 수 있습니다.이제 위의 내용을 좀 더 정리해보겠다. 어노테이션이란?자바를 개발한 사람들은 소스코드에 대한 문서를 따로 만들기보다 소스코드와 문서를 하나의 파일로 관리하는 것이 낫다고 생각했다. 그래서 소스코드의 주석에 소스코드에 대한 정보를 저장하고, 소스코드의 주석으로부터 HTML 문서를 생성해내는 프로그램(javadoc.exe)를 만들어 사용했다. 그런데 여기서 의문점이 하나 든다. 🙋🏻 왜 어노테이션이라는 것을 살펴보려 하는데 주석이라는 내용이 먼저 나올까? 프로그램의 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이 바로 어노테이션이다.어노테이션은 주석(comment)처럼 프로그래밍 언어에 영향을 미치지 않으면서도 다른 프로그램에게 유용한 정보를 제공할 수 있다는 장점이 있다. 📚 어노테이션(annotation)의 뜻은 주석, 주해, 메모이다.package org.example; public @interface SampleAnnotation { }위의 코드는 인텔리제이로 나의 어노테이션을 만든 코드이다.그럼 인텔리제이로 어노테이션을 만드는 것도 끝났으니 이제 끝인가? 나는 여기서 더 나아가서 이 어노테이션 코드가 .class파일로 컴파일 되었을 때 어떻게 나오는지 보고 싶어서 터미널로 컴파일을 해보았다. 컴파일 결과는 다음과 같다.public interface org.example.SampleAnnotation extends java.lang.annotation.Annotation { }컴파일 시점에 extends 한적 없는 java.lang.annotation.Annotation 이 extends 되어 있다. 이제 좀 더 자세한 어노테이션의 내용과 활용법을 알아가보자. 어노테이션은 JDK에서 기본적으로 제공하는 것과 다른 프로그램에서 제공하는 것들이 있는데, 어느 것이든 그저 약속된 형식의 정보를 제공하기만 하면 될 뿐이다.JDK에서 제공하는 표준 어노테이션은 주로 컴파일러를 위한 것으로 컴파일러에게 유용한 정보를 제공한다. 📚 JDK에서 제공하는 어노테이션은 'java.lang.annotation' 패키지에 포함되어 있다.어노테이션은 코드에 넣는 주석이다. 완전히 주석같지는 않지만 그 비슷한 부류이다.주석이기 때문에, 실행되는 코드라고 생각하면 안된다. 어노테이션은 기능을 가지고 있는 것이라 착각을 할 수 있지만 어노테이션은 마크, 표시 해놓는 주석이다. 어노테이션은 다이나믹하게 실행되는 코드는 들어가지 않는다.즉, 런타임에 알아내야 하는 것들은 못 들어간다.위의 내용을 좀 더 풀어쓰면 컴파일러 수준에서 해석이 되야 하거나, 완전히 정적이어야 한다는 말이다.이유를 아래 코드로 보여주겠다. package me.sungbin.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class HelloController { private static final String hello = "/hello"; @GetMapping(hello) public String hello() { return "hello"; } }위와 같이 hello 변수는 정적 변수이므로 @GetMapping 어노테이션에 사용할 수 있다.하지만. hello 변수가 동적인 변수라면 컴파일 에러가 발생한다.아래의 코드를 보자. 컴파일 에러가 발생하는 것을 볼 수 있을 것이다. 간략한 어노테이션 정의 방법새로운 어노테이션을 정의하는 방법은 아래와 같다.'@'기호를 붙이는 것을 제외하면 인터페이스 정의와 동일하다. package me.sungbin; public @interface SampleAnnotation { 타입요소이름(); } 📚 타입요소등, 어노테이션 정의에 대한 자세한 정의방법과 내용들은 구체적인 내용들을 확인 후, 살펴보자.자바의 표준 어노테이션자바에서 기본적으로 제공하는 어노테이션들은 몇 개 없다.그나마 이들의 일부는 '메타 어노테이션(meta annotation)' 으로 어노테이션을 정의하는데 사용되는 어노테이션의 어노테이션이다. 표준 어노테이션과 메타 어노테이션@Override: 컴파일러에게 오바리이딩하는 메서드라는 것을 알린다.@Deprecated: 앞으로 사용하지 않을 것을 권장하는 대상에 붙인다.@SuppressWarnings: 컴파일러의 특정 경고메시지가 나타나지 않게 해준다.@SafeVarags: 제네릭스 타입의 가변인자에 사용한다. (JDK 1.7)@FunctionalInterface: 함수형 인터페이스라는 것을 알린다. (JDK 1.8)@Native: native 메서드에서 참조되는 상수 앞에 붙인다. (JDK 1.8)@Target*: 어노테이션이 적용가능한 대상을 지정하는데 사용한다.@Documented*: 어노테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다.@Inherited*: 어노테이션이 자손 클래스에 상속되도록 한다.@Retention*: 어노테이션이 유지되는 범위를 지정하는데 사용한다.@Repeatable*: 어노테이션을 반복해서 사용할 수 있게 한다. (JDK 1.8)*이 붙은 것이 메타 어노네이션이다.📚 메타 어노테이션: 어노테이션을 정의하는데 사용하는 어노테이션의 어노테이션 @Override현재 메서드가 슈퍼 클래스의 메서드를 오버라이드한 것임을 컴파일러에게 명시해준다.메서드가 슈퍼클래스에 없다면 에러를 발생시기 때문에 오타와 같은 실수도 잡을 수 있다. @Deprecated마커 어노테이션으로 다음 버전에 지원되지 않을 수도 있기 때문에 앞으로 사용하지 말라고 경고를 알린다.@Deprecated를 붙인 메서드는 인텔리제이에서 아래의 사진과 같이 표시해준다. @SuppressWarning경고를 제거하는 어노테이션으로 개발자가 의도를 가지고 설계를 했는데 컴파일은 이를 알지 못하고 컴파일 경고를 띄울 수 있기 때문에 이를 제거하는 목적이다. @SafeVarargsJava 7이상에서 사용가능하고 제네릭같은 가변인자 매개변수 사용시 경고를 무시한다제네릭사용할 클래스,메서드 내부에서의 데이터타입을 외부에서 지정하는 기법 @FunctionalInterfaceJava 8이상에서 사용가능하고 컴파일러에게 함수형 인터페이스라는 것을 알리는 어노테이션이다.메타 어노테이션'어노테이션을 위한 어노테이션' 쯕, 어노테이션에 붙이는 어노테이션으로 어노테이션을 정의할 때 어노테이션의 적용대상(target) 이나 유지기간(retention)등을 지정하는데 사용된다. 📚 메타 어노테이션은 java.lang.annotation 패키지에 포함되어 있다. @Target어노테이션이 적용가능한 대상을 지정하는데 사용한다.아래 예제는 '@SuppressWarnings' 를 정의한 것인데, 이 어노테이션에 적용할 수 있는 대상을 '@Target' 으로 지정한다.여러 개의 값을 지정할 때는 배열처럼 괄호{} 를 이용하여 지정할 수 있다.package me.sungbin; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { String[] value(); } @Target으로 지정할 수 있는 어노테이션 적용대상의 종류ANNOTATION_TYPE: 어노테이션CONSTRUCTOR: 생성자FIELD: 필드(멤버 변수, ENUM 상수)LOCAL_VARIABLE: 지역변수METHOD: 메서드PACKAGE: 패키지PARAMETER: 매개변수TYPE: 타입(클래스, 인터페이스, ENUM)TYPE_PARAMETER: 타입 매개변수(JDK1.8)TYPE_USE: 타입이 사용되는 모든 곳(JDK1.8)📚 java.lang.annotation.ElementType 이라는 열거형에 정의되어 있다. static import문을 사용하면 ElementType.TYPE 이 아니라 TYPE 과 같이 간략히 사용할 수 있다. TYPE은 타입을 선언할 때 어노테이션을 붙일 수 있다는 뜻TYPE_USE는 해당 타입의 변수를 선언할 때 붙일 수 있다는 뜻이다.FIELD 는 기본형에 사용할 수 있고, TYPE_USE는 참조형에 사용된다는 점을 주의한다.타입 선언부제네릭 타입, 변수 타입, 매개변수 타입, 예외 타입...타입에 사용할 수 있으려면TYPE_PARAMETER : 타입 변수에만 사용할 수 있다.TYPE_USE : 타입 변수를 포함해서 모든 타입 선언부에 사용할 수 있다.package me.sungbin; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Target({FIELD, TYPE, TYPE_USE}) public @interface MyAnnotation { } package me.sungbin; import me.sungbin.controller.HelloController; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @MyAnnotation public class AnnotationTestApplication { @MyAnnotation int i; @MyAnnotation HelloController helloController; public static void main(String[] args) { SpringApplication.run(AnnotationTestApplication.class, args); } } @Retention어노테이션 유지되는 기간을 지정하는데 사용한다. 어노테이션 유지정책의 종류SOURCE: 소스 파일에만 존재. 클래스파일에는 존재하지 않는다.CLASS: 클래스 파일에 존재. 실행 시에 사용 불가능하다. (기본값)RUNTIME: 클래스 파일에 존재하며 실행시에 사용 가능하다.SOURCE -> CLASS -> RUNTIMESOURCE는 소스코드만 유지하겠다.컴파일 시에만 사용하겠다는 것!컴파일하고 나면 어노테이션은 없어진다. -> 바이트코드에도 남아있지 않다.CLASS애노테이션에 대한 정보를 클래스 파일까지, 즉 바이트 코드에도 남겨 두겠다.클래스 정보를 읽어들이는 방법(바이트 코드를 읽어들이는)을 바탕으로 애노테이션 정보를 읽어와서 처리할 수 있다.예) BYTE BUDDY, ASM 활용바이트 코드엔 남아 있지만, 이 클래스파일을 JVM이 실행할 때 클래스에 대한 정보를 클래스로더가 읽어서 메모리에 적재하게되고, 이후 사용 시점에 메모리에서 읽어올 때 애노테이션 정보를 제외하고 읽어옴RUNTIME위 CLASS와 동일하지만, 메모리에 적재된 클래스 정보를 읽어올 때 애노테이션 정보를 그대로 포함하는 것이다.바이트코드에서 읽어오는게 빠를까?RetentionPolicy를 CLASS로 한 이후, 바이트코드를 읽어 처리하는 라이브러리를 활용?리플렉션으로 읽어오는게 빠를까?RetentionPolicy를 CLASS로 한 이후, 바이트코드를 읽어 처리하는 라이브러리를 활용? -> 리플렉션 자체가 부하가 존재한다.-> 바이트 코드의 양에 영향을 끼친다.-> 리플렉션은 메모리에 이미 올라와 있는 정보를 읽는다. 클래스 로더가 읽고 메모리에 적재시킨 후 읽어온다. 📚 커스텀하게 만든 애노테이션이 정말로 RUNTIME 까지 필요한 정보인가? RUNTIME 까지 사용할 필요가 없다면, CLASS 레벨로 내려가거나 SOURCE 레벨로 내려갈 수도 있을 것이다. 그냥, 의례적으로 RUNTIME으로 작성하는 경우가 있었다면? 그 역할을 다시 살펴보고 명확한 Retention Policy 를 정의하자. 표준 어노테이션 중 '@Override' 나 '@SuppressWarnings' 처럼 컴파일러가 사용하는 어노테이션은 유지 정책이 'SOURCE' 이다. -> 컴파일러를 직접 작성할 것이 아니면, SOURCE 이상의 유지정책을 가질 필요가 없다. 유지 정책을 RUNTIME 으로 한다면,실행 시에 리플렉션(Reflection) 을 통해 클래스 파일에 저장된 어노테이션의 정보를 읽어서 처리 할 수 있다.Retention 정책은 RUNTIME 으로 정의하고Target은 TYPE과 FIELD로 정의한다.package me.sungbin; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Target({TYPE, FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { } Target이 TYPE과 FIELD 임으로 클래스에도 애노테이션을 선언할 수 있고클래스 내부의 필드에도 애노테이션을 선언할 수 있다.package me.sungbin; @MyAnnotation public class TestClass { @MyAnnotation private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } TestClass 클래스에 선언된 Annotation을 리플렉션을 이용해 확인할 수 있다.package me.sungbin; import java.lang.reflect.Field; import java.util.Arrays; public class App { public static void main(String[] args) { Arrays.stream(TestClass.class.getAnnotations()).forEach(System.out::println); Field[] declaredFields = TestClass.class.getDeclaredFields(); for (Field declaredField : declaredFields) { Arrays.stream(declaredField.getAnnotations()).forEach(System.out::println); } } }  표준 어노테이션 중 '@FunctionalInterface' 는 '@Override' 처럼 컴파일러가 체크해주는 어노테이션이지만, 실행 시에도 사용되므로 유지 정책이 "RUNTIME"으로 되어 있다. @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FunctionalInterface {} 유지 정책을 "CLASS" 으로 한다면컴파일러가 어노테이션의 정보를 클래스 파일에 저장할 수 있게 하지만,클래스 파일이 JVM에 로딩 될 때는 어노테이션의 정보가 무시되어 실행 시에 어노테이션에 대한 정보를 얻을 수 없다.→ CLASS 가 유지정책의 기본값임에도 불구하고 잘 사용되지 않는 이유 지역 변수에 붙은 어노테이션은 컴파일러만 인식할 수 있으므로, 유지 정책이 RUNTIME인 어노테이션을 지역변수에 붙여도 실행 시에는 인식되지 않는다. @Documented어노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다.표준 어노테이션 중 Override와 SuppressWarnings를 제외하고 모두 Documented 메타 어노테이션이 붙어 있다. @Documented애노테이션 정보가 javadoc으로 작성된 문서에 포함된다고 한다. 이것이 무슨말일까? 내 코드가 자바docs에 올라간다는 말일까?정확히 말하면 자바docs에 올라간다는 말이 아니라,직접 javadoc을 만들 수 있다는 뜻이다.이런식으로 만들 수 있는데, Local 지역입력 ko_KRother command line arguments : 한글깨짐 방지-encoding UTF-8 -charset UTF-8 -docencoding UTF-8적절하게 내용을 채운뒤 output directory에 경로를 입력해주면 끝이다.그러면 @Documented를 붙인거와 안 붙인것을 비교해보자. 코드public class Korea implements Great{ @Override @Make public String country() { return "한국"; } } 없는거 있는거JavaDoc애노테이션을 알기 전에 JavaDoc에 대해 알아보자.JavaDoc은 Java코드에서 API문서를 HTML 형식으로 생성해주는 도구이다.HTML 형식이기 때문에 다른 API를 하이퍼 링크를 통해 접근이 가능하다. JavaDoc TagsJavaDoc은 여러 Tag를 작성하여 문서를 완성한다.Java 코드에서 애노테이션으로 추가한다.IDE에서 /** 입력 후 엔터를 치면 자동으로 형식이 생성된다.Javadoc Tags의 종류들@author@deprecated@exception@param@return@see@serial@serialData@serialField@since@throws@since@throws@version@Inherited어노테이션이 자손 클래스에 상속되도록 한다.'@Inherited' 가 붙은 어노테이션을 조상 클래스에 붙이면, 자손 클래스도 이 어노테이션이 붙은 것과 같이 인식된다.MyAnnotation은 Inherited 애노테이션을 통해 자손 클래스에도 인식되도록 정의한다.package me.sungbin; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Retention(RetentionPolicy.RUNTIME) @Target({TYPE, FIELD}) @Inherited public @interface MyAnnotation { } 부모클래스인 Sungbin클래스에 MyAnnotation을 정의package me.sungbin; @MyAnnotation("hi") public class Sungbin { @MyAnnotation("yang sung bin") private String name; }  Sungbin 클래스의 자식 클래스인 Child 클래스에는 별도의 어노테이션 정의가 없다.package me.sungbin; public class Child extends Sungbin { } 리플렉션을 이용해 Child 클래스의 어노테이션을 확인해보자.→ ChildSson 클래스에는 정의한 애노테이션이 없지만,→ 부모 클래스인 Sson 클래스에 정의한 애노테이션이 확인됨을 볼 수 있다.→ Inherited 애노테이션을 통해 자식 클래스까지 전파될 수 있음을 확인할 수 있다. Inherited 애노테이션을 바탕으로 리플렉션을 활용해 자식클래스에서부모클래스에 정의되어 있는 Inherited 애노테이션을 확인할 수 있다. 📚 리플랙션의 getDeclaredFields(); 를 하면 클래스에 정의된(선언된) 것들을 가져와서 조작할 수 있다. public이던, private 이던,, Getter와 Setter에 대해 논의를 하며 큰 비용을 소모하는 것이 크게 가치가 없다.. 객체지향을 얘기하며 Getter, Setter의 정의 관련한 내용으로 얘기할 수 있겠지만, Getter와 Setter가 없더라도 리플랙션을 이용하면 충분히 가져오고 수정할 수 있기 때문이다. 중요한건 Getter, Setter 가 아닌것 같다. @Repeatable보통은 하나의 대상에 한 종류의 어노테이션을 붙이게 되는데,'@Repeatable'이 붙은 어노테이션은 여러 번 붙일 수 있다. 일반적인 어노테이션과 달리 같은 이름의 어노테이션이 어러 개가 하나의 대상에 적용될 수 있기 때문에, 이 어노테이션들을 하나로 묶어서 다룰 수 있는 어노테이션도 추가로 정의해야 한다. @Native네티이브 메서드(native method)에 의해 참조되는 '상수 필드(constant field)'에 붙이는 어노테이션이다.여기서, 네이티브 메서드는 JVM이 설치된 OS의 메서드를 말한다.네이티브 메서드는 보통 C언어로 작성되어 있는데, 자바에서는 메서드의 선언부만 정의하고 구현하지 않는다.그래서 추상 메서드처럼 선언부만 있고 구현부가 없다. 어노테이션 타입 정의어노테이션의 요소어노테이션 내에 선언된 메서드를 어노테이션의 요소라고 한다. 📚 어노테이션에도 인터페이스처럼 상수를 정의할 수 있지만, 디폴트 메서드는 정의할 수 있다. 어노테이션의 요소는 반환 값이 있고 매개변수는 없는 추상 메서드의 형태를 가진다.다만, 어노테이션을 적용할 때 이 요소들의 값을 빠짐없이 지정해주어야 한다.각 요소들은 기본값을 가질 수 있으며, 기본값이 있는 요소들은 어노테이션을 적용할 때 값을 지정하지 않으면 기본값이 사용된다.어노테이션의 요소가 오직 하나 뿐이고 이름이 value 인 경우, 어노테이션을 적용할 때 요소의 이름을 생략하고 값만 적어도 된다.요소 타입이 배열인 경우, 괄호{} 를 사용해 여러 개의 값을 지정할 수 있다.하나인 경우는 괄호{} 를 생략할 수 있다.java.lang.annotation.Annotation모든 어노테이션의 조상은 Annotation이다.그러나 어노테이션은 상속이 허용되지 않으므로 아래와 같이 명시적으로 Annotation을 조상으로 지정할 수 없다. @interface TestInfo extends Annotation{ // 에러. 허용되지 않는 표현이다. int count(); String testedBy(); ... } Annotation 을 살펴보면Annotation은 어노테이션이 아니라 일반적인 인터페이스로 정의되어 있다. 모든 어노테이션의 조상인 Annotation 인터페이스가 위와 같이 정의되어 있기 때문에모든 어노테이션 객체에 대해 equals(), hashCode(), toString() 과 같은 메서드를 호출하는 것이 가능하다.리플랙션(Reflection)을 이용해 특정 클래스에 선언된 애노테이션들을 조회하여 equals, hashCode, toString 메서드를 호출해본다.어노테이션 요소의 규칙어노테이션의 요소를 선언할 때 반드시 지켜야 하는 규칙요소 타입은 기본형, String, Enum, 어노테이션, Class 만 허용() 안에 매개변수를 선언할 수 없다.예외를 선언할 수 없다.요소를 타입 매개변수로 정의할 수 없다.마커 어노테이션 Marker Annotation값을 지정할 필요가 없는 경우,어노테이션의 요소를 하나도 정의하지 않을 수 있다.Serializable 이나 Cloneable 인터페이스처럼, 요소가 하나도 정의되지 않은 어노테이션을 마커 어노테이션이라 한다. 🙋🏻 이런 마커 어노테이션은 왜 사용될까? 글을 찾아보니 아래의 내용이 있었다.마커 어노테이션을 통해 코드 작성 시점, 컴파일 시점, 러타임 시점에 부가적인 작업을 추가할 수 있을 것이다.코드 작성 시점에 어노테이션 정보를 통해 부가적인 정보를 check 하여 컴파일에러를 발생시킬 수 있을 것이며컴파일하는 과정에서 어노테이션 정보를 바탕으로 부가적인 정보를 포함하여 컴파일된 결과를 내보낼 수도 있을 것이다.또한, 런타임 시점에 리플랙션을 이용하여 애노테이션 정보를 바탕으로 부가적인 작업을 할 수 있을 것이다.Java8 어노테이션 변화 애노테이션 관련 큰 변화 두가지자바 8 부터 애노테이션을 타입 선언부에도 사용할 수 있게 되었다.자바 8 부터 애노테이션을 중복해서 사용할 수 있게 되었다.타입 선언부제네릭 타입변수 타입매개변수 타입예외 타입...타입에 사용할 수 있으려면TYPE_PARAMETER : 타입 변수에만 사용할 수 있다.TYPE_USE : 타입 변수를 포함해서 모든 타입 선언부에 사용할 수 있다.중복 사용할 수 있는 애노테이션을 만들기@Repeatable애노테이션들을 감싸고 있을 컨테이너 애노테이션을 선언해야 한다.중복 사용할 애노테이션 만들기컨테이너 애노테이션은 중복 애노테이션과 @Retention 및 @Target 이 같거나 더 넓어야 한다.컨테이너이기 떄문에 , 이것은 접근 지시자의 범위와 유사한 개념이라고 볼 수 있다.@Retention : 애노테이션을 언제까지 유지할 것이냐?@Target : 애노테이션을 어디에 사용할 것이냐?애노테이션 프로세서애노테이션 프로세서는 소스코드 레벨에서 소스코드에 붙어있는애노테이션을 읽어서 컴파일러가 컴파일 하는 중에 새로은 소스코드를 생성하거나 기존 소스코드를 바꿀 수 있다.또는, 클래스(바이트코드) 도 생성할 수 있고 별개의 리소스파일을 생성할 수 있는 강력한 기능이다. 애노테이션 프로세서 사용 예롬복 (기존코드를 변경한다)AutoService (리소스 파일을 생성해준다.)java.util.ServiceLoader 용 파일 생성 유틸리티@Override애노테이션 프로세서 장점바이트코드에 대한 조작은 런타임에 발생되는 조작임으로 런타임에 대한 비용이 발생한다.but. 애노테이션 프로세서는 애플리케이션을 구동하는 런타임 시점이 아니라,컴파일 시점에 조작하여 사용함으로 런타임에 대한 비용이 제로가 된다.단점은 기존의 코드를 고치는 방법은 현재로써는 public 한 API 가 없다.롬복 같은 경우.. 기존 코드를 변경하는 방법이지만 public 한 api를 이용한 것이 아님으로 해킹이라고 할 수 도 있다.롬복(Lombok)의 동작원리Lombok@Getter @Setter, @Builder 등의 애노테이션과애노테이션 프로세서를 제공하여 표준적으로 작성해야 할 코드를 개발자 대신 생성해주는 라이브러리이다.사용하기의존성 추가IntelliJ Lombok 플로그인 설치Intellij Annotation Processing 옵션 활성화동작원리컴파일 시점에 "애노테이션 프로세서"를 사용하여 (자바가 제공하는 애노테이션 프로세서)소스코드의 AST(Abstract Syntax Tree) 를 조작한다.AST에 대한 참고 사이트 (아래 참조 참고)javax.annotation.processing || Interfaec Processor⇒ 소스코드의 AST를 원래는 참조만 할 수 있다. // 수정하지 못한다. 그리고 하면 안된다!⇒ 그러나 수정이 됬음을 알 수 있다.(컴파일 이후 바이트코드 확인)⇒ 참조만 해야 하는 것을 내부 클래스를 사용하여 기존 코드를 조작하는 것임으로 "해킹" 이라고 얘기하기도 한다. 논란 거리공개된 API가 아닌 컴파일러 내부 클래스를 사용하여 기존 소스 코드를 조작한다.특히 이클립스의 경우에는 Java Agent를 사용하여 컴파일러 클래스까지 조작하여 사용한다.해당 클래스들 역시 공개된 API가 아니다보니 버전 호환성에 문제가 생길 수도 있고 언제라도 그런 문제가 발생해도 이상하지 않다.그럼에도 불구하고 엄청난 편리함 때문에 널리 쓰이고 있으며, 대안이 몇가지 있지만 롬복의 모든 기능과 편의성을 대체하지 못하는 상황이다.AutoValueImmutables기존 Getter, Setter, equals, hasCode 등의 메소드를 생성하는 순간?해당 클래스는 이미 방대해진 모습을 볼 수 있다.해당 클래스를 위한 메소드들이 선언이 되어 있더라도 위 메소드들 사이에 파묻혀 있다면?개발자 입장에서 놓칠 수도 있다. (그래서 boilerplat 코드라는 개념도 나온다.)⇒ 롬복을 이용하여 쉽게, 그리고 가독성 높게 클래스를 구현할 수 있다. package me.sungbin; import lombok.Getter; import lombok.Setter; @Getter @Setter public class Member { private String name; private int age; }  위의 롬복이 적용된 코드를 컴파일하면 아래와 같이 나온다. package me.sungbin; public class Member { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } 결론위에서 미션에 대해 다 애기한 듯 하다. 결론을 내보겠다.어노테이션을 사용하는 이유는 단순하다.코드의 가독성과 유지보수성 향상: 어노테이션을 사용하면 개발자가 코드의 의도를 더 명확하게 표현할 수 있습니다. 예를 들어, @Override 어노테이션은 메소드가 상위 클래스의 메소드를 오버라이드한다는 것을 명시합니다.컴파일 시간 검사: 어노테이션을 통해 코드에 대한 추가적인 검사를 수행할 수 있어, 잠재적인 오류를 컴파일 시간에 발견하고 수정할 수 있습니다.런타임 처리: 특정 어노테이션이 적용된 요소를 런타임에 검사하고 처리할 수 있어, 리플렉션을 사용한 동적 처리가 가능해집니다. 이는 프레임워크와 라이브러리에서 많이 활용됩니다.이런 이유로 사용이 되며 이로인하여 코드문서화, 컴파일러에 특정처리를 지시, 코드분석 도구 지원, 런타임처리등이 가능해지게 된다. 우리가 스프링의 의존성 주입을 할 때 @Autowired도 이런 기능처리를 해준다. 컴파일러에서의 처리:코드 검증: 컴파일러는 어노테이션을 사용하여 코드에 대한 추가적인 검증을 수행합니다. 예를 들어, @Override 어노테이션은 메서드가 실제로 상위 클래스나 인터페이스의 메서드를 오버라이드하는지 확인하는 데 사용됩니다. 만약 오버라이드하는 메서드가 없다면, 컴파일러는 에러를 발생시킵니다.정책 적용: 일부 어노테이션은 컴파일러에 특정 정책을 적용하도록 지시합니다. 예를 들어, @Deprecated 어노테이션이 적용된 요소를 사용하는 코드는 컴파일러 경고를 발생시키며, 이는 개발자에게 해당 요소가 더 이상 사용되지 않아야 함을 알립니다.소스 코드 변환: 어노테이션 프로세서를 사용하여 컴파일 시점에 소스 코드를 자동으로 생성하거나 수정할 수 있습니다. 이는 코드 생성 라이브러리나 프레임워크에서 흔히 사용되는 기법입니다.런타임에서의 처리:리플렉션을 통한 접근: 런타임에는 리플렉션 API를 사용하여 어노테이션 정보에 접근할 수 있습니다. 이를 통해 개발자는 실행 중인 프로그램에서 클래스, 메서드, 필드 등에 적용된 어노테이션을 검사하고, 해당 어노테이션에 지정된 정보를 바탕으로 동적인 처리를 수행할 수 있습니다.동적 처리: 런타임에 어노테이션을 기반으로 동적 처리를 하는 예로, Java EE와 Spring 프레임워크에서 의존성 주입을 구현하는 방법을 들 수 있습니다. 이러한 프레임워크는 특정 어노테이션(@EJB, @Autowired)이 붙은 필드나 메서드를 찾아, 런타임에 자동으로 의존성을 주입합니다.구성 관리: 어플리케이션의 구성 정보를 어노테이션을 통해 관리할 수 있습니다. 예를 들어, 웹 어플리케이션에서 서블릿이나 REST 엔드포인트를 정의할 때 사용되는 어노테이션들은 런타임에 웹 서버가 해당 구성 정보를 읽어들여 서비스를 구동하는 데 사용됩니다.이러한 방식으로 어노테이션은 컴파일 시점과 런타임에 다양한 목적으로 활용됩니다. 컴파일 시점에는 코드의 정확성을 보장하고, 런타임에는 코드의 동적인 행위를 제어하는 데 중요한 역할을 합니다.커스텀 어노테이션이것 또한 위에서 예제로 많이 보여드렸으므로 어노테이션 예제를 보여줌으로 이 글을 마치려고 한다. 정말 단순히 어노테이션부터 시작해서 리플렉션까지 갔는데 정말 험난한 여정이였지만 보람찬 공부가 되었다. package me.sungbin; import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.*; @Retention(RetentionPolicy.RUNTIME) @Target({TYPE, FIELD}) @Inherited public @interface MyAnnotation { String value(); }  📚 참조https://b-programmer.tistory.com/264http://javaparser.org/inspecting-an-ast/

백엔드인프런워킹업스터디클럽백엔드미션어노테이션

대롱대롱

[인프런 워밍업클럽 CS 2기] 3주차 미션

마지막 3주차 미션! 시작합니다 운영체제메모리의 종류는 어떤것들이 있나요? 각 메모리의 특징도 함께 적어주세요.레지스터 - 가장 빠른 기억장소로 CPU에 있어요. 휘발성 메모리입니다.캐시 - 레지스터와 메인 메모리 사이에 있는 휘발성 메모리입니다. 메인메모리에 있는 데이터를 미리 저장합니다.(메인)메모리 - 실제 운영체지와 다른 프로세스들이 올라가는 공간으로 휘발성 메모리입니다.보조기억장치(하드디스크,SSD) - 가격이 (상대적으로) 저렴하며 비휘발성메모리입니다. 사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 어떤 레지스터일까요?경계 레지스터가 있어서 사용자 프로세스가 메모리의 운영체제 영역에 침범하게 되면 프로세스를 강제종료 시킬 수 있어요. 메모리 할당 방식에서 가변 분할 방식과 고정 분할 방식의 장단점은 뭔가요?가변분할 방식은 프로세스 크기에 맞는 메모리공간을 할당하는 방식입니다.내부단편화는 일어나지 않는다는 장점이 있지만 외부단편화가 발생할 수 있다는 단점이 있어요.고정분할 방식은 프로세스 크기에 상관없이 정한 크기만큼 공간을 할당하는 방식입니다.구현이 간단하고 오버헤드가 발생하지 않지만 내부단편화가 발생할 수 있다는 단점이 있어요. CPU 사용률을 올리기 위해 멀티프로그래밍을 올렸지만 스왑이 더 많이 이루어져 CPU 사용률이 0%에 가까워 지는 것을 뭐라고 할까요?스레싱이라고 합니다. 메모리 부족으로 페이지 폴트가 많이 발생하게 되어 대부분의 시간에 스왑을 하게 되는 현상입니다. HDD나 SSD는 컴퓨터를 실행시키는데 꼭 필요한 걸까요?이유를 함께 적어주세요.꼭 필요하다고 할 수는 없습니다. 일반적으로 HDD나 SSD에 운영체제를 설치하고 컴퓨터 부팅할 때 불러와서 동작을 합니다. 그러나 HDD나 SSD에서만 이러한 동작을 할 수 있는 것은 아니기 때문에 꼭 필요하지는 않습니다. 파일을 삭제해도 포렌식으로 파일을 복구할 수 있는 이유가 무엇일까요?파일을 삭제하게 되면 파일시스템은 파일의 모든 정보를 지우는 것이 아니라 파일테이블의 헤더를 삭제하고 free block list에 추가합니다. 사용했던 블록을 이 리스트에 추가하기 때문에 사용했던 블록의 데이터는 그대로 남아있게 됩니다. 그렇기 떄문에 포렌식으로 파일을 복구할 수 있는 것입니다. 자료구조와 알고리즘지금까지 배운 5개의 정렬 알고리즘의 장단점과 시간 복잡도를 적어주세요.버블정렬, 선택정렬, 삽입정렬위 세 정렬은 구현이 쉽고 직관적이지만 성능이 좋지 않습니다.(O(n^2))병합정렬큰 문제를 작은 문제로 쪼개서 해결하기 때문에 성능이 좋습니다(O(nlogn). 그러나 정렬할 배열을 넣을 메모리가 필요하다는 것이 단점입니다.퀵정렬공간효율적이고 캐시친화적이며 병렬화도 가능합니다. 정렬 알고리즘 중 우수한 성능을 보입니다.(O(nlogn)에 근접한 성능)그러나 피벗을 잘못 선택한다면 성능이 저하되어 최악의 경우 성능이 O(n^2)이 될 수도 있습니다. 메모리가 부족한 시스템에서 어떤 문제를 해결하는데 재귀로 쉽게 구현이 가능할 것 같습니다. 여러분이라면 메모이제이션과 타뷸레이션 중 어떤 걸 이용하실 건가요? 이유를 함께 적어주세요.   재귀로 쉽게 구현할 수 있다면 메모이제이션이 좋지만 메모이제이션은 메모리를 많이 사용한다는 문제가 있습니다. 메모리가 부족한 이슈가 있기 때문에 결과적으로는 타뷸레이션을 사용할 것 같습니다.

cs자료구조운영체제미션

이양구

[인프런 워밍업 클럽 FE 0기] 미션8 - 디즈니 플러스 앱

🎞 Disney Plus APP GitHub 🎞 Disney Plus APP DemoRecord by ScreenToGif  개요인프런 워밍업 클럽 FE 0기의 여덟 번째 미션인 '디즈니 플러스 앱' 입니다. 따라하며 배우는 리액트 섹션 4~5(리액트로 Netflix 앱 만들기) 목표swiper 라이브러리 커스텀해보기react-oauth/google 로 구글 로그인 연동해보기 구현swiper 라이브러리 커스텀해보기// LoginPage import "swiper/css/effect-fade"; <Swiper modules={[Autoplay, EffectFade, Pagination, A11y]} autoplay={auto} effect={"fade"} pagination={{ clickable: true, }} loop={true} fadeEffect={{ crossFade: true }} slidesPerView={1} speed={2000} > {...} </Swiper> // Row.tsx import "swiper/css/mousewheel"; <Swiper modules={[Navigation, Pagination, Scrollbar, A11y, Mousewheel]} navigation pagination={{ clickable: true }} mousewheel speed={1000} spaceBetween={10} > {...} </Swiper> 2024년 3월 10일의 디즈니 플러스 메인 페이지를 그대로 옮겨보고자 swiper 라이브러리를 커스텀해봤다.로그인 페이지에서는 좌우로 넘기는 슬라이드가 아닌 fade-in-out의 슬라이드를 구현하기 위해 swiper에 EffectFade 모듈을 추가하고 fadeEffect 속성을 추가했다.이 fadeEffect가 제대로 작동하기 위해선 반드시 해당 이펙트의 css를 추가해야 한다.다른 모듈이나 컴포넌트를 추가할 때처럼 자동으로 추가되지 않으니 주의해야 한다. (이걸 몰라서 한참을 찾았다. 😥)Row 컴포넌트는 마우스 휠에 따라 움직이는 슬라이드를 만들기 위해 Mousewheel 모듈과 속성을 이용했다.이렇게 슬라이드 속성을 정한 뒤에 swiper가 렌더링하는 요소의 class를 찾아 CSS에서 원하는 디자인으로 변경하면 된다.이때 라이브러리의 CSS와 겹치는 속성이 있을 수 있기 떄문에 '!important'를 붙이는 게 좋다. react-oauth/google 로 구글 로그인 연동해보기// index.js <GoogleOAuthProvider clientId={process.env.REACT_APP_CLIENT_ID}> <BrowserRouter> <App /> </BrowserRouter> </GoogleOAuthProvider> // App.jsx const navigate = useNavigate(); const [isLogin, setIsLogin] = useState( localStorage.getItem("user") ? true : false ); useEffect(() => { isLogin ? navigate("/") : navigate("/login"); }, [isLogin]); <Routes> {isLogin ? ( <Route path="/" element={<Layout setIsLogin={setIsLogin} />}> <Route index element={<MainPage />} /> <Route path=":movieId" element={<DetailPage />} /> <Route path="search" element={<SearchPage />} /> </Route> ) : ( <Route path="login" element={<LoginPage setIsLogin={setIsLogin} />} /> )} </Routes> react-oauth/google는 구글 로그인을 지원하는 라이브러리로, 사전에 구글의 Cloud에서 API 등록을 하고 Client ID를 발급받아야 사용할 수 있다.먼저 프로젝트의 최상위에 GoogleOAuthProvider로 감싸준다.그리고 사용자의 로그인 여부에 따라 페이지를 이동시키기 위해 라우터를 설정한 App 컴포넌트에서 관련 코드를 작성했다.페이지가 렌더링 될 때 로컬 스토리지에 저장된 유저 정보를 받아오고 만약 없다면 로그인 페이지로 보내도록 했다. // loginPage const googleLogin = async (credentialResponse) => { localStorage.setItem( "user", JSON.stringify(jwtDecode(credentialResponse.credential)) ); setIsLogin(true); }; <GoogleLogin onSuccess={(credentialResponse) => googleLogin(credentialResponse)} /> GoogleLogin 컴포넌트는 react-oauth/google 라이브러리에서 지원하는 버튼 컴포넌트로 디자인 및 로그인 관련 함수가 내장되어 있다.onSuccess는 사용자의 로그인이 성공했을 때 실행되는 콜백 함수이며, 인자로 로그인한 유저의 정보를 담은 데이터를 갖는다.여기서 credential이라는 값은 유저의 정보를 담고 있는 토큰으로 암호화되어 있기 때문에 jwt-decode 라이브러리를 이용해 디코딩하여 사용해야 한다.여기서 받은 picture는 사용자의 프로필 이미지 링크를 포함하고 있어서 Nav 컴포넌트에서 사용해 로그인한 유저의 프로필 이미지로 변경했다. 회고'Netflix 앱 만들기'를 하면서 사용했던 기술이 대부분이라 오래 걸리지 않을 것 같았지만...라이브러리 알아보고 문서 읽고 실행해보고... 하는 데 너무 오래 걸린 것 같다.배너 하단의 카테고리 부분은 이전에 같은 과제를 하셨던 분의 깃허브를 참고했다. (https://github.com/kimneighbor/clone-disney-plus-app)로그인 페이지는 따라하기 싫어서 현재 디즈니 플러스 홈페이지를 보고 참고했다.그대로 하면 얼마 안 걸릴 거라 생각했는데 생각보다 라이브러리 커스텀에서 좀 애를 먹었다. 😅with_networks: "2739" 2739는 TMDB에서 디즈니 플러스 방송사(networks) 코드라서 axios의 instance 기본 값에 추가했다.몇몇 요청은 해당 파라미터가 통하지 않거나 오류를 보내기도 해서 완벽하진 않다.디즈니 플러스에서 API를 제공했다면 더 알맞게 페이지를 구현할 수 있었을 텐데 하는 아쉬움이 남는다.한편 영화 정보 API를 제공해주는 TMDB(The Movie Database) 같은 곳이 있어 감사하고 다행이라는 생각이 들었다.프론트엔드 공부하는데 API를 제공해주는 곳이 아예 없었다면 혹은 매번 일정 비용을 지불해야 했다면 얼마나 힘들었을까로그인도 사실 좀 더 좋은 라우팅 구조나 상태 관리 라이브러리를 공부하고 사용해보고 싶었지만...계속 욕심만 커지는 것 같아 최대한 간단하게 구현하려 했다.(사실 과제 밀려서 조바심에 아무것도 못 했다... 😂) 

프론트엔드워밍업워밍업클럽프론트엔드프론트FE미션과제발자국

강지원

[인프런 워밍업 스터디 클럽 2기 FE] 강지원 과제 제출

<JavaScript 과제> Day 2 Mission (음식 메뉴 앱)github : https://github.com/noaprost/inflearn_study_js_mission/tree/main/mission1개발 시간 : 3시간개발 순서메뉴 정보를 담을 menu.json 파일을 만들었습니다.fetch를 사용하여 json 데이터를 불러오고 main 부분에 동적으로 child를 추가해주었습니다.각 카테고리 button에 onClick eventListener를 달아주고 curCategory 변수를 선언하여 현재 클릭 된 카테고리가 무엇 인지에 따라 다른 child가 main에 보여지도록 했습니다.아쉬웠던 점useEffect나 useState를 대체할 코드를 js로 짜는 것이 미숙해서 코드가 깔끔하게 짜이지 않은 것 같아 아쉽습니다.카테고리 버튼을 누를 때마다 main에 이미 있는 child를 모두 제거 후 다시 필터링해서 append 해주었는데, 코드가 비효율적인 것 같아서 아쉽습니다.느낀 점첫 과제를 무사히 끝내서 다행이다. 이번 과제는 바닐라 js로만 앱을 만든 것이 3년전 이후로 처음이라 많이 해맸지만 앞으로의 과제를 만들면서 js 실력이 많이 길러질 것 같아서 기대가 됐다. main 화면Breakfast를 클릭한 화면  Day 3 Mission (가위 바위 보 앱)github : https://github.com/noaprost/inflearn_study_js_mission/tree/main/mission2개발 시간 : 2시간구현 사항가위, 바위, 보 버튼을 누르면컴퓨터에서 랜덤 변수를 생성하고 플레이어와 승패를 비교합니다.승패에 따라 승리 횟수를 업데이트 해주고, 남은 횟수를 1 감소 시킵니다.남은 횟수가 모두 소진됐을 경우최종 승리 횟수를 비교해서 알맞는 문구를 띄워주고 replay 버튼을 보여줍니다.replay 버튼을 누를 경우모든 횟수가 초기화됩니다. 느낀 점한번 만들어봤던 앱이라서 바로 만들기부터 시작했는데, 중간에 막혀서 고생했다ㅠ 구현할 기능과 순서를 다시 쭉 적어 놓고 구현하니까 순조롭게 만들어져서 요구 사항 작성의 중요성을 다시 한번 깨달았다. main 화면 (게임 중)게임이 끝난 화면  Day 4 Mission (퀴즈 앱)github : https://github.com/noaprost/inflearn_study_js_mission/tree/main/misson3개발 시간 : 2시간구현 사항랜덤으로 1~50사이의 수를 골라서 문제를 생성합니다.랜덤으로 정답+랜덤 수 / 랜덤 수1+랜덤 수2+정답이 없습니다. 둘 중 하나를 보여줍니다.정답을 누를 경우 Next 버튼이 보여지고 버튼을 클릭하면 다음 문제로 이동합니다.문제를 틀렸을 경우 Restart 버튼이 보여지고 버튼을 클릭하면 새로운 문제를 보여줍니다. 아쉬웠던 점정답/틀린 답을 클릭했을 경우 ui를 보여줄 때 class 이름을 추가하고 삭제하는 방식으로 구현했는데, if문도 많이 중첩되어있고 긴 코드를 작성한 것 같아서 아쉽습니다. 추후에 더 나은 코드로 리팩토링을 하고 싶습니다. 만족한 점답 버튼을 최대한 랜덤으로 보이게 하고 싶어서 수를 먼저 만들고 이후에 동적으로 생성한 점이 만족스럽습니다. 느낀 점생각보다 구현할 때 신경 쓸 부분이 많았고, ui 처리가 어려웠지만 재밌게 만들었다. 영상에 요구 사항이 잘 안보여서 규칙 등을 직접 정하면서 만들었는데 그 점도 재밌었다. 문제를 띄운 화면정답을 클릭했을 경우오답을 클릭했을 경우  Day 5 Mission (책 리스트 나열 앱, Github Finder 앱) 책 리스트 나열 앱github 주소 : https://github.com/noaprost/inflearn_study_js_mission/tree/main/mission4개발 시간 : 1시간구현 순서form을 만들어서 input 값 2개를 받는다.submit 버튼을 누르면 input에 있던 값을 다른 변수에 저장해둔다.데이터를 가공해서 리스트에 책 제목과 저자, 삭제 버튼을 담은 목록을 보여준다.삭제 버튼을 누르면 해당 리스트가 삭제된다.느낀 점이번 과제는 개인적으로 정말 쉬웠다. todo 앱 강의를 먼저 듣고 나서 만들어서 그런지 가장 명확하게 구현 순서가 그려져서 재미있었다. 책 생성 화면책 삭제 화면Github Finder 앱github 주소 : https://github.com/noaprost/inflearn_study_js_mission/tree/main/mission5개발 시간 : 7시간구현 순서Github api로 user정보와 repo정보를 가져온 후, repo 정보는 최근에 작성된 것이 먼저 보여지도록 정렬한다.displayUserInfo와 displayLatestRepo 함수를 이용해서 각각의 정보를 화면에 보여준다.필요한 정보 정리// user data에서 가져올 목록 // 맨위 4개 태그 public_repos public_gists followers following // 리스트 info company blog location created_at // View Profile 버튼 html_url // 최근 리포 baseUrl repos_url // repo data에서 가져올 목록 // Latest Repos name -> html_url 이용해서 이동할 수 있도록 stargazers_count watchers_count forks_count 어려웠던 점새로운 user를 검색할 때 마다 userInfo와 latestRepo 컨테이너에 담긴 정보들을 지워주고 새로 담아야 하는데, 아래의 간단한 코드를 떠올리지 못해서 3시간이나 해맸다.document.getElementById("user-info").innerHTML = ""; document.getElementById("latest-repo").innerHTML = ""; 느낀 점처음 user의 정보를 가져오는 BaseUrl을 찾는 것이 어려웠지만 url을 찾고 나니 나머지는 데이터 가공 뿐이라서 만드는 과정은 재밌었다. main 화면검색 결과 화면 (user info)검색 결과 화면 (latest repo)  <React 과제> Day 9 Mission (예산 계산기)github 주소 : https://github.com/noaprost/inflearn_react_mission_budget_calculator개발 시간 : 4시간구현 사항예산 목록을 생성, 수정, 삭제할 수 있어야 한다.목록 지우기 버튼을 누르면 목록 전체가 삭제되어야 한다.생성, 삭제, 수정 시 맨 위에 status를 알려주는 상태 메세지를 띄워준다.총 예산을 계산해서 가장 아래쪽에 표시해준다. 느낀 점그동안 Next.js, Three.js 공부를 하느라 React 프로젝트를 오랫만에 만들었더니 간단한 CRUD 앱인데도 꽤나 어렵게 구현하였다. 역시 꾸준한 것 보다 좋은 것은 없는 것 같다ㅠㅠ 과제를 진행하면서 잠시 잊었던 감을 다시 찾아야겠다는 생각이 들었다. main 화면예산 입력 후 화면예산 수정 화면  Day 10 Mission(디즈니 플러스 앱)github 주소 : https://github.com/noaprost/disneyplus_clone개발 기간 : 약 2일페이지 별 구현 사항로그인 페이지firebase를 이용해서 구글로 로그인을 한다.로그인 버튼을 누르면 popup창이 뜨고 로그인이 되면 홈으로 이동한다.Navbaruser가 있으면 프로필 사진이 원형으로 보여지고, 없으면 LOGIN 버튼이 보여진다.disney 로고를 누르면 user가 있을 경우 "/home"으로 이동, 없을 경우 "/"로 이동한다.user 프로필 사진을 hover하면 LOGOUT 버튼이 1.5초간 보여지고 클릭 시 user 정보가 사라진다.메인 페이지axios를 이용해서 영화 목록을 받아온 뒤 영화 하나의 정보를 보여준다. (이미지, 제목, 설명)영화사 버튼을 만들고, hover 시 영상이 재생되도록 한다.인기 영화, 평점 높은 영화, 판타지 영화, 액션 영화 각 카테고리에 맞는 영화들의 이미지를 보여준다.카테고리에 보여지는 영화들은 swiper를 이용해서 감싸준다.카테고리에 보여지는 영화를 클릭할 경우 상세 정보를 담은 모달이 나오고, 화면 밖을 클릭할 경우 모달이 닫히게 해준다.Modal이미지, 개봉일, 제목, 평점, 설명을 보여준다.메인 페이지에 오면 검색 창이 나타나고, 검색어 입력 시 검색 페이지로 이동한다.검색 페이지에서 메인 페이지로 돌아오게 되면 useLocation을 이용해서 검색어를 초기화해준다.검색 페이지로 이동할 때 검색어 정보를 query에 담아 url에 파라미터로 보내준다.검색 페이지useLocation으로 받은 데이터를 가공해서 검색어를 저장한다.검색어가 변경될 때마다 검색어를 query로 받는 검색 결과를 업데이트 해준다.결과의 이미지를 목록의 형태로 보여준다.이미지를 클릭할 경우 화면에 꽉 찬 이미지가 보여진다. 느낀 점이번 프로젝트를 하면서 React, CSS, Html, JS에 대해 새로운 것을 많이 알게 되었다. 과제를 하는 동안에는 에러도 많이 나고, 데이터가 안받아지거나, 페이지가 예상한대로 동작하지 않아서 스트레스도 많이 받아가며 만들었지만, 그 과정에서 실력은 확실히 성장할 수 있었다. 끝나고 나니까 뿌듯하고 계속 보게 됐다. 아쉬운 점카테고리 별로 영화 정보를 받아올 때, 인기 영화와 평점 높은 영화를 받아오는 api 주소와 장르별 영화를 받아오는 api 주소가 달라서 서로 다른 컴포넌트에서 로직을 짰다. 이것 때문에 swiper 코드와 Modal 코드, 목록을 보여주는 코드들이 중복이 된 것 같아서 아쉽다. 로그인 페이지메인 페이지메인 페이지 (영화사 버튼 hover 시)메인 페이지 (카테고리 별 목록)메인 페이지 (영화 상세 정보 모달)검색 페이지검색 페이지 (이미지 클릭 시)  Day 12 Mission (퀴즈 앱)github 주소 : https://github.com/noaprost/quiz_app개발 시간 : 3시간라우터 구조 및 구현 사항"/"Welcome to Quiz App을 보여준다."/question"수학 문제 2개를 보여준다.라디오 버튼을 클릭하면 답변 확인 버튼이 뜬다.답변 확인 버튼을 클릭하면 정답을 클릭했을 경우와 오답을 클릭했을 경우를 나눠서 보여준다.정답을 클릭했을 경우 border color를 green으로, 오답을 클릭했을 경우 red로 보여준다.정답인 label에 v표시를 붙여주고, 오답인 label에는 x를 붙여준다."/state"math와 alphabet 중에 하나를 선택할 수 있는 select box를 보여준다.선택하면 카테고리에 맞는 문제를 보여준다.채점 방식은 question과 동일하다."/quiz"퀴즈를 보기 전math와 alphabet 중에 하나를 선택할 수 있는 select box를 보여준다.연습 테스트 시작 버튼을 보여준다. 클릭하면 퀴즈 화면으로 변경된다.퀴즈를 보는 중문제와 남은 문제 수가 보여진다.답을 선택하면 다음 버튼이 보여지고, 마지막 문제였을 경우 제출 버튼이 보여진다.다음 버튼을 선택하면 다음 문제가 보여지고, 제출 버튼을 누르면 결과 화면으로 변경된다.퀴즈를 본 후총 문제 수 중 몇 문제를 맞췄는지 보여준다. (합격했을 경우 초록색, 아닌 경우 빨간색)시험 합격/불합격 여부가 보여진다. (4개 전부 맞을 경우 합격, 아닌 경우 불합격)새로운 연습 테스트 시작 버튼이 보여진다.버튼 클릭 시, 퀴즈를 보기 전 화면으로 돌아간다. 아쉬운 점문제를 랜덤으로 동적 생성하고 퀴즈의 문제 수도 설정할 수 있도록 구현해보고 싶었는데 시간이 부족해서 구현하지 못했다. 스터디가 끝난 후에라도 혼자서 개발해보고 싶다. 느낀 점그래도 가장 최근에 개발할 때 사용했던 Next.js와 Typescript여서 비교적 편하게 개발했던 것 같다. 구조들이나 변수가 반복되는 부분이 많다 보니 코드를 가독성 있게 짜기가 쉽지 않았다. 리팩토링에 대한 공부의 필요성이 느껴졌다. home 화면question 화면 (문제를 풀기 전)state 화면 (문제를 푼 후)quiz 화면quiz 화면 (연습 테스트 시작)quiz 화면 (테스트 결과) 

JSReact인프런스터디과제미션

seongmin kim

인프런 워밍업 클럽 CS 2기 - 3주차 미션

운영체제1. 메모리의 종류는 어떤것들이 있나요? 각 메모리의 특징도 함께 적어주세요.레지스터휘발성 메모리컴퓨터의 bit = 레지스터의 크기메인메모리의 값을 가져와서 레지스터에서 연산하고 메인메모리로 저장캐시레지스터와 메인메모리 속도 차이 때문에 미리 데이터를 가져다 놓는 곳 메인메모리(RAM) 휘발성 메모리실제 운영체제와 다른 프로세스들이 올라오는 공간가격이 비쌈보조저장장치(HDD / SSD) 비휘발성 메모리파일 저장 공간2. 사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 어떤 레지스터일까요?경계 레지스터(Boundary Register): 주기억 장치(RAM)내에 존재하는 프로그램은 크게 운영체제와 사용자 영역으로 나뉜다. 사용자가 영역에 존재하는 OS영역에 침범하거나, 프로세스 경계를 벗어났다면 강제로 종료시킴3. 메모리 할당 방식에서 가변 분할 방식과 고정 분할 방식의 장단점은 뭔가요?가변 분할 방식프로세스가 크다면, 메모리도 크게 할당 장점: '내부 단편화(연속된 공간에 할당되므로, 더 크게 할당되어 낭비되는 공간)'가 없음 단점: '외부단편화(공간이 남는데 연속된 공간이 아니라 할당 할 수 없는 현상)' 발생고정 분할 방식일정 크기로 나누고, 프로세스 크기와 상관없이 메모리 할당 장점: 구현이 간단하며, 오버헤드가 적음 단점: 크기보다 더 할당되는 '내부 단편화'가 발생4. CPU 사용률을 올리기 위해 멀티프로그래밍을 올렸지만 스왑이 더 많이 이루어져 CPU 사용률이 0%에 가까워 지는 것을 뭐라고 할까요?스레싱5. HDD나 SSD는 컴퓨터를 실행시키는데 꼭 필요한 걸까요? 이유를 함께 적어주세요. 운영체제(OS)와 소프트웨어, 그리고 데이터를 저장하고 실행할 수 있도록 해 주기 때문에 실질적인 컴퓨터 사용을 위해선 꼭 필요하다. 6. 파일을 삭제해도 포렌식으로 파일을 복구할 수 있는 이유가 무엇일까요?파일시스템의 효율적인 관리를 위해 빈 공간에 모아둔 free block List가 있다. 특정 파일을 삭제하면 파일시스템은 파일테이블의 헤더를 삭제하고 free block list를 추가하는데, 이렇게 삭제된 위치는 사용자로 하여금 삭제된 것처럼 보인다.실제로는 물리적 디스크에 그대로 남아 있으므로 복구할 수 있다.자료구조와 알고리즘1. 지금까지 배운 5개의 정렬 알고리즘의 장단점과 시간 복잡도를 적어주세요.버블 정렬 장점: 이해와 구현이 쉽다.단점: 성능이 좋지 않다.시간 복잡도: O(n²)선택정렬 장점: 이해와 구현이 쉽다.단점: 성능이 좋지 않다.시간 복잡도: O(n²)삽입정렬 장점: 이해와 구현이 쉽다.단점: 성능이 좋지 않다.시간 복잡도: O(n²)병합정렬 장점: 성능이 좋다.단점: 정렬 배열을 저장한 메모리 공간 필요하다.시간 복잡도: O(n log n)퀵정렬 장점: 성능이 좋다.단점: 피벗설정을 잘못할 경우 O(n²)의 성능이 될 수 있다. 저장할 공간이 추가로 필요하다.시간 복잡도: O(n log n)2. 메모리가 부족한 시스템에서 어떤 문제를 해결하는데 재귀로 쉽게 구현이 가능할 것 같습니다. 여러분이라면 메모이제이션과 타뷸레이션 중 어떤 걸 이용하실 건가요? 이유를 함께 적어주세요.- 메모이제이션 (Memoization)방식: 재귀 호출 과정에서 계산된 값을 메모리에 저장하고, 동일한 계산이 필요할 때 저장된 값을 재사용하는 방식이다. 즉, 하향식(Top-Down) 접근법으로, 문제를 재귀적으로 나누면서 필요할 때마다 계산을 수행한다.장점재귀적인 접근이기 때문에 구현이 직관적이며, 복잡한 문제를 분할하여 풀기 좋다.필요한 부분만 계산해서 저장하므로, 일부 입력값에 대해서만 최적화된 결과를 저장할 수 있다.단점각 재귀 호출마다 스택을 사용하므로, 호출 깊이가 깊어지면 스택 오버플로우가 발생할 수 있다.메모리를 적게 사용하려는 상황에서 재귀 호출의 오버헤드와 캐싱을 위한 메모리 사용이 부담이 될 수 있다.- 타뷸레이션 (Tabulation)방식: 작은 문제부터 차례대로 해결하면서, 테이블에 저장된 값을 이용해 큰 문제를 푸는 방식이다. 이는 상향식(Bottom-Up) 접근법으로, 배열을 사용해 반복적으로 값을 계산해 나가는 방식이다.장점반복적인 접근 방식을 사용하기 때문에 스택 오버플로우의 위험이 없다.재귀 호출이 없어 호출 스택을 줄일 수 있어 메모리 사용을 최적화할 수 있다.단점모든 경우를 계산해서 테이블에 저장하므로, 메모리 사용량이 많을 수 있다.문제를 작은 부분으로 분해하여 해결하는 과정이 덜 직관적일 수 있다.이에 따라, 메모리가 부족한 시스템에서 안정성을 고려한다면, 타뷸레이션을 선택하겠다.

알고리즘 · 자료구조워밍업클럽미션

Jay

워밍업 클럽 CS 3주차 발자국 : 미션

운영체제메모리의 종류는 어떤것들이 있나요? 각 메모리의 특징도 함께 적어주세요.주기억장치 (RAM):특징: 휘발성 메모리로, 전원이 꺼지면 데이터가 사라집니다. 빠른 접근 속도를 가지며, 운영체제와 애플리케이션이 실행될 때 사용됩니다.보조기억장치 (HDD, SSD 등):특징: 비휘발성 메모리로, 전원이 꺼져도 데이터가 유지됩니다. HDD는 기계적인 구조로 상대적으로 느리지만 큰 용량을 제공하고, SSD는 전자적인 구조로 빠른 속도를 제공합니다.캐시 메모리:특징: CPU와 RAM 사이에 위치하여 자주 사용되는 데이터를 저장합니다. 빠른 접근 속도를 제공하여 CPU의 성능을 향상시키는 역할을 합니다.ROM (읽기 전용 메모리):특징: 비휘발성 메모리로, 주로 부팅 프로그램이나 펌웨어가 저장됩니다. 일반 사용자가 데이터를 수정할 수 없습니다.가상 메모리:특징: 물리적인 메모리 용량보다 큰 메모리를 사용할 수 있도록 해주는 기술로, 하드디스크의 일부를 메모리처럼 사용합니다.사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 어떤 레지스터일까요?사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 경계 레지스터(Bound Register)입니다.설명: 경계 레지스터는 프로세스가 접근할 수 있는 메모리의 범위를 정의합니다. 이 레지스터는 프로세스가 사용 가능한 메모리 영역의 최댓값을 설정하여, 프로세스가 해당 범위를 벗어나 메모리의 운영체제 영역이나 다른 프로세스의 영역에 접근하는 것을 방지합니다.작동 방식:프로세스가 메모리 접근을 시도할 때, CPU는 해당 주소가 경계 레지스터에 설정된 범위 내에 있는지 확인합니다.만약 접근하려는 주소가 경계 레지스터의 한계를 초과하면, CPU는 메모리 접근을 차단하고 오류를 발생시킵니다. 이를 통해 운영체제는 메모리의 보호 및 안정성을 유지할 수 있습니다.이러한 방식으로 경계 레지스터는 운영체제와 사용자 프로세스 간의 안전한 메모리 관리를 도와줍니다.메모리 할당 방식에서 가변 분할 방식과 고정 분할 방식의 장단점은 뭔가요?고정 분할 방식:장점: 관리가 간편하고, 메모리 할당 속도가 빠릅니다.단점: 내부 단편화가 발생할 수 있으며, 메모리의 유효 활용도가 떨어질 수 있습니다.가변 분할 방식:장점: 메모리를 더 효율적으로 사용할 수 있으며, 내부 단편화가 줄어듭니다.단점: 관리가 복잡하고, 외부 단편화 문제가 발생할 수 있습니다.CPU 사용률을 올리기 위해 멀티프로그래밍을 올렸지만 스왑이 더 많이 이루어져 CPU 사용률이 0%에 가까워 지는 것을 뭐라고 할까요?CPU 스케줄링의 목표는 CPU 사용률을 높이는 것입니다. 이를 위해 멀티 프로그래밍을 통해 동시에 실행되는 프로세스 수를 늘립니다. 하지만 프로세스 수가 많아지면 물리 메모리가 부족해져 일부 프로세스는 스왑 영역에 저장되고, 이로 인해 페이지 폴트가 빈번하게 발생합니다. 결국 스왑 작업이 CPU 작업 시간을 초과하게 되어 CPU 사용률이 떨어지고, 이 현상을 스레싱(thrashing)이라고 합니다. HDD나 SSD는 컴퓨터를 실행시키는데 꼭 필요한 걸까요?HDD나 SSD는 컴퓨터를 실행하는 데 필수적이지는 않지만, 데이터와 프로그램을 저장하는 데 중요한 역할을 합니다. 일부 시스템은 RAM을 활용한 메모리 부팅이 가능하여, 저장 장치 없이도 작동할 수 있는 임베디드 시스템이 존재합니다. 그러나 일반적으로 컴퓨터 운영에 필요한 데이터를 지속적으로 저장하기 위해 HDD나 SSD와 같은 저장 장치가 필요합니다. 파일을 삭제해도 포렌식으로 파일을 복구할 수 있는 이유가 무엇일까요?파일을 삭제하더라도 포렌식으로 복구할 수 있는 이유는, 파일 시스템이 삭제된 파일의 모든 정보를 즉시 지우지 않기 때문입니다. 파일이 삭제될 때, 파일 시스템은 해당 파일의 헤더를 파일 테이블에서 삭제하고 빈 공간을 관리하는 프리 블록 리스트에 추가합니다. 이 과정에서 파일의 데이터는 여전히 디스크에 남아 있습니다. 사용자는 파일이 삭제된 것처럼 느끼지만, 실제로는 데이터가 그대로 존재하기 때문에, 전문적인 도구와 기술을 사용하면 삭제된 파일의 데이터를 복구할 수 있습니다.  자료구조와 알고리즘지금까지 배운 5개의 정렬 알고리즘의 장단점과 시간 복잡도를 적어주세요.버블 정렬장점: 구현이 간단하고 직관적이며, 이미 정렬된 경우 최선의 성능을 보인다.단점: 효율성이 떨어지며, 평균 및 최악의 경우 시간 복잡도가 O(n²)로 비효율적이다.시간 복잡도:최선: O(n)평균: O(n²)최악: O(n²)선택 정렬장점: 구현이 간단하고, 추가적인 메모리 공간을 사용하지 않는다.단점: 비효율적이며, 항상 O(n²) 시간 복잡도를 가진다.시간 복잡도:최선: O(n²)평균: O(n²)최악: O(n²)삽입 정렬장점: 작은 데이터 집합에 대해 빠르게 동작하며, 안정적인 정렬 알고리즘이다.단점: 큰 데이터 집합에 대해서는 O(n²)로 비효율적이다.시간 복잡도:최선: O(n)평균: O(n²)최악: O(n²)병합 정렬장점: 안정적인 정렬 방식이며, O(n log n)의 시간 복잡도로 효율적이다.단점: 추가적인 메모리 공간이 필요하여, 공간 복잡도가 O(n)이다.시간 복잡도:최선: O(n log n)평균: O(n log n)최악: O(n log n)퀵 정렬장점: 평균적으로 O(n log n)의 시간 복잡도를 가지고, 메모리 사용이 효율적이다.단점: 최악의 경우 O(n²)로 성능이 떨어질 수 있으며, 불안정한 정렬이다.시간 복잡도:최선: O(n log n)평균: O(n log n)최악: O(n²) 메모리가 부족한 시스템에서 어떤 문제를 해결하는데 재귀로 쉽게 구현이 가능할 것 같습니다. 여러분이라면 메모이제이션과 타뷸레이션 중 어떤 걸 이용하실 건가요? 이유를 함께 적어주세요.메모리가 부족한 시스템에서는 타뷸레이션을 사용할 것입니다. 타뷸레이션은 하향식 접근 방식으로, 모든 가능한 상태를 테이블에 저장하여 나중에 재사용할 수 있게 합니다. 메모리 사용량이 제한된 상황에서, 문제를 작은 하위 문제로 나누어 해결하기 때문에 최적의 공간 효율성을 유지할 수 있습니다.반면, 메모이제이션은 재귀적인 방식으로 구현되어, 메모리가 부족한 시스템에서는 스택 오버플로우가 발생할 가능성이 높아질 수 있습니다. 따라서 타뷸레이션은 메모리를 더 효율적으로 활용하면서도 문제를 해결하는 데 유리한 선택이 될 것입니다.

미션

Jay 1개월 전
유선아

[미션] 인프런 워밍업클럽 CS 2기 3주차 미션

운영체제메모리의 종류는 어떤것들이 있나요? 각 메모리의 특징도 함께 적어주세요. 레지스터, 캐시 , 메인 메모리(RAM), 보조저장장치 하드디스크 가 있습니다.레지스터는 가장 빠른 기억 저장소로, CPU내에 존재하고, 휘발성 메모리입니다.캐시는 레지스터와 메인 메모리, 사이에 존재하고, 휘발성 메모리입니다. 캐시는 메인 메모리에 있는 값을 레지스터로 옮기는 시간을 단축하기 위해 미리 데이터를 가져와 저장하는 곳 입니다. 메인 메모리는 실제 운영체제와 프로세스가 올라가는 곳으로, 휘발성 메모리입니다. 하드 디스크나 SSD보다는 속도가 빠르지만, 가격이 비싸기 때문에 실행중인 프로그램만 올립니다.  보조 저장장치 (HDD, SSD) 는 비휘발성 메모리로 가격이 저렴해, 작업한 파일들을 저장한다.  사용자 프로세스가 메모리의 운영체제 영역에 침범하지 못하도록 만든 레지스터는 어떤 레지스터일까요?경계 레지스터 CPU내에 존재하며 메모리 관리자가 사용자 프로세스가 경계 레지스터의 값을 벗어나는지 감시하고, 벗어날 경우 프로세스를 종료시킨다.  메모리 할당 방식에서 가변 분할 방식과 고정 분할 방식의 장단점은 뭔가요?가변 분할 방식 장점) 프로세스의 크기에 따라 메모리를 할당하는 방식으로, 메모리의 연속된 공간에 할당되기 때문에, 낭비되는 공간인 내부 단편화가 없다 . 단점) 외부단편화가 발생한다. 고정 분할 방식장점) 프로세스의 크기 상관 없이 메모리를 할당하는 방식으로, 비연속 메모리 할당으로 구현이 간단하고 오버헤드가 적다. 단점) 작은 프로세스도 큰 영역에 할당되어서 공간이 낭비되는 내부 단편화가 발생한다.  CPU 사용률을 올리기 위해 멀티프로그래밍을 올렸지만 스왑이 더 많이 이루어져 CPU 사용률이 0%에 가까워 지는 것을 뭐라고 할까요?스레싱 CPU 사용률을 높이려하지만 오히려 더 떨어지는 상황이 나오는 것으로 ,CPU 사용률을 높이기 위해 멀티 프로그래밍 정도를 올리는데, 물리 메모리의 프레임을 할당하는데 한계가 있어 일부는 스왑영역에 저장하고, 이로 인해 Page Fault가 많이 발생하고, 그러면 CPU 작업 시간 보다 스왑 작업 시간이 더 길어 지고 CPU사용률이 떨어진다. 그럼 CPU 스케줄러는 CPU 사용률이 낮아져 더 많은 프로세스를 메모리에 올리게 되고 이 과정을 반복하다 보면 CPU 사용률이 0%에 가깝게 된다.  HDD나 SSD는 컴퓨터를 실행시키는데 꼭 필요한 걸까요? 이유를 함께 적어주세요.HDD나 SSD는 컴퓨터를 실행시키는 데 꼭 필요한 것은 아니지만, 현실적으로 대부분의 컴퓨터 환경에서 운영체제와 데이터를 저장하는 데 매우 중요한 역할을 하기 때문에 필수적이다.HDD나 SSD가 아닌 다른 메모리는 속도가 빠르지만 가격이 너무 비싸고 휘발성이기 때문에, 비휘발성인 HDD나 SSD 같은 보조 기억장치에 운영체제를 저장하고 필요한 데이터와 소프트웨어를 로드하는 것이 저렴하면서도 효율적으로 컴퓨터를 이용할 수 있는 방법이다. 파일을 삭제해도 포렌식으로 파일을 복구할 수 있는 이유가 무엇일까요?free block list 덕분이다. 만약 특정 파일을 삭제한다면, 파일 시스템은 파일의 모든 정보를 지우는 것이 아니라 파일 테이블의 헤더를 삭제하고 free block list에 추가한다. 이렇게 처리하면 사용자는 파일이 삭제된 것처럼 느끼지만, 사용했던 블록의 데이터는 그대로 남아있기 때문에 포렌식을 통해 데이터를 복구할 수 있다. 자료구조와 알고리즘지금까지 배운 5개의 정렬 알고리즘의 장단점과 시간 복잡도를 적어주세요.버블정렬장점 : 이해와 구현이 간단하다. 단점 : 성능이 좋지 않다. 시간 복잡도 : O(n²)선택 정렬장점 : 이해와 구현이 간단하다.단점 : 성능이 좋지 않다. 시간 복잡도 : O(n²)삽입 정렬장점 : 이해와 구현이 간단하다.단점 : 성능이 좋지 않다. 시간 복잡도 : O(n²)병합 정렬장점 : O(nlog n) 성능으로 버블, 선택 , 삽입 정렬보다 성능이 훨씬 좋다. 단점 : 재귀적인 기법으로 이해하기 어렵고, 구현하기 어렵다. 시간 복잡도 : O(n logn)퀵 정렬장점 : 성능이 좋고, 병합 정렬보다도 적은 메모리 공간을 차지해 더 좋은 알고리즘으로 평가 받는다. 단점 : 재귀적인 기법으로 이해하기 어렵고, 구현하기 어렵다. 시간복잡도 : O(n logn)메모리가 부족한 시스템에서 어떤 문제를 해결하는데 재귀로 쉽게 구현이 가능할 것 같습니다. 여러분이라면 메모이제이션과 타뷸레이션 중 어떤 걸 이용하실 건가요? 이유를 함께 적어주세요.타뷸레이션  메모이제이션은 재귀 호출을 사용하기 때문에 함수 호출에 따른 오버헤드와 메모리 비용이 큽니다. 반면, 타뷸레이션은 반복문을 사용하여 오버헤드가 적고, 메모리 사용량도 예측 가능하기 때문에 더 효율적입니다

알고리즘 · 자료구조워밍업클럽운영체제자료구조알고리즘CS미션

유선아

[미션] 인프런 워밍업클럽 CS 2기 2주차 미션

운영체제FIFO 스케줄링의 장단점이 뭔가요?FIFO 스케줄링의 장점은 단순하고 직관적입니다.단점은 한 프로세스가 다 끝나야 다음 프로세스가 시작되기 때문에, 실행시간이 짧은 프로세스라도 늦게 도착할 경우, 먼저 도착한 실행시간이 긴 프로세스가 끝날때까지 기다려야 한다는 단점이 있습니다. SJF를 사용하기 여러운 이유가 뭔가요?SJF는 이론적으로 FIFO 보다 성능이 좋지만, 실제로 어떤 프로세스가 얼마나 걸릴지 예측하기 힘들기 때문입니다.또한 Burst Time이 짧은 프로세스가 먼저 실행되기 때문에, Burst Time이 긴 프로세스는 앞에 모든 프로세스를 기다리며 아주 오랫동안 실행이 안 될수도 있다는 문제 때문에 사용하기 어렵습니다. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?타임 슬라이스가 아주 작으면 컨텍스트 스위칭이 자주 발생하기 때문에 타임 슬라이스에서 실행되는 프로세스의 처리량보다 컨텍스트 스위칭을 처리량이 더 커져 오버헤드가 커지게 되는 문제가 발생합니다. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요? CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하면 CPU 사용이 적은 것이니 I/O Bound Process 라고 인식하고,반대로 프로세스가 CPU 스케줄러에 의해 강제로 CPU를 뺏기는 상황이면 CPU 사용이 많은 것이니 CPU Bound Process 라고 인식합니다. 공유자원이란무엇인가요?프로세스간 통신을 할 때 공동으로 사용하는 변수나 파일입니다. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요? 상호배제 : 한 프로세스가 한 자원을 점유하면, 다른 프로세스에게 공유되면 안됩니다.비선점 : 한 프로세스가 한 자원을 점유하는동안, 다른 프로세스가 이를 뺏을 수 없어야 합니다.점유와 대기 : 한 프로세스가 한 자원을 점유할때, 다른 프로세스도 같은 자원을 원해야 합니다.원형 대기 : 점유와 대기를 하는 프로세스의 관계가 원형이어야 합니다.이 중 한가지 조건도 충족하지 않을 경우, 교착상태가 발생하지 않습니다. 자료구조와 알고리즘재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저조건이 없을 경우, 재귀 함수를 탈출하지 못하고 계속해서 재귀함수가 호출된다. 즉, 콜 스택에 계속해서 함수가 쌓여서 메모리가 부족해져 프로세스가 강제 종료될 수 있습니다. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ // 재귀 로직 if (n <= 0) { return 0; } return (n % 2 === 1? n : 0) + sumOdd(n - 1); } console.log(sumOdd(10)) // 25v2function sumOdd(n){ // 기저 조건 if(n <= 1) { return n; } // 재귀 로직 if(n % 2 == 0){ return sumOdd(n -1); // n이 짝수일 때, n-1로 재귀호출 } else{ return n + sumOdd(n - 2); // n이 홀수일 때, n을 더하고 n-2로 재귀호출 } } console.log(sumOdd(10)) // 25 v3 (java)public class SumOddClass{ public static int sumOdd(int n){ // 기저 조건 if (n <= 1) { return n; } // 짝수일 때 n-1로 재귀 호출 if (n % 2 == 0){ return sumOdd(n -1); } // 홀수일 때 n을 더하고 n-2로 재귀 호출 return n + sumOdd(n -2); } public static void main(String[] args){ int n = 10; int result = sumOdd(n); System.out.println(result); } } 

워밍업클럽운영체제자료구조알고리즘CS미션

인프런 워밍업 클럽 스터디 2기 - CS 2주차 미션

운영체제 Q. FIFO 스케줄링의 장단점이 뭔가요? 장점 : 단순하고 직관적단점 : 프로세스의 Burst Time에 따라 성능이 좌우됨, I/O 작업이 있다면 I/O 작업이 끝날 때 까지 CPU는 쉬기 때문에 CPU 사용률이 떨어짐 Q. SJF를 사용하기 어려운 이유가 뭔가요? 프로세스가 끝나는 시간을 예측할 수 없음만약 Burst Time이 짧은 프로세스가 계속 추가된다면 Burst Time이 긴 프로세스는 영영 실행되지 않을 수 있음 Q. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요? 컨택스트 스위칭이 자주 발생하여 오버헤드가 커짐 Q. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요? CPU를 스스로 반납한다면 -> I/O Bound ProcessCPU를 강제로 빼앗긴다 -> CPU Bound Process Q. 공유자원이란 무엇인가요? 프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일들 Q. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요? 상후배제 - 어떤 프로세스가 리소스를 점유했다면 다른 프로세스에서 리소스를 점유할 수 없음비선점 - 다른 프로세스의 리소스를 빼앗을 수 없음점유와 대기 - 리소스 A를 가지고 있는 상태에서 리소스 B를 기다림원형 대기 - 점유와 대기를 하는 프로세스들의 관계는 원형을 이루어야 함 자료구조와 알고리즘Q. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요? 콜스택이 꽉 차서 에러가 발생함 Q. 0부터 입력 n 까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.

알고리즘 · 자료구조미션

f1rstf1y9

[인프런 워밍업클럽 CS 2기] 2주차 미션📒

운영체제1. FIFO 스케줄링의 장단점이 뭔가요?FIFO 알고리즘은 단순하게 프로세스가 큐에 들어온 순서대로 CPU를 할당받기 때문에, 알고리즘이 단순하고 직관적이라는 장점이 있습니다.다만, 먼저 들어온 프로세스가 완전히 끝나야만 다음 프로세스가 실행되기 때문에, 실행 시간이 짧고 늦게 도착한 프로세스가 실행 시간이 길고 빨리 도착한 프로세스의 작업을 한참 다려야해서 비효율적입니다. 또한 I/O 작업이 들어오면 CPU는 해당 I/O 작업이 끝날 때까지 쉬고 있게 되기 때문에 CPU 사용률이 떨어진다는 단점이 있습니다. 2. SJF를 사용하기 여러운 이유가 뭔가요?SJF는 Shortest Job First로, Burst Time이 짧은 프로세스를 먼저 실행시키는 알고리즘입니다. 만약 그러한 알고리즘을 사용한다면, 어떤 프로세스가 얼마나 오래동안 실행될지 예측이 어렵고, Burst Time이 긴 프로세스는 아주 오랫동안 실행되지 않을 수 있기 때문에 사용하기 어렵습니다. 3. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?RR는 Round Robin으로, 특정한 타임 슬라이스만큼 프로세스에게 CPU를 할당했다가, 해당 시간이 지나면 다른 프로세스에게 CPU를 할당하는 방식으로 동작하는 알고리즘입니다. 만약 RR 스케줄링에서 타임 슬라이스가 아주 작으면 그 짧은 시간마다 계속해서 실행되던 프로세스에게서 CPU를 뺏어서 다른 프로세스에게 CPU를 할당해야하고, 그만큼 컨텍스트 스위칭이 자주 일어나게 됩니다. 결국 프로세스의 처리량보다 컨텍스트 스위칭을 처리하는 비용이 더 커져서 오버헤드가 커집니다. 4. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?MLFQ는 Multi Level Feedback Queue로, 우선순위 큐를 여러개 두어 우선순위가 높으면 타임 슬라이스 크기가 작고, 우선순위가 낮으면 타임 슬라이스 크기가 커지는 방식의 알고리즘입니다. 기본적으로 CPU Bound Process에게는 타임 슬라이스를 크게 주고, I/O Bound Process에게는 타임 슬라이스를 작게 줍니다. 이때, CPU를 사용하는 프로세스가 스스로 CPU를 반납하면 I/O Bound Process일 확률이 높고, 실행 도중에 CPU 스케줄러에 의해 강제로 CPU를 뺏기는 상황이 발생하면 CPU Bound Process일 확률이 높으므로 이를 이용해 두 프로세스를 구분합니다. 5. 공유자원이란무엇인가요?공유자원이란 프로세스가 통신할 때 공동으로 이용하는 변수, 파일 등으로 한 마디로 여러 프로세스가 함께 공유하고 있는 자원을 의미합니다.공유자원은 각 프로세스의 접근 순서에 따라 결과가 달라지는데, 시분할 처리로 인해 어떤 프로세스가 먼저 실행되고 나중에 실행되는지 예측하기 어려워 연산 결과를 예측하기 힘듭니다. 6. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?교착 상태에 빠질 수 있는 조건으로는 상호배제, 비선점, 점유와 대기, 원형 대기의 4가지가 있습니다. 이 중 하나라도 만족하지 못하면 교착상태는 발생하지 않습니다.상호배제 - 어떤 프로세스가 한 프로세스를 점유하면, 그 리소스는 다른 프로세스에게 공유되면 안됩니다.비선점 - 프로세스 A가 리소스를 점유하고 있으면 다른 프로세스는 그 리소스를 뺏을 수 없습니다.점유와 대기 - 어떤 프로세스가 리소스A를 갖고 있는 상태에서 다른 리소스B를 원하고 있는 상황이어야 합니다.원형 대기 - 점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있어야 합니다.자료구조와 알고리즘1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저조건을 만들지 않거나 잘못 설정하면 무한히 재귀함수가 호출되어 콜스택 메모리 공간이 가득 차게 되고, 자동으로 종료되는 등 예기치 못하게 프로그램이 동작할 수 있습니다. 2. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ if (n <= 0) return 0; if (n % 2 == 0) { return n + sumOdd(n-2); } else { return sumOdd(n-1); } } console.log(sumOdd(10));

워밍업클럽CS미션

seongmin kim

인프런 워밍업 클럽 CS 2기 - 2주차 미션

운영체제 1. FIFO 스케줄링의 장단점이 뭔가요?FIFO = 먼저 들어온 작업이 먼저 나간다는 뜻FIFO 스케줄링: 스케줄링 큐에 들어온 순서대로 CPU를 할당받는 방식장점: 단순하고 직관적인 알고리즘단점: 한 프로세스가 완전히 끝나야 다음 프로세스가 실행되기 때문에, 실행시간이 짧고 늦게 도착한 프로세스가 실행시간이 길고 빨리 도착한 프로세스의 작업을 기다려야 한다.2. SJF를 사용하기 여러운 이유가 뭔가요?SJF = Shortest Job FirstFIFO(First in First Out)에서 Burst Time이 짧은 프로세스를 먼저 실행했을 때 평균 대기 시간이 짧아진 것에서 아이디어를 얻음이론적으로는 FIFO보다 성능이 좋으나, 실제 구현 시 문제가 발생함어떤 프로세스가 얼마나 실행될지 예측하기 힘들다.Burst Time이 긴 프로세스는 아주 오랫동안 실행되지 않을 수도 있다.3. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?타임슬라이스가 너무 짧으면 CPU 스위칭이 빈번하게 일어나 오버헤드가 발생할 수 있다.4. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?CPU Bound Process: CPU를 사용하는 프로세스가 실행하다가 CPU 스케줄러에 의해 강제로 CPU를 뺏기는 경우, CPU 사용률이 높음I/O Bound Process: CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하는 경우, CPU 사용률이 낮음 5. 공유자원이란 무엇인가요?프로세스 간 통신을 할 때 공동으로 이용하는 변수나 파일들여러 프로세스가 공유하고 있기 때문에 각 프로세스의 접근 순서에 따라 결과가 달라질 수 있다.6. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?교착상태(데드락): 여러 프로세스가 서로 다른 프로세스의 작업이 끝나기를 기다리다가 아무도 작업을 진행하지 못하는 상태상호배제: 어떤 프로세스가 한 리소스를 점유했다면, 그 리소스는 다른 프로세스에게 공유가 되면 안된다.비선점: 프로세스 A가 리소스를 점유하고 있는데, 프로세스 B가 리소스를 빼앗을 수 없어야 한다.점유와 대기: 어떤 프로세스가 리소스 A를 가지고 있는 상태에서 리소스 B를 원하는 상태여야 한다.원형 대기: 점유와 대기를 하고 있는 프로세스가 원형을 이루고 있어야 한다.자료구조와 알고리즘 1. 재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?기저 조건: 재귀 함수를 멈추는 조건기저조건을 만들지 않거나 잘못 설정하면 무한 루프가 발생하여 스택 오버플로우가 발생할 수 있다.2. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.Pythondef sum_odd_numbers(n): if n <= 0: return 0 # n이 홀수일 때 n을 더하고, n-1로 재귀 호출 elif n % 2 != 0: return n + sum_odd_numbers(n - 1) # n이 짝수일 때 n-1로 재귀 호출 else: return sum_odd_numbers(n - 1) n = 10 print(sum_odd_numbers(n))

알고리즘 · 자료구조워밍업클럽미션

Jay

워밍업 클럽 CS 2주차 발자국 : 미션

운영체제FIFO 스케줄링의 장단점이 뭔가요?장점:단순성: FIFO 스케줄링은 구현이 매우 간단합니다. 프로세스가 도착한 순서대로 CPU를 할당받습니다.예측 가능성: 각 프로세스가 실행될 순서를 쉽게 알 수 있어, 작업의 순서가 명확합니다.단점:젊은 프로세스 대기: 새로운 프로세스가 도착하면 오래된 프로세스가 끝날 때까지 기다려야 하므로, 긴 작업이 젊은 프로세스의 대기 시간을 증가시킬 수 있습니다.비효율적인 CPU 사용: 짧은 작업이 긴 작업 뒤에 대기하게 되면, 전체 대기 시간과 응답 시간이 길어져 시스템 자원의 비효율성을 초래할 수 있습니다.또한 입출력 작업이 있다고 한다면 CPU는 입출력 작업이 끝날 때까지 쉬고 있기 때문에 CPU 사용률이 하락합니다. SJF를 사용하기 여러운 이유가 뭔가요?예측의 어려움: SJF는 각 프로세스의 실행 시간을 미리 알아야 최적의 스케줄링이 가능하지만, 실제 실행 시간은 정확히 알기 어렵습니다.선택의 문제: SJF를 구현하기 위해 모든 프로세스의 실행 시간을 파악해야 하므로, 이 정보를 수집하는 데 시간이 소요될 수 있습니다. 또한, 이를 위해 프로세스를 정렬해야 하므로 CPU 자원을 추가로 사용해야 합니다.스타베이션: 짧은 작업이 우선적으로 실행되므로, 긴 작업이 계속해서 대기 상태에 있을 수 있으며, 이로 인해 긴 작업이 스타베이션에 빠질 위험이 있습니다. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?과도한 문맥 전환: 타임 슬라이스가 너무 작으면 각 프로세스의 실행 시간이 짧아져 문맥 전환이 자주 발생합니다. 이로 인해 CPU의 부하가 증가하고, 문맥 전환에 소요되는 시간이 전체 실행 시간을 초과할 수 있습니다.응답 시간 증가: 각 프로세스가 CPU를 할당받는 시간이 줄어들어, 응답 시간이 증가할 수 있으며, 특히 I/O 바운드 프로세스에서는 더 큰 영향을 받을 수 있습니다.비효율적인 자원 사용: CPU가 실행 중인 프로세스를 자주 변경함에 따라 자원 사용의 비효율성이 발생할 수 있습니다. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?CPU Bound Process: CPU 자원을 주로 사용하는 프로세스로, 계산이 많이 필요합니다. 프로세스가 타임 슬라이스 크기를 오버해서 CPU 스케줄러에 의해 강제로 CPU를 뺏기는 상황이면 CPU 사용이 많은 것이니, CPU 바운드 프로세스일 확률이 높습니다.I/O Bound Process: 주로 I/O 작업을 수행하며, CPU 사용 시간이 짧고 대기 시간이 깁니다. CPU를 사용하는 프로세스가 실행하다가 스스로 CPU를 반납하면 CPU 사용이 적은 거니, I/O 바운드 프로세스일 확률이 높습니다. 공유자원이란 무엇인가요?공유자원은 프로세스 간 통신에서 여러 프로세스 또는 스레드가 동시에 접근하거나 사용할 수 있는 자원을 의미합니다.공유자원은 협업과 데이터 통신을 용이하게 하지만, 공유 자원에 대한 접근 순서에 따라 연산 결과가 달라질 수 있습니다. 컨텍스트 스위칭으로 인해 어떤 프로세스가 먼저 실행될지 예측할 수 없어 동기화 문제가 발생할 수 있습니다.또한 동시에 여러 프로세스가 접근할 경우 교착상태나 경쟁 상태와 같은 문제를 초래할 수 있습니다. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야 할까요?교착상태가 발생하기 위한 네 가지 조건은 다음과 같습니다:상호 배제 (Mutual Exclusion): 자원은 한 번에 하나의 프로세스만 사용할 수 있어야 하며, 다른 프로세스는 사용할 수 없다.점유와 대기 (Hold and Wait): 적어도 하나의 프로세스가 자원을 점유한 상태에서 다른 자원을 요청해야 한다.비선점 (No Preemption): 이미 점유한 자원은 자발적으로 반환되기 전까지 다른 프로세스가 빼앗을 수 없다.환형 대기 (Circular Wait): 프로세스들이 서로 자원을 기다리며, 대기하는 프로세스의 원이 형성되어야 한다. 자료구조와 알고리즘재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?무한 재귀: 기저 조건이 없거나 잘못 설정되면 재귀 함수가 종료되지 않고 무한히 자기 자신을 호출하게 됩니다. 이로 인해 스택 메모리가 소진되어 스택 오버플로우가 발생할 수 있습니다.비효율적인 성능: 재귀 호출이 계속되어 성능 저하가 발생할 수 있으며, 필요한 자원(메모리, CPU 시간)이 비효율적으로 소모됩니다. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.function sumOdd(n){ if (n <= 0) { return 0; } const isOdd = n % 2 === 1; return (isOdd ? n : 0) + sumOdd(n - 1); } console.log(sumOdd(10)) // 25

미션

Jay 1개월 전
대롱대롱

[인프런 워밍업클럽 CS 2기] 2주차 미션

2주차 미션 시작합니다. 운영체제FIFO 스케줄링의 장단점이 뭔가요?FIFO 스케줄링은 스케줄링 큐에 들어온 순서대로 CPU를 할당받는 방식입니다.장점단순하고 직관적입니다.(들어온 순서대로 실행되고 나가면 끝!)단점실행시간이 짧은데 늦게 온 프로세스는 실행시간이 길고 먼저 온 프로세스를 기다려야 합니다. 순서대로 실행되어야 하기 때문이죠.만약에 입출력 작업이 먼저 와 있다면 입출력 작업이 끝날 때까지 CPU가 쉬어야해서 CPU 사용률이 감소한다는 단점이 있습니다. SJF를 사용하기 여러운 이유가 뭔가요?SJF(Shortest Job First)는 짧은 작업을 먼저 실행하는 알고리즘입니다.SJF에는 2개의 문제점이 있습니다.1) 어떤 프로세스가 얼마나 실행될지 예측하기 어렵다는 점2) Burst time이 짧은 프로세스가 중간에 계속 들어오면 긴 프로세스는 계속 뒤로 밀려 아주 오랫동안 실행되지 않을 수 있다는 점이런 문제점 때문에 SJF는 사용하기 어렵습니다. RR 스케줄링에서 타임 슬라이스가 아주 작으면 어떤 문제가 발생할까요?RR스케줄링에서 타임슬라이스가 아주 작으면 앱이 동시에 동작하는 것처럼 느낄 수 있습니다.그러나 단점으로는 오버헤드가 너무 커진다는 것입니다. Context Switching 처리량이 실행되는 프로세스 처리량보다 많기 때문에 이런 일이 발생하게 됩니다. 운영체제가 MLFQ에서 CPU Bound Process와 I/O Bound Process를 어떻게 구분할까요?CPU bound process는 대부분의 시간에 CPU연산을 하는 프로세스입니다.CPU를 많이 사용하기 때문에 CPU사용하는 프로세스가 실행하다가 CPU스케줄러에 강제로 CPU를 빼앗긴다면 운영체제는 CPU bound process로 판단합니다.I/O bound process는 대부분의 시간을 I/O작업으로 보내고 CPU연산을 조그맣게 합니다. CPU 사용이 적기 때문에 CPU사용하는 프로세스가 스스로 CPU를 반납한다면 운영체제는 CPU I/O process로 판단합니다. 공유자원이란무엇인가요?공유자원이란 프로세스 간 통신을 할 때 '공동으로 이용'하는 변수나 파일들을 의미합니다. 교착상태에 빠질 수 있는 조건은 어떤 것들을 충족해야할까요?교착상태에 빠지기 위해서는 아래 4가지로 이 조건들을 모두 충족해야 합니다.1) 상호배제한 프로세스가 한 리소스를 점유했다면 그 리소스는 다른 프로세스에서 공유될 수 없습니다.2) 비선점한 프로세스가 리소스를 점유할 때 다른 프로세스가 리소스를 뺏을 수 없습니다.3) 점유와 대기어떤 프로세스가 한 리소스를 가지고 있는 상태에서 다른 리소스를 원하는 상태입니다.4) 원형대기점유와 대기를 하는 프로세스들의 관계가 원형을 이루고 있어야합니다.  자료구조와 알고리즘재귀함수에서 기저조건을 만들지 않거나 잘못 설정했을 때 어떤 문제가 발생할 수 있나요?재귀함수에서 기저조건을 만들지 않거나 잘못 설정하면 재귀함수가 계속 호출되게 되고 메모리가 금방 가득 차서 프로그램 자동 종료되는 상황이 생길 수 있습니다. 0부터 입력 n까지 홀수의 합을 더하는 재귀 함수를 만들어보세요.def sumOdd(n): if n<=0: return 0 if n % 2 == 1: #홀수 return n + sumOdd(n-2) else: return sumOdd(n-1) print(sumOdd(10))

미션운영체제알고리즘자료구조cs

f1rstf1y9

[인프런 워밍업클럽 CS 2기] 1주차 미션📒

운영체제 1. while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 } 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? 폴링 방식의 성능 문제를 해결하기 위해서는 인터럽트를 사용할 수 있습니다. 인터럽트란, CPU가 주기적으로 실행이 완료되었는지 상태를 체크하는 대신, 그 시간에 다른 작업을 수행할 수 있도록 하는 메커니즘입니다. 즉, CPU가 계속해서 상태를 확인하지 않아도 특정 조건이 충족되면 원래의 작업을 즉시 처리할 수 있게 하는 알림 같은 개념이다.코드 수정해보기스킬 사용 여부를 계속 체크하는 대신, 다른 작업을 수행하면서도 플레이어가 스킬을 사용했을 때를 감지해서 특정한 반응이 일어날 수 있도록 코드를 수정했습니다.void onSkillActivated() { // 스킬이 활성화 되면 실행되는 코드 activateSkill(); } int main() { // 스킬 사용 이벤트에 인터럽트 핸들러 등록 registerInterruptHandler("SkillActivated", onSkillActivated); while (true) { // 기타 게임 로직 처리 } return 0; } 2. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 코드, 즉 명령어의 집합으로 .exe와 같은 파일 형태로 존재합니다. 실행되지 않으면 CPU, 메모리 등의 시스템 자원을 사용할 수 없습니다. 이제 이러한 프로그램을 더블 클릭 등으로 실행을 시키면 메모리에 적재되어 CPU에서 실제로 실행되고, 바로 그것을 프로세스라고 부릅니다. 프로세스는 실행 중일 때 시스템 자원을 사용합니다. 또한 준비 상태, 실행 상태, 대기 상태 등 다양한 상태를 가집니다.한 마디로 프로그램은 실행 중이 아닌 상태의 코드이고, 프로세스는 실행 중인 상태의 프로그램입니다. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 메모리 상에 여러 프로세스가 존재하고, CPU가 이 프로세스들을 번갈아 가며 실행하는 방식입니다. 멀티프로세싱은 CPU가 여러개의 프로세스를 처리하는 방식입니다.  운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요? 운영체제는 PCB(Process Control Block)를 사용하여 프로세스를 관리합니다. PCB에는 각 프로세스에 대한 정보가 저장되어 있습니다. 포인터, 프로세스 상태, 프로세스 ID, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보, CPU 스케줄링 정보 등 프로세스에 효율적으로 접근하고, CPU가 뺏겼다가 프로세스가 다시 실행될 때와 같은 상황에 필요한 정보들이 PCB에 담겨있습니다. 컨텍스트 스위칭이란 뭔가요?운영체제가 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행 중인 프로세스의 상태를 PCB에 저장하고, 다른 프로세스의 상태값으로 CPU의 세팅을 변경하는 작업을 말합니다. CPU의 점유 시간이 다 된 경우, I/O 요청이 있는 경우, 다른 종류의 인터럽트가 있는 경우에 컨텍스트 스위칭이 발생합니다. 예를 들어 프로세스 A의 CPU 점유 시간이 다 된 경우, 현재 CPU 레지스터 값을 PCB A에 저장하고, 다음에 실행될 프로세스의 PCB를 참조해서 해당 프로세스의 마지막 상태로 CPU의 레지스터 값을 세팅합니다.  자료구조와 알고리즘 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 학생 정보를 저장하기 위해 해시 테이블을 사용하면 좋을 것 같습니다. 일반적으로 학생들은 고유한 학번(학생 id)을 갖고 있기 때문에 이러한 학번을 key로 사용하면, 특정 학생의 id만 알고있으면 학생의 정보에 빠르게(O(1)) 접근할 수 있어 유용할 것이라고 생각합니다. 또한 한 교실의 학생 인원에 변동(전학 등)이 생길 경우 해시 테이블을 사용한다면 학생 데이터의 삽입, 삭제도 빠르게 할 수 있습니다. 다만, 해시함수에서 충돌이 발생할 수 있기 때문에 이 점에 유의해서 프로그램을 작성해야할 것입니다. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.주어진 조건에 가장 적합한 자료구조는 큐라고 생각합니다.큐는 FIFO(First In First Out), 가장 먼저 들어온 것이 가장 먼저 나가는 방식으로 동작합니다. 따라서 큐를 사용하면 주문이 들어온 순서대로 처리할 수 있습니다. 또한 새로운 주문을 큐의 끝에 추가하는 삽입 연산, 가장 먼저 들어온 주문을 큐의 맨 앞에서 제거하는 삭제 연산 등의 간단한 연산만으로 주문 프로그램을 구현할수 있습니다.

워밍업클럽CS미션

Jay

워밍업 클럽 CS 1주차 발자국 : 미션

운영체제1. 아래 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 }인터럽트를 활용할 수 있습니다.CPU는 입출력 관리자에게 입출력 명령을 내리고, 이 과정에서 다른 작업을 계속 수행할 수 있습니다.입출력 관리자는 입출력이 완료되면 CPU에게 신호를 보내고, CPU는 이 신호를 수신하여 서비스 루틴(Interrupt Service Routine, ISR)을 실행해 작업을 완료합니다.여기서 서비스 루틴이란 특정 인터럽트가 발생했을 때 해당 인터럽트를 처리하기 위해 실행되는 함수를 말합니다.(이 때, “특정 인터럽트가 발생했을 때 해당 인터럽트를 처리한다”는 것은 CPU가 어떤 특정한 이벤트(인터럽트)를 감지하고, 그 이벤트에 따라 미리 정의된 작업, 즉 서비스 루틴을 실행하는 과정을 의미합니다)인터럽트는 비동기적으로 동작하기 때문에 성능을 개선할 수 있는 이점이 있습니다.이와 같이 인터럽트를 사용하면 폴링 방식보다 더 효율적으로 스킬 사용 여부를 체크할 수 있으며, CPU 자원을 보다 효과적으로 활용할 수 있습니다. 2. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 하드디스크나 SSD와 같은 저장장치에 저장된 명령어와 데이터의 집합입니다. 예를 들어, 애플리케이션이나 앱도 프로그램에 해당됩니다. 프로그램은 그 자체로는 실행되지 않으며, 컴퓨터가 실행할 준비 상태에 있는 정적인 존재입니다.프로세스는 실행 중인 프로그램을 의미합니다. 저장장치에 있던 프로그램이 메모리에 로드되어, 운영체제의 제어를 받으며 CPU, 메모리 등 컴퓨터 자원을 활용해 작업을 수행하는 능동적인 존재입니다. 프로세스는 CPU 스케줄링을 통해 처리되고, 필요에 따라 입력 및 출력 작업도 수행합니다. 3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 하나의 CPU가 여러 프로세스를 시분할 방식으로 처리하는 메모리 관리 개념입니다.멀티프로세싱은 여러 CPU가 각기 다른 프로세스를 병렬로 처리하는 CPU 관리 개념입니다.멀티프로그래밍은 메모리 관점에서 여러 프로그램(또는 프로세스)이 동시에 메모리에 올라와 있는 상태를 말합니다. 운영체제는 이 프로그램들 중 하나가 CPU를 사용할 수 없을 때(예: 입출력 작업 대기 시) 다른 프로그램이 CPU를 사용할 수 있도록 하여 자원의 효율성을 높입니다. 즉, 하나의 CPU가 여러 프로그램을 시분할 방식으로 실행하는 것을 말합니다. 멀티프로그래밍의 반대 개념은 유니프로그래밍, 즉 한 번에 하나의 프로그램만 메모리에 올라오는 방식입니다.멀티프로세싱은 CPU 관점에서 둘 이상의 CPU가 동시에 여러 프로세스를 처리하는 것을 의미합니다. 멀티프로세싱 시스템에서는 각 CPU가 독립적으로 다른 작업을 수행할 수 있기 때문에 작업 처리 속도와 시스템의 효율성이 크게 향상됩니다. 이는 다중 CPU 또는 코어를 활용하는 시스템에서 이루어지며, 이를 통해 여러 프로세스가 동시에 병렬로 처리될 수 있습니다. 4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?운영체제는 프로세스 제어 블록(PCB: Process Control Block)을 사용하여 여러 개의 프로세스를 관리합니다. 각 프로세스가 실행 중일 때, 운영체제는 해당 프로세스의 상태와 정보를 PCB에 저장하여 추적하고 관리합니다.프로세스가 생성되면 운영체제는 그 프로세스에 대한 고유한 PCB를 생성합니다. 이 PCB에는 다음과 같은 주요 정보들이 포함됩니다:프로세스 ID (PID): 프로세스의 고유 식별자프로세스 상태: 실행, 대기, 준비 등 현재 상태CPU 레지스터 정보: 프로세스가 CPU에서 작업을 하던 도중의 상태(레지스터 값)메모리 관리 정보: 프로세스의 코드, 데이터, 스택 등이 저장된 메모리 영역 정보입출력 상태 정보: 입출력 요청이나 장치 사용 상황우선순위: 프로세스의 우선순위에 따른 스케줄링 정보운영체제는 이 PCB들을 연결 리스트(또는 다른 자료구조)로 관리하여, 여러 프로세스를 효율적으로 스케줄링하고 제어합니다. PCB는 각 프로세스의 상태를 기억하기 때문에 프로세스가 CPU를 사용하다가 중단될 때, 해당 프로세스의 정보를 PCB에 저장하고, 나중에 다시 해당 프로세스가 CPU를 사용할 때 이전 상태에서부터 이어서 작업할 수 있습니다.프로세스가 종료되면 운영체제는 해당 프로세스의 PCB를 연결 리스트에서 제거하고 메모리에서 해제하여 자원을 회수합니다. 5. 컨텍스트 스위칭이란 뭔가요?CPU가 한 프로세스에서 다른 프로세스로 전환할 때 수행되는 작업입니다. CPU는 여러 프로세스를 동시에 처리할 수 없기 때문에, 하나의 프로세스를 실행하다가 다른 프로세스를 실행하려면 현재 프로세스의 상태를 저장하고 새로운 프로세스의 상태를 복구해야 합니다. 이러한 상태 정보는 프로세스 제어 블록(PCB)에 저장됩니다.컨텍스트 스위칭 과정은 다음과 같습니다:현재 실행 중인 프로세스의 상태 저장: CPU는 현재 실행 중인 프로세스의 상태(프로그램 카운터, 레지스터 값, 메모리 관리 정보 등)를 PCB에 저장합니다. 이렇게 하면 나중에 이 프로세스를 다시 실행할 때, 중단된 지점부터 작업을 이어서 할 수 있습니다.새로운 프로세스의 상태 로드: 다음으로 실행할 프로세스의 PCB에서 저장된 상태 정보를 CPU에 로드합니다. 이때 새로운 프로세스가 실행되기 위한 프로그램 카운터, 레지스터 값, 메모리 정보 등을 CPU가 가져옵니다.CPU 전환: CPU는 이제 새로운 프로세스의 명령어를 실행하며 작업을 이어나갑니다.컨텍스트 스위칭은 필수적인 작업이지만, 오버헤드가 발생합니다. 이 과정은 비교적 짧은 시간이 걸리지만, 불필요하게 자주 발생하면 CPU가 실제 작업보다는 프로세스 전환에 더 많은 시간을 소모할 수 있습니다.따라서 컨텍스트 스위칭은 효율적인 CPU 자원 관리와 동시성 유지를 위한 필수적인 메커니즘이지만, 너무 빈번하게 발생하지 않도록 스케줄러가 잘 조정해야 합니다.  자료구조와 알고리즘1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요.해시 테이블(Hash Table)을 사용하겠습니다. 해시 테이블은 해시 함수를 사용해 데이터를 효율적으로 저장하고 검색할 수 있는 자료구조입니다. 해시 함수를 통해 학생 정보(예: 학생 ID)를 키로 변환하고, 해당 키에 맞는 위치에 데이터를 저장합니다.이 자료구조의 장점은 데이터의 삽입, 수정, 삭제, 검색이 평균적으로 O(1)의 시간 복잡도를 가지기 때문에 매우 빠릅니다. 따라서 학생 정보가 많더라도, 특정 학생의 정보를 빠르게 조회하거나 수정할 수 있습니다. 또한, 해시 테이블은 중복을 허용하지 않으므로 학생 ID와 같은 고유 식별자를 기반으로 데이터 관리가 용이합니다.그러나 해시 테이블의 단점으로는 충돌 관리가 필요하다는 점이 있습니다. 해시 함수가 서로 다른 데이터를 동일한 해시 값으로 변환할 경우, 이를 해결하기 위한 방법(체이닝 또는 오픈 어드레싱 등)을 구현해야 합니다. 하지만 전체적으로 성능과 효율성 측면에서 학생 관리 프로그램에 적합합니다. 2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.큐(Queue)를 선택하겠습니다. 큐는 FIFO(First In, First Out) 구조로, 먼저 들어온 데이터가 먼저 처리되는 자료구조입니다. 주문 처리는 보통 고객이 주문한 순서대로 처리되어야 하기 때문에 큐는 자연스럽게 이러한 요구 사항을 충족시킵니다.큐에서 데이터 삽입(Enqueue)은 뒤쪽에서 이루어지고, 데이터 삭제(Dequeue)는 앞쪽에서 이루어지기 때문에 주문이 들어온 순서대로 처리가 보장됩니다. 즉, 프로그램이 새로운 주문을 받을 때는 큐의 뒤에 추가하고, 주문을 처리할 때는 큐의 앞에서 데이터를 꺼내 처리합니다.큐는 또한 O(1)의 시간 복잡도로 삽입과 삭제 작업이 이루어지기 때문에, 대량의 주문이 처리될 때에도 효율적으로 관리할 수 있습니다. 이 구조 덕분에 고객 주문의 공평한 처리와 성능 측면에서 매우 유리합니다.

미션CS

Jay 1개월 전
유선아

[미션] 인프런 워밍업클럽 CS 2기 1주차 미션

운영체제 1. while(true){ wait(1); // 1초 멈춤 bool isActivated = checkSkillActivated(); // 체크 } 위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요? 인터럽트 방식을 이용해야합니다.CPU가 입출력 관리자에게 입출력 명령을 내리고 CPU는 다른 작업을 계속 하고, 입출력관리자가 입출력이 완료됐을 때, CPU 에게 신호를 주면, CPU는 그 신호를 받아 인터럽트 서비스 루틴 ISR을 실행시켜 작업을 완료합니다. 즉, CPU가 주기적으로 진행상황을 계속 확인할 필요가 없기 때문에 성능의 이점이 생깁니다. 프로그램과 프로세스가 어떻게 다른가요?프로그램은 하드디스크 등과 같은 저장장치에 저장된 명령문의 집합체입니다.프로세스는 프로그램이 메모리에 올라갔을 때, 실행중인 프로그램을 프로세스라고 합니다.멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?멀티프로그래밍은 메모리에 여러개의 프로세스가 올라온 것이고 메모리에 관점에서 정의된 것 이고,멀티프로세싱은 CPU가 여러개의 프로세스를 처리하는 것으로 CPU관점에서 정의한 것 입니다. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?운영체제는 프로세스의 정보를 가지고 있는 PCB를 사용해 프로세스를 관리한다. 운영체제는 프로세스가 만들어지면 해당 프로세스의 정보를 가지고 있는 PCB 을 만들고 저장 하고,(PCB에는 포인터, 프로세스 상태, 프로세스 ID, 프로그램 카운터, 레지스터 정보, 메모리 관련 정보, CPU스케줄링 정보등이 저장된다.)PCB들은 연결리스트라는 자료구조로 저장되고, 운영체제는 프로세스가 종료되면 연결리스트에서 해당 프로세스의 PCB를 제거한다. 컨텍스트 스위칭이란 뭔가요?컨텍스트 스위칭이란 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해, 실행 중인 프로세스의 상태를 저장하고, 다른 프로세스의 상태값으로 교체하는 작업입니다. 현재 작업 중이던 프로세스의 작업 내용을 PCB에 저장하고, 실행 할 프로세스의 PCB를 가져와 그 정보를 참조하여 CPU가 다시 세팅되어 이어서 실행됩니다.  자료구조와 알고리즘 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요. 배열을 선택할 것입니다.보통 학생의 정보는 학기 초에 일괄적으로 저장한 다음, 그 이후에 정보를 확인하고 찾는 작업이 주를 이루고 학생의 정보가 추가되거나 수정되는 일은 자주 일어나지 않기 때문입니다. 학생 번호는 인덱스로 두어 인덱스로 학생의 정보를 쉽게 찾을 수 있을 것 같다고 생각하기 때문에 읽기 기능이 O(1)의 성능을 가진 배열을 이용하는 것이 좋을 것 같습니다. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요. Queue 자료구조를 선택할 것입니다.Queue는 FIFO(first in first out)으로 먼저 들어간 데이터가 먼저 쓰이는 데이터 구조이기 때문에 주문 들어온 순서대로 처리하기 위해 적합하다고 판단 되기 때문입니다.

알고리즘 · 자료구조워밍업클럽운영체제자료구조알고리즘CS미션

seongmin kim

인프런 워밍업 클럽 CS 2기 - 1주차 미션

운영체제1.위 코드는 1초 마다 플레이어가 스킬을 사용했는지 체크하는 코드입니다. 이 방식은 폴링방식입니다. 1초마다 체크하기 때문에 성능에 좋지 않습니다. 이를 해결하기 위한 방식으로 어떤 걸 이용해야 할까요?-> 폴링방식의 단점을 해결한 인터럽트 방식을 사용한다. 인터럽트는 입출력 관리자에게 입출력 명령을 내리는 것까지는 폴링 방식과 같지만, 명령을 내린 후에 CPU가 다른 작업을 계속한다. 이에 따라, 인터럽트는 비동기적으로 동작하므로 성능에 이점이 있다. 2. 프로그램과 프로세스가 어떻게 다른가요?-> 프로그램은 하드디스크와 같은 저장 장치에 저장된 명령문의 집합체이며, 프로세스는 실행 중인 프로그램이다.-> 프로세스는 메모리도 사용하고, 운영체제의 CPU스케줄링 알고리즘에 따라서 CPU도 사용하며, 필요에 따라 입력과 출력을 하기 때문에 능동적이지만, 프로그램은 하드디스크(저장 장치)만 사용하므로 수동적이다. 3. 멀티프로그래밍과 멀티프로세싱이 어떻게 다른가요?-> 멀티프로그래밍: 메모리에 여러 개의 프로세스가 올라온 것-> 멀티프로세싱: CPU가 여러 개의 프로세스를 처리하는 것 4. 운영체제는 프로세스를 관리하기 위해서 어떤 것을 사용하나요?-> PCB(Process Control Block) 5. 컨텍스트 스위칭이란 뭔가요?-> 프로세스를 실행하는 중에 다른 프로세스를 실행하기 위해 실행 중인 프로세스의 상태를 저장하고 다른 프로세스의 상태 값으로 교체하는 작업자료구조와 알고리즘1. 여러분은 교실의 학생 정보를 저장하고 열람할 수 있는 관리 프로그램을 개발하려고 합니다. 이 때 여러분이라면 학생의 정보를 저장하기 위한 자료구조를 어떤 걸 선택하실 건가요? 이유를 함께 적어주세요.-> 학생 수가 적으면 배열을 사용한다. 다만, 학생의 수가 많거나 변동될 경우가 있다면 배열보다는 해시테이블을 사용한다. 해시테이블은 키(key)와 밸류(value)로 구성되어 있고, 키(key)만 알면 밸류(value)에 O(1) 성능으로 읽을 수 있다. 2. 여러분은 고객의 주문을 받는 프로그램을 개발하려고 합니다. 주문은 들어온 순서대로 처리됩니다. 이 때 여러분이라면 어떤 자료구조를 선택하실 건가요? 이유를 함께 적어주세요.-> 주문이 들어온 순서대로 처리하려면 큐를 선택한다. 큐는 선입선출(FIFO: First In First Out) 구조이므로, 들어온 순서대로 처리되어 적합하다.

알고리즘 · 자료구조워밍업클럽미션

이양구

[인프런 워밍업 클럽 FE 0기] 미션7 - 예산 계산기 앱

💸 Budget Calculator APP GitHub 💸 Budget Calculator APP DemoRecord by ScreenToGif  개요인프런 워밍업 클럽 FE 0기의 일곱 번째 미션인 '예산 계산기 앱' 입니다. 따라하며 배우는 리액트 섹션 0~3(To-Do 앱) 목표의존성 배열(Dependency Array) 을 이용해 함수 실행하기state 를 전역 변수처럼(?) 사용해보기 구현구조|-- App | |-- Form | |-- Lists | | |-- List  의존성 배열(Dependency Array) 을 이용해 함수 실행하기// App.jsx const [budgetList, setBudgetList] = useState( JSON.parse(localStorage.getItem("budgetList")) || [] ); useEffect(() => { localStorage.setItem("budgetList", JSON.stringify(budgetList)); }, [budgetList]); const totalCost = useCallback(() => { return budgetList.reduce((acc, cur) => acc + cur.cost, 0); }, [budgetList]); 최상위 컴포넌트인 <App> 컴포넌트에서 만든 'budgetList'이라는 state를 useEffect와 useCallback의 의존성 배열에 추가했다.useEffect에서는 해당 state가 변경되면 로컬 스토리지의 budgetList를 최근의 리스트로 변경한다.이렇게 하면 일일이 setBudgetList가 호출되는 곳마다 함수를 사용하지 않아도 된다.다음은 예산의 총 금액을 반환하는 함수가 리스트가 변경될 때마다 실행되도록 useCallback으로 감싸고 의존성 배열에 state를 추가했다.// Form.jsx const budgetNameRef = useRef(); const [budgetName, setBudgetName] = useState(""); const [budgetCost, setBudgetCost] = useState(0); useEffect(() => { if (isEdit) { setBudgetName(budget.name); setBudgetCost(budget.cost); budgetNameRef.current.focus(); } }, [isEdit]); <Form> 컴포넌트에서는 useEffect에 'isEdit'이라는 state를 의존성 배열에 추가했다.사용자가 예산을 수정하기 위해 list의 Edit 버튼을 클릭하면 해당 budget의 name과 cost를 최근 state로 불러오고, useRef를 이용해 name을 입력하는 <input> 요소에 focus 상태가 되도록 했다.state 를 전역 변수처럼(?) 사용해보기// App.jsx const [currentBudget, setCurrentBudget] = useState({ isEdit: false, budget: {}, }); // List.jsx const handleEdit = () => { setCurrentBudget({ isEdit: true, budget: list, }); setHandleStatus({ type: "edit", message: "Editing..." }); }; // Form.jsx const handleBudgetSubmit = (e) => { const newBudget = { id: Date.now(), name: budgetName, cost: budgetCost, }; // isEdit의 값에 따라 새로 추가할지 수정할지 결정 if (isEdit) { setBudgetList((prevBudgetList) => { const newBudgetLists = [...prevBudgetList]; const index = newBudgetLists.findIndex(({ id }) => id === budget.id); newBudgetLists[index] = newBudget; return newBudgetLists; }); setCurrentBudget({ isEdit: false, budget: {} }); setHandleStatus({ type: "submit", message: "Edit Success!" }); } else { setBudgetList((prevBudgetLists) => [...prevBudgetLists, newBudget]); setHandleStatus({ type: "submit", message: "Submit Success!" }); } // submit 종료 시 input의 데이터를 초깃값으로 설정 setBudgetName(""); setBudgetCost(0); }; 배웠던 To Do 앱은 List의 Edit 버튼을 클릭했을 때 해당 List의 요소를 input 요소로 변경시키고 수정을 했다.하지만 과제는 클릭을 했을 때 List의 요소를 변경시키는 게 아니라 Form의 input에 해당 예산의 데이터를 전달해야 했다.그래서 마치 전역 변수처럼 사용할 'currentBudget'이라는 state를 생성하고 'isEdit'이라는 boolean 값과 수정할 예산의 데이터를 담을 'budget'이라는 값을 설정했다.'isEdit'의 상태 값이 true일 때 수정하기와 삭제하기 <button> 요소를 disabled로 변경한다.또한 submit 함수는 새로운 입력 값을 budgetList에 추가하지 않고 해당 예산의 index를 찾아 수정하고 리스트를 변경한다.이렇게 하니 onSubmit과 onEdit 처럼 비슷한 기능을 하는 함수를 여러 개 만들지 않아도 되었다. ⚠ setTimeout 렌더링const { type, message } = handleStatus; const handleStyle = useCallback(() => { if (type === "edit") { return "text-gray-500 block"; } else if (type === "none") { return "hidden"; } else { // 2초 뒤에 실행 --> App - Form - Status 1번 더 렌더링 setTimeout(() => { setHandleStatus({ type: "none", message: "" }); }, 2000); if (type === "submit") { return "text-green-400 block"; } else { return "text-red-400 block"; } } }, [type]); 추가, 삭제, 수정의 완료 및 진행 중 상태를 보여주는 <Status> 컴포넌트를 만들었다.App에서 만든 'handleStatus'라는 state를 전달하고 메세지가 나타난 뒤에 사라지게 만들고 싶어서 setTimeout() 메서드를 이용해 2초 뒤에 상태를 초기화했다.하지만 이 상태가 App과 Form 컴포넌트에서 참고하다 보니 나타나고 사라질 때마다 렌더링이 발생했다.CSS의 opacity로 처리하기엔 state의 값을 변경해야 했기에 알맞는 방법은 아니라 생각했다.뭔가 <Status> 컴포넌트 내부에서만 렌더링이 일어나게 하고 싶었는데 아직 다른 방법을 찾지 못했다.😢😢😢 회고다른 컴포넌트의 클릭 이벤트로 변경된 state를 이용하는 부분이 생각보다 오래 걸렸다.처음엔 콜백 함수처럼 App 컴포넌트에서 함수 만들고 prop으로 넘겨봤지만 List와 Form은 종속적인 관계가 아니라 힘들었다. 😢그래서 생각해낸 게 state를 이용해서 상태의 변경을 이벤트처럼 사용하는 것이었다.pub-sub 혹은 observer 패턴 같다는 생각도 했지만, 이렇게 최상위에서 선언한 state가 이곳저곳 돌아다니는 게 좋은 방법은 아닐 것 같다는 생각이 들었다.규모가 커지면 렌더링 관리도 힘들고 props를 쫓아다녀야 하기 때문이다.이래서 상태 관리 라이브러리가 나왔나 보다. 🤔 

프론트엔드워밍업워밍업클럽프론트엔드프론트FE미션과제발자국

이양구

[인프런 워밍업 클럽 FE 0기] 미션4-2 - GitHubFinder 앱

🔍 github-finder-app GitHub 🔍 github-finder-app 개요인프런 워밍업 클럽 FE 0기의 네 번째 미션인 'GitHubFinder 앱' 입니다.따라하며 배우는 자바스크립트 섹션 5(OOP), 섹션 6(비동기) 목표Fetch API 를 이용해 깃허브 유저 목록 불러오기Closure 를 이용해 Debounce Function 만들기 구현Fetch API 를 이용해 깃허브 유저 목록 불러오기async function loadUser(input) { prevInputValue = input; try { // const response = await fetch('./src/javascript/user.json'); const response = await fetch(`${url}/${input}`); if (!response.ok) { throw new Error('Failed to fetch user json'); } const json = await response.json(); setUserAvatar(json); setUserInfo(json); await loadUserRepos(json); } catch (error) { console.error(error); } }fetch() 메서드의 응답은 HTTP 응답 전체를 나타내는 'response' 객체를 반환한다.response의 ok 속성은 응답의 성공 여부를 불리언 값으로 가지고 있다.따라서 응답이 성공이 아닐 경우 오류 객체(new Error())를 반환하고 catch 문으로 Promise의 오류를 처리한다.응답에 성공한 response 객체를 JSON으로 사용하기 위해선 json() 메서드를 이용해 파싱해야 한다. Closure 를 이용해 Debounce Function 만들기// debounce debounceInput.addEventListener('input', debounce(loadUser, 1000)); // debounceInput.addEventListener('input', e => callback(e)); function debounce(callback, delay = 0) { // timer는 부모 함수에서 선언된 지역 변수 let timer = null; return (arg) => { // 여기서 arg는 input event if (timer) { // 이미 타이머가 있는데 또 실행되면 타이머 삭제 clearTimeout(timer); } // 변수 timer는 부모 함수에서 선언되었지만 내부 함수에서 사용(클로저) timer = setTimeout(() => { callback(arg.target.value); }, delay); }; }<input> 요소의 'input' 이벤트는 요소의 value가 변경될 때마다 발생한다.만약 사용자가 입력할 때마다 서버에 데이터를 요청한다면 서버의 부하가 커지기 때문에 좋은 방법은 아니다.이럴 때 사용자의 입력이 끝난 뒤 마지막 value를 이용해 서버로 요청하는 게 효율적인 방법이라 할 수 있다.함수의 실행 요청이 반복될 때 마지막 요청만으로 실행하는 걸 '디바운싱(debouncing)'이라고 부른다.debounce 함수는 인자로 실행할 함수를 받고 자식 함수를 반환한다.부모 함수인 debounce 함수에서 선언한 변수(timer)를 자식 함수에서 사용할 수 있는 클로저(Closure)를 이용해 자식 함수의 setTimeout() 메서드의 반환 값인 'timeoutID'를 할당한다.변수 'timer'에 할당한 timeoutID를 이용해 setTimeout() 메서드의 지연 시간(delay)이 종료되기 전에 요청이 들어왔다면 이전에 생성한 타이머를 clearTimeout() 메서드를 이용해 종료하고 다시 타이머를 할당한다. 이렇게 delay로 설정한 시간 이내에 사용자의 입력이 없을 경우 API 요청 함수를 실행하게 된다. 반복적인 함수의 실행을 다루는 방법으로 디바운싱(debouncing)와 쓰로틀링(throttling)이 있다.여러 변수를 고려해 'lodash' 라이브러리의 debounce를 많이 사용한다. 회고이번 미션은 debounce가 반환하는 자식 함수의 인자(argument)가 어떤 타입인지 알기 때문에 callback 함수에 전달하는 인자를 수정해서 미숙한 debounce 함수라고 볼 수 있다.늘 라이브러리를 통해 사용하던 함수를 만들려고 하니 모르는 것도 많고, 고려해야 할 부분이 많다는 걸 알게 됐다.자바스크립트의 기초를 잘 알아야 이런 라이브러리 메서드의 원리를 이해하기도 쉽고, 커스텀하기에 수월한 것 같다.(외의로 GitHub의 API 요청이 API key 없이도 되어서 신기했고, 그 덕에 조금은 수월했다. 아주 조금... 😵) DemoRecord by ScreenToGif

프론트엔드워밍업워밍업클럽프론트엔드프론트FE미션과제발자국

이양구

[인프런 워밍업 클럽 FE 0기] 미션1 - 음식 메뉴 앱

🍝 food-recipe-app API from TheMealDBGitHub food-recipe-app 개요인프런 워밍업 클럽 FE 0기의 첫 번째 미션인 '음식 메뉴 앱' 만들기입니다.따라하며 배우는 자바스크립트의 섹션 1~3(자바스크립트 기초, Window 객체 및 DOM, Event)를 보고 자바스크립트의 DOM 요소를 조작하는 데 중점을 두었습니다.음식 데이터는 TheMealDB의 API를 이용했습니다. 사용한 API가 '음식 레시피'라서 이름을 변경했습니다. 목표문서 객체 모델(The Document Object Model, 이하 DOM)의 메소드(methods)를 이용해 요소(element)에 접근하고 생성하고 교체하기이벤트 리스너(Event Listener) 메소드를 이용해 요소에 이벤트를 등록하고 이벤트 객체 이용하기메뉴 데이터를 Fetch API를 사용해 불러오기 구현이벤트 위임(Event Delegation)을 이용한 이벤트 생성/* <nav id="food-navigation"> <div class="food-navigation-item"> <button id="Beef"> <figure> <img src="https://www.themealdb.com/images/category/beef.png"> <figcaption> Beef </figcaption> </figure> </button> </div> // ... </nav> */ // Not Event Delegation foodNavigation.querySelectorAll('button').forEach((button) => { button.addEventListener('click', async () => { const targetId = button.id; await setFoodList(targetId); }); }); // Event Delegation foodNavigation.addEventListener('click', async (event) => { const targetElement = event.target; // closest() 메서드는 주어진 CSS 선택자와 일치하는 요소를 찾을 때까지, // 자기 자신을 포함해 위쪽(부모 방향, 문서 루트까지)으로 문서 트리를 순회합니다. const targetDiv = targetElement.closest('.food-navigation-item'); if (!targetDiv) { return; } const targetButton = targetDiv.querySelector('button'); const targetId = targetButton.id; await setFoodList(targetId); });이벤트 위임이란 '상위 요소에서 하위 요소의 이벤트를 제어하는 것'을 의미합니다.이벤트를 위임하는 이유이벤트를 하나의 핸들러로 처리함으로써 메모리 사용량을 줄이고 성능을 향상시킬 수 있다.새로운 요소가 추가되거나 제거되는 경우 이벤트 리스너는 상위 요소에 연결되어 있어 재연결의 필요성이 줄어든다.저는 nav 태그에 이벤트를 등록하고 closest 메서드를 이용해 버튼의 id를 찾는 방법을 사용했습니다. 하위 요소를 제거하고 생성한 요소를 추가하기/* <div id="food-list"> <div class="food-list-item"> <figure> <img src="img src" /> </figure> <div class="food-list-item-desc"> <p>food name</p> <hr /> <div> food recipe </div> </div> </div> </div> */ const foodList = await getFoodList(strCategory); const foodListElement = document.getElementById('food-list'); const foodListItem = document.querySelectorAll('.food-list-item'); foodListItem.forEach((item) => item.remove()); // foodListElement.innerHTML = ''; foodList.map(async (food) => { // ... const foodElement = getFoodElement( idMeal, strMeal, strMealThumb, strInstructions ); foodListElement.appendChild(foodElement); });배웠던 removeChild()와 replaceChild() 메서드를 이용하고자 했으나...'만약 해당 카테고리의 음식 리스트의 개수가 다르다면 어떻게 하지?'라는 생각에 한번에 제거하기로 결정했습니다.처음엔 innerHTML을 이용해 하위 코드를 공백으로 만들었지만, 뭔가 이건 너무 이상하다는 생각(요소의 참조나 연결 같은 게 깨지진 않을까)이 들어 찾아보았습니다.stack overflow의 Remove child nodes (or elements) or set innerHTML=""?라는 글에서는 innerHTML은 하위 요소의 이벤트 핸들러가 완전히 제거되지 않을 수도 있다고 한다.또한 Why InnerHTML Is a Bad Idea and How to Avoid It?에서는 innerHTML이 보안상 좋지 않다는 점을 말하고 있다. Stack Overflow의 글을 자세히 읽어 보니 다음과 같은 글이 있었다.What is the best way to empty a node in JavaScript그리고 MDN 문서에도 이렇게 소개하고 있다.replaceChildren() provides a very convenient mechanism for emptying a node of all its children. You call it on the parent node without any argument specified:즉 replaceChildren()메서드를 빈 인자로 실행하면 하위 자식 노드를 모두 지워준다는 것...!😅 회고빈 폴더를 놓고 코드를 작성해본 게 너무 오랜만인 것 같다.자료를 찾기 귀찮다는 마음과 첫 미션이니까 API를 써볼까 하며 자만했던 순간도 있었다.미션의 목적보다 어느새 다른 부분을 신경 쓰느라 배보다 배꼽이 점점 커지는 것 같았다.딸랑 script 태그 한 줄 작성하고 js 파일을 제대로 못 불러와서 몇 시간을 해결 방법을 찾아서 해매기도 했다.😭이벤트 위임 코드를 작성할 때 이은재 님의 시나브로 자바스크립트에서 배웠던 부분을 참고했다.음식 레시피를 불러올 때 요소를 지우고 불러와서 그런지 해당 부분이 사라지고 나타나서 페이지가 늘었다 줄었다 하는 게 눈에 띈다.이래서 가상 돔을 쓰는걸까? 아니면 태그의 속성을 하나하나 수정하면 되는걸까?일단 진도를 따라잡고 배워서 발전시켜야겠다. DemoRecord by ScreenToGif

프론트엔드워밍업워밍업클럽FE프론트프론트엔드과제미션발자국

김민성

[워밍업 클럽 스터디 2기 - BE] (클린코드, 테스트코드) day 18 미션

출처 : 인프런 워밍업 클럽 스터디 2기 - 백엔드 클린코드, 테스트 코드(Java, Spring Boot)Practical Testing: 실용적인 테스트 가이드 1. @Mock, @MockBean, @Spy, @SpyBean, @InjectMocks 이 애노테이션들을 한번 정리하고 차이점을 알아보자. @Mockorg.mockito.Mock 이며 Mockito.mock() 을 애노테이션화 한 것으로 볼 수 있다.사용하려면 junit5기준으로 @ExtendWith(MockitoExtension.class)을 클래스 위에 달아주어야 한다.역할은 내가 어떤 테스트를 하고 싶은데, 그 테스트를 하려면 또 다른 의존성(클래스)를 끌고 와야 하는 상황에서 이 의존성을 가짜로 바꿔치기 (Stub)해 주는 것이다.그래서 내가 테스트 하고 싶은 코드만 테스트 할 수 있게 되는 것이다. @MockBeanorg.springframework.boot.test.mock.mockito.MockBean 패키지이며(!) spring-boot-test가 제공하는 애노테이션 이다.이걸 사용하면 스프링 컨텍스트가 관리하는 빈을 대체할 수 있다. → 즉 @SpringBootTest를 사용해야함.mock객체를 스프링 컨텍스트에 대신 등록하는 것이다. 그래서 Autowired에 의존성이 주입됨.역할은 @Mock과 유사하다. @InjectMocksorg.mockito.InjectMocks이며 @Mock이나 @Spy가 붙은 의존성 객체를 내가 테스트 할 객체에 주입할 때 사용하는 애노테이션이다. @Mock private MailSendClient mailSendClient; // 의존성(가짜 객체) @InjectMocks private MailService mailService; //실제 테스트할 객체코드에서 보면 mailSendClient라는 가짜 객체를 테스트를 위해 mailService에 주입하겠다는 것이다. @Spyorg.mockito.Spy이며 Mockito.spy()를 애노테이션화 한 것으로 볼 수 있다.의존성을 대체하는 @Mock과 같은 역할을 하지만 한 가지 큰 차이점이 있다.@Spy를 사용하면 일부 기능은 가짜로 Stub할 수 있고, 일부 기능은 실제로 동작 시킬 수 있다. @Slf4j @Component public class MailSendClient { // 메일 전송 public boolean sendEmail(String fromEmail, String toEmail, String subject, String content) { log.info("메일 전송"); throw new IllegalArgumentException("메일 전송"); } public void a() { log.info("a"); } public void b() { log.info("b"); } public void c() { log.info("c"); } }다음과 같은 가짜로 대체하고 싶은 클래스가 있다. 여기서 sendEmail()만 가짜로 Stub하고 나머지 a(), b(), c()는 실제 메서드를 실행하고 싶은 거다.public class MailService { private final MailSendClient mailSendClient; public boolean sendMail(String fromEmail, String toEmail, String subject, String content) { boolean result = mailSendClient.sendEmail(fromEmail, toEmail, subject, content); if (result) { // 추가 로직 } mailSendClient.a(); mailSendClient.b(); mailSendClient.c(); ... } }이런 식으로 MailService에서 sendMail()을 테스트를 할 때 mailSendClient의 sendMail()만 가짜로 쓴다는 의미이다. @Spy private MailSendClient mailSendClient; @InjectMocks private MailService mailService; @Test @DisplayName("메일 전송 테스트") void sendMail() { doReturn(true) .when(mailSendClient) .sendEmail(anyString(), anyString(), anyString(), anyString()); boolean result = mailService.sendMail("", "", "", ""); }이렇게 doReturn().when().스터빙할메서드()이라는 메서드 체이닝을 통해 스터빙할 수 있다. @Spy를 사용하면 일부 기능은 가짜로 Stub할 수 있고, 일부 기능은 실제로 동작 시킬 수 있다. @SpyBean이것도 @MockBean과 마찬가지로 org.springframework.boot.test.mock.mockito.SpyBean spring-boot-test가 제공하는 애노테이션 이다. 즉 @SpringBootTest를 사용해야함.가짜 객체의 일부만 stub하고, 나머지는 실제 메서드를 사용하고 싶을 때 사용.2. 다음과 같은 테스트가 있을 때 이걸 분류해보자.@BeforeEach void setUp() { ❓ } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { 1-1. 사용자 생성에 필요한 내용 준비 1-2. 사용자 생성 1-3. 게시물 생성에 필요한 내용 준비 1-4. 게시물 생성 1-5. 댓글 생성에 필요한 내용 준비 1-6. 댓글 생성 // given ❓ // when ❓ // then 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { 2-1. 사용자 생성에 필요한 내용 준비 2-2. 사용자 생성 2-3. 게시물 생성에 필요한 내용 준비 2-4. 게시물 생성 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 2-7. 댓글 수정 // given ❓ // when ❓ // then 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { 3-1. 사용자1 생성에 필요한 내용 준비 3-2. 사용자1 생성 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 3-6. 사용자1의 게시물 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 3-9. 사용자2가 사용자1의 댓글 수정 시도 // given ❓ // when ❓ // then 검증 }여기서 @DisplayName으로 뭘 테스트할지 알 수 있다.이번 테스트는 댓글에 대한 테스트를 하려는 것으로 느낄 수 있다.그럼 given절에는 댓글을 달기 위한 사전 준비를 해야 하는데, 반복적으로 준비해야 하는 것은 setUp()으로 빼보자.1-1. 사용자 생성에 필요한 내용 준비 1-2. 사용자 생성 1-3. 게시물 생성에 필요한 내용 준비 1-4. 게시물 생성 2-1. 사용자 생성에 필요한 내용 준비 2-2. 사용자 생성 2-3. 게시물 생성에 필요한 내용 준비 2-4. 게시물 생성 3-1. 사용자1 생성에 필요한 내용 준비 3-2. 사용자1 생성 3-5. 사용자1의 게시물 생성에 필요한 내용 준비 3-6. 사용자1의 게시물 생성이 내용은 계속 반복된다.@BeforeEach void setUp() { 사용자 생성에 필요한 내용 준비 사용자 생성 게시물 생성에 필요한 내용 준비 게시물 생성 } 이렇게 준비해보자. 첫 번째 테스트는 댓글을 작성할 수 있다가 핵심이기 때문에 다음과 같이 나타냈다.@DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-5. 댓글 생성에 필요한 내용 준비 // when 1-6. 댓글 생성 // then 검증 }  두 번째 테스트는 댓글을 수정이 핵심이기 때문에 댓글 생성까지는 준비하고, 핵심인 댓글 수정을 when에서 실행했다.@DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 }  마지막 테스트는 타인이 댓글을 수정 시도한다.이기 때문에given절에선 타인 사용자 2를 만들어주고, 내가 댓글을 생성해 놓는다.그리고 when절에서 타인이 내 댓글을 수정 시도한다.@DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 } 전체 코드는 다음과 같다.@BeforeEach void setUp() { 사용자 생성에 필요한 내용 준비 사용자 생성 게시물 생성에 필요한 내용 준비 게시물 생성 } @DisplayName("사용자가 댓글을 작성할 수 있다.") @Test void writeComment() { // given 1-5. 댓글 생성에 필요한 내용 준비 // when 1-6. 댓글 생성 // then 검증 } @DisplayName("사용자가 댓글을 수정할 수 있다.") @Test void updateComment() { // given 2-5. 댓글 생성에 필요한 내용 준비 2-6. 댓글 생성 // when 2-7. 댓글 수정 // then 검증 } @DisplayName("자신이 작성한 댓글이 아니면 수정할 수 없다.") @Test void cannotUpdateCommentWhenUserIsNotWriter() { // given 3-3. 사용자2 생성에 필요한 내용 준비 3-4. 사용자2 생성 3-7. 사용자1의 댓글 생성에 필요한 내용 준비 3-8. 사용자1의 댓글 생성 // when 3-9. 사용자2가 사용자1의 댓글 수정 시도 // then 검증 }  

백엔드테스트코드워밍업클럽미션

채널톡 아이콘