728x90
반응형

TCP는 Transmission Contorl Protocol으로, 전송 제어 프로토콜입니다.

TCP는 신뢰성 있는 데이터 전송을 위해 사용되는 연결지향 프로토콜입니다.

 

UDP는 User Datagram Protocol으로 사용자 데이터그램 프로토콜입니다.

UDP는 빠른 데이터 전송을 중요시하는 비연결 프로토콜입니다.

두 단어 모두에게 존재하는 프로토콜(Protocol)이 디지털 장치간의 서로 통신하고 상호작용하기 위한 규칙의 집합입니다.

 

TCP와 UDP의 차이점은 다음과 같습니다.

  • 신뢰성
    • TCP는 데이터 손실이나 순서의 뒤섞임이 발생하지 않습니다.
    • UDP는 정확성을 확인하거나 재전송을 요청할 수 없기에 데이터가 손실 되거나 순서가 뒤섞일 수 있습니다
  • 연결
    • TCP는 데이터를 전송하기 전에 연결을 설정하고, 전송후 연결을 해제합니다. 연결 및 해제과정에서 추가적인 오버헤드는 초래할 수 있으나, 신뢰성 있는 통신을 보장합니다.
    (오버헤드: 데이터전송 및 처리 과정에서 추가 부담이나 리소스 낭비를 뜻함)
    • UDP는 연결 및 해제 단계가 없기에 빠른 전송이 가능하지만 데이터의 무결성을 보장하지 않습니다.
  • 사용사례
    • TCP는 주로 이메일, 파일 전송과 같이 신뢰성이 중요한 경우 사용됩니다.
    • UDP는 실시간 스트리밍, 온라인 게임, 음성통화 같이 데이터 전송 속도가 중요한 경우 사용됩니다.

TCP 패킷의 재전송 과정

  1. 패킷 송신 : 송신자는 여러개의 패킷으로 나눠 수신자에게 보냄. 각 패킷은 고유한 일련번호를 가지고 있습니다.
  2. 패킷 수신 : 수신자는 패킷을 받고, 패킷의 일련번호를 확인하여 순서대로 재조립합니다.
  3. 패킷 손실 확인 : 만약 패킷이 손실되었다고 감지하면, 송신자에게 패킷 손실을 알리기 위한 메시지를 보냅니다.
  4. 재전송 요청 : 송신자는 손실된 패킷을 재전송하고, 이 패킷의 일련번호를 통해 수신자는 어떤 패킷이 재전송된 것인지 판단할 수 있습니다.
  5. 패킷 재전송 : 재전송된 패킷은 수신자에게 도착하고 재조립합니다.

TCP 세션 관리 (연결의 설정과 종료 과정) - Easy Version

  1. 연결 설정 (Handshake)
    • 두 컴퓨터 간의 통신을 먼저 연결 설정해야 합니다. 이 단계를 연결 설정 또는 핸드쉐이크라고 부릅니다.
  2. 데이터 전송
    • 연결 설정후, 데이터를 주고 받을 수 있습니다. A는 작은 조각으로 나눠 B에게 보내면 재조립하여 사용합니다.
  3. 연결 해제 (Termination)
    • 데이터 통신이 끝난 후, 연결을 해제합니다.
    • A는 B에게 끝내고자 하는 의사를 전달합니다. B는 요청을 수락하고 연결이 종료됩니다.

TCP 3-way Handshake (연결 설정)TCP 4-way Handshake (연결 해제) - Hard Version

더보기

TCP 3-way Handshake (연결 설정):

  1. Step 1 - 클라이언트가 서버에게 SYN 보내기 (SYN, Seq=X): 연결 설정 단계에서 클라이언트가 서버에게 연결을 요청하는 SYN 패킷을 보냅니다. 이 패킷은 클라이언트의 초기 순서 번호(X)를 포함하고, 연결을 시작함을 나타냅니다.
  2. Step 2 - 서버가 클라이언트에게 응답하기 (SYN, ACK, Seq=Y, Ack=X+1): 서버는 클라이언트의 요청을 받고, 클라이언트의 순서 번호를 확인한 후 자신의 순서 번호(Y)와 함께 SYN/ACK 패킷을 보냅니다. 이것은 연결 수락을 의미하며, 서버는 다음에 올 것으로 예상되는 데이터 패킷의 순서 번호(X+1)를 보냅니다.
  3. Step 3 - 클라이언트가 서버에게 응답하기 (ACK, Seq=X+1, Ack=Y+1): 클라이언트는 서버의 응답을 받고, 서버의 순서 번호(Y)를 확인한 후 ACK 패킷을 보냅니다. 이것은 서버가 연결을 수락했음을 확인하고, 클라이언트가 서버의 예상 순서 번호(Y+1)로부터 데이터를 보낼 것임을 나타냅니다.

필요성:

  • 3-way handshake는 양쪽 간에 상호 동의된 초기 순서 번호를 설정하고, 연결을 설정하며, 통신을 시작하는 데 필요합니다. 이 단계가 없으면 데이터 통신이 시작되지 않습니다.

TCP 4-way Handshake (연결 해제):

  1. Step 1 - 클라이언트가 서버에게 연결 종료 요청 (FIN, Seq=X): 데이터 통신이 끝나면 클라이언트는 서버에게 연결 종료를 요청하는 FIN 패킷을 보냅니다. 이것은 클라이언트가 더 이상 데이터를 보내지 않을 것임을 나타냅니다.
  2. Step 2 - 서버가 클라이언트에게 응답하기 (ACK, Seq=Y, Ack=X+1): 서버는 클라이언트의 FIN 요청을 받고 확인하기 위해 ACK 패킷을 보냅니다. 그러나 서버는 아직 데이터를 보내기 위해 준비 중입니다.
  3. Step 3 - 서버가 클라이언트에게 연결 종료 요청 (FIN, Seq=Z, Ack=X+1): 서버가 데이터 전송을 마치면, 서버는 연결 종료를 요청하는 FIN 패킷을 클라이언트에게 보냅니다. 이것은 서버가 클라이언트에게 더 이상 데이터를 보내지 않을 것임을 나타냅니다.
  4. Step 4 - 클라이언트가 서버에게 응답하기 (ACK, Seq=X+1, Ack=Z+1): 클라이언트는 서버의 FIN 요청을 받고, 클라이언트도 더 이상 데이터를 보내지 않을 것임을 나타내는 ACK 패킷을 보냅니다. 이로써 연결이 종료됩니다.

필요성:

  • 4-way handshake는 양쪽 간의 데이터 통신이 완료되고 연결이 종료됨을 보장합니다. 이 단계가 없으면 연결이 계속 유지될 수 있으며, 다른 데이터 전송이 불가능합니다.

 

"SYN"은 "Synchronize"의 약자로 동기입니다.

"ACK"는 "Acknowledgment"의 약자로 승인입니다.

"FIN"은 "Finish"의 약자로 종료입니다. 그 과정을 리눅스를 통해 3way, 4way인 것이 보입니다.

중간의 P의 경우, 패킷의 약자로 데이터 패킷을 전송하는 과정입니다.

 

TCP와 UDP를 그림으로 표현했을때 다음과 같습니다.

 

TCP (Transmission Control Protocol)

연결 지향 방식, 패킷 교환방식

3way handshaking 으로 연결 4way handshaking으로 해제

흐름제어 - 송.수신측의 데이터 처리속도 차이 줄이기 위함, receiver가 현재 상태를 sender에게 피드백해 패킷 수를 조절

혼잡 제어 - 송신측의 데이터 전달과 네트워크 데이터 처리 속도 차이를 해결 하기 위함

위 두가지 기능 가능

높은 신뢰성- 낮은 성능

전이중(각각의 독립된 회선 사용), 점대점(1대1통신) 방식

각각의 패킷들은 연결되어있으며 번호가 매겨짐

신뢰성있는 전송이 필요할때 사용

가변길이 헤더

 

 

UDP (User Datagram Protocol)

비연결형 방식, 데이터그램 방식

정보를 주고받을떄 신호절차를 가지고 있지 않음

UDP헤더의 CheckSum 필드로 최소한의 오류 검출

낮은 신뢰성 -높은 성

각각의 패킷들은 독립되어있다

빠른 전송이 필요할때 사용

고정 길이 헤더

 

일반적으로는 저런 내용이지만 UDP는 커스터마이징이 가능하며 개발자의 역량에 따라서 UDP를 이용해

TCP와 비슷한 신뢰성 가지게 할 수 있음

ex) QUIC

 

728x90
반응형
728x90
반응형

좋은 코드란 무엇인가?

‘좋은 코드’의 기준이 조금씩 다르고 각각의 경험을 기반으로 좋은 코드를 정의하고 있다. 세간에 좋은 코드의 정의는 정말 많다.

  • 읽기 쉬운 코드
  • 중복이 없는 코드
  • 테스트가 용이한 코드

결론은? 좋은 코드를 왜 작성해야 하는지부터 고민했던 과정을 글로 정리해보았다.

  • 코드 간의 의존성을 고민하자.
  • 합의된 규칙으로 일관성있게 작성하자.
  • 적절하게 확장 가능하도록 설계하자.
  • 어쩔 수 없는 코드는 주석과 함께 격리하자.
  • 답은 테스트 코드 기반의 자동화 테스트다.

 


 

객체지향 프로그래밍 (OOP)

객체 지향적 설계 원칙

  1. SRP(Single Responsibility Principle) : 단일 책임 원칙클래스는 단 하나의 책임을 가져야 하며 클래스를 변경하는 이유는 단 하나의 이유이어야 한다.
  2. OCP(Open-Closed Principle) : 개방-폐쇄 원칙확장에는 열려 있어야 하고 변경에는 닫혀 있어야 한다.
  3. LSP(Liskov Substitution Principle) : 리스코프 치환 원칙상위 타입의 객체를 하위 타입의 객체로 치환해도 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다.
  4. ISP(Interface Segregation Principle) : 인터페이스 분리 원칙인터페이스는 그 인터페이스를 사용하는 클라이언트를 기준으로 분리해야 한다.
  5. DIP(Dependency Inversion Principle) : 의존 역전 원칙고수준 모듈은 저수준 모듈의 구현에 의존해서는 안된다.

 


 

RESTful API

 

우선, 위키백과의 정의를 요약해보자면 다음과 같다.

월드 와이드 웹(World Wide Web a.k.a WWW)과 같은 분산 하이퍼미디어 시스템을 위한 소프트웨어 아키텍처의 한 형식으로 자원을 정의하고 자원에 대한 주소를 지정하는 방법 전반에 대한 패턴

REST란, REpresentational State Transfer 의 약자이다. 여기에 ~ful 이라는 형용사형 어미를 붙여 ~한 API 라는 표현으로 사용된다. 즉, REST 의 기본 원칙을 성실히 지킨 서비스 디자인은 'RESTful'하다라고 표현할 수 있다.

REST가 디자인 패턴이다, 아키텍처다 많은 이야기가 존재하는데, 하나의 아키텍처로 볼 수 있다. 좀 더 정확한 표현으로 말하자면, REST 는 Resource Oriented Architecture 이다. API 설계의 중심에 자원(Resource)이 있고 HTTP Method 를 통해 자원을 처리하도록 설계하는 것이다.

RESTful 하게 API 를 디자인 한다는 것은 무엇을 의미하는가.(요약)

  1. 리소스 와 행위 를 명시적이고 직관적으로 분리한다.
  • 리소스는 URI로 표현되는데 리소스가 가리키는 것은 명사로 표현되어야 한다.
  • 행위는 HTTP Method로 표현하고, GET(조회), POST(생성), PUT(기존 entity 전체 수정), PATCH(기존 entity 일부 수정), DELETE(삭제)을 분명한 목적으로 사용한다.
  1. Message 는 Header 와 Body 를 명확하게 분리해서 사용한다.
  • Entity 에 대한 내용은 body 에 담는다.
  • 애플리케이션 서버가 행동할 판단의 근거가 되는 컨트롤 정보인 API 버전 정보, 응답받고자 하는 MIME 타입 등은 header 에 담는다.
  • header 와 body 는 http header 와 http body 로 나눌 수도 있고, http body 에 들어가는 json 구조로 분리할 수도 있다.
  1. API 버전을 관리한다.
  • 환경은 항상 변하기 때문에 API 의 signature 가 변경될 수도 있음에 유의하자.
  • 특정 API 를 변경할 때는 반드시 하위호환성을 보장해야 한다.
  1. 서버와 클라이언트가 같은 방식을 사용해서 요청하도록 한다.
  • 브라우저는 form-data 형식의 submit 으로 보내고 서버에서는 json 형태로 보내는 식의 분리보다는 json 으로 보내든, 둘 다 form-data 형식으로 보내든 하나로 통일한다.
  • 다른 말로 표현하자면 URI 가 플랫폼 중립적이어야 한다.

어떠한 장점이 존재하는가?

  1. Open API 를 제공하기 쉽다
  2. 멀티플랫폼 지원 및 연동이 용이하다.
  3. 원하는 타입으로 데이터를 주고 받을 수 있다.
  4. 기존 웹 인프라(HTTP)를 그대로 사용할 수 있다.

단점은 뭐가 있을까?

  1. 사용할 수 있는 메소드가 한정적이다.
  2. 분산환경에는 부적합하다.
  3. HTTP 통신 모델에 대해서만 지원한다.

 


 

TDD

Test-Driven Development(TDD)는 매우 짧은 개발 사이클의 반복에 의존하는 소프트웨어 개발 프로세스이다. 우선 개발자는 요구되는 새로운 기능에 대한 자동화된 테스트케이스를 작성하고 해당 테스트를 통과하는 가장 간단한 코드를 작성한다. 일단 테스트 통과하는 코드를 작성하고 상황에 맞게 리팩토링하는 과정을 거치는 것이다. 말 그대로 테스트가 코드 작성을 주도하는 개발방식인 것이다.

 

 

 


 

함수형 프로그래밍

 

함수형 프로그래밍의 가장 큰 특징 두 가지는 immutable data와 first class citizen으로서의 function이다.

immutable vs mutable

우선 immutable과 mutable의 차이에 대해서 이해를 하고 있어야 한다. immutable이란 말 그대로 변경 불가능함을 의미한다. immutable 객체는 객체가 가지고 있는 값을 변경할 수 없는 객체를 의미하여 값이 변경될 경우, 새로운 객체를 생성하고 변경된 값을 주입하여 반환해야 한다. 이와는 달리, mutable 객체는 해당 객체의 값이 변경될 경우 값을 변경한다.

first-class citizen

함수형 프로그래밍 패러다임을 따르고 있는 언어에서의 함수(function)는 일급 객체(first class citizen)로 간주된다. 일급 객체라 함은 다음과 같다.

  • 변수나 데이터 구조안에 함수를 담을 수 있어서 함수의 파라미터로 전달할 수 있고, 함수의 반환값으로 사용할 수 있다.
  • 할당에 사용된 이름과 관계없이 고유한 구별이 가능하다.
  • 함수를 리터럴로 바로 정의할 수 있다.

Reactive Programming

반응형 프로그래밍(Reactive Programming)은 선언형 프로그래밍(declarative programming)이라고도 불리며, 명령형 프로그래밍(imperative programming)의 반대말이다. 또 함수형 프로그래밍 패러다임을 활용하는 것을 말한다. 반응형 프로그래밍은 기본적으로 모든 것을 스트림(stream)으로 본다. 스트림이란 값들의 집합으로 볼 수 있으며 제공되는 함수형 메소드를 통해 데이터를 immutable 하게 관리할 수 있다.

 

 



MVC패턴

다음 링크로 대체

http://asfirstalways.tistory.com/180

 

1. MVC 아키텍쳐에 대한 이해

Things 1. MVC 아키텍쳐에 대한 이해떠도는 여러 이미지들과 책에 나온 구성도를 내 나름대로 재구성해보았다. MVC에 대한 기본 개념은 모두 동일하기 때문에 Servlet과 JSP를 기준으로 설명하여 보다

asfirstalways.tistory.com

 

 


 

깃과 깃허브

 

Git 이란 VCS(Version Control System)에 대해서 기본적인 이해를 요구하고 있다.

Git 을 사용하기 위한 각종 전략(strategy)들이 존재한다. 해당 전략들에 대한 이해를 기반으로 Git 을 사용해야 하기 때문에 면접에서 자주 물어본다. 주로 사용되는 strategy 중심으로 질문이 들어오며 유명한 세 가지를 비교한 글을 첨부한다.

많은 회사들이 GitHub 을 기반으로 협업을 하게 되는데, (BitBucket 이라는 훌륭한 도구도 존재합니다.) GitHub 에서 어떤 일을 할 수 있는지, 어떻게 GitHub Repository 에 기여를 하는지 정리한 글을 첨부한다.

 

 


 

출처: https://github.com/JaeYeopHan/Interview_Question_for_Beginner#%EB%A9%B4%EC%A0%91%EC%97%90%EC%84%9C-%EB%B0%9B%EC%95%98%EB%8D%98-%EC%A7%88%EB%AC%B8%EB%93%A4

 

GitHub - JaeYeopHan/Interview_Question_for_Beginner: :boy: Technical-Interview guidelines written for those who started studying

:boy: :girl: Technical-Interview guidelines written for those who started studying programming. I wish you all the best. :space_invader: - GitHub - JaeYeopHan/Interview_Question_for_Beginner: :boy:...

github.com

 

 

 

728x90
반응형
728x90
반응형

참고링크 : https://blog.hexabrain.net/98

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hello, world!");
        }
    }
}

using = using은 말 그대로 '사용하다'라는 의미를 가지고 있습니다. 바로 네임스페이스 System을 사용한다는 말과 같습니다. using을 이용하면, 전체 이름을 참조하지 않고 선언된 네임스페이스 내부 개체들에 접근할 수 있어 불필요한 타이핑을 막습니다.

 

namespace = 네임스페이스(namespace)는 관련된 구조체, 클래스, 델리게이트, 인터페이스 등을 그룹화 한것을 말합니다. 예를 들어서, System.Collections.Generic에는 제네릭 컬렉션을 정의하는 클래스와 인터페이스들이 들어있습니다. 또 System.Linq에는, LINQ를 사용하는 쿼리를 지원하는 클래스와 인터페이스들이 들어있습니다. 이처럼 네임스페이스는 사용하기 편리하게끔 성격이 비슷한 것들을 묶어놓는 것과 같습니다.

 

main = static void Main는 메소드(method)이며, 메인(main) 메소드는 그중에서 가장 중요한 메소드 이며, 프로그램의 최초의 진입점(Entry Point)을 나타냅니다. 모든 프로그램에는 메인 메소드가 반드시 존재해야하며, 메인 메소드가 시작되면 프로그램이 시작되며, 종료되면 프로그램도 같이 종료됩니다. 여기서 static는 한정자로 정적인 메소드를 의미하며, void는 반환 형식으로 반환 값이 없음을 의미합니다.

 

< 자리표시자 >

프로그램 실행 결과를 화면에 출력할 때 사용하는 출력문 등에서는 자리 표시자(틀) 개념을 이용해서 출력 서식을 지정할 수 있습니다. {n} 형태로 {0}, {1}, {2} 순서대로 자리를 만들고 그다음에 있는 값을 차례로 넘겨받아 출력합니다. {0}, {1} 식으로 뒤에 이어 나올 값에 대한 자리 번호(인덱스)를 지정해 놓는 방법을 자리 표시자(place holder) 또는 서식 지정자(format specifier)라고 합니다. 번호 인덱스는 0부터 시작합니다. 다음 코드를 살펴보세요.

Console.WriteLine("{0}", "Hello, C#");

WriteLine() {0} 형태로 0번째 자리를 만들어 놓으면 콤마 뒤에 있는 "Hello, C#" 문자열이 {0} 자리에서 실행됩니다.

 

 

 

 

 

 

728x90
반응형
728x90
반응형

오버로딩 (Overloading)과 오버라이딩 (Overriding)은 객체 지향 프로그래밍에서 메소드를 다룰 때 사용되는 개념입니다. 

 

1.오버로딩 (Overloading): 메소드 오버로딩은 한 클래스 내에서 같은 이름의 메소드를 여러 개 정의하는 것입니다. 
이 메소드들은 매개변수의 수, 타입 또는 순서가 다르기 때문에 서로 다른 기능을 수행할 수 있습니다. 
또한 컴파일러가 호출되는 매개변수를 기준으로 적절한 메소드를 선택합니다. 
메소드 오버로딩을 사용하면 코드를 간결하게 유지하면서 동일한 기능을 하는 메소드들을 하나의 이름으로 그룹화할 수 있습니다.

public class Calculation
{
    public int Add(int a, int b)
    {
        return a + b;
    }

    public double Add(double a, double b)
    {
        return a + b;
    }
}



2. 오버라이딩 (Overriding): 메소드 오버라이딩은 기반 클래스(base class)에 있는 메소드를 파생 클래스(derived class)에서 재정의하여 사용하는 것입니다. 
이를 통해 파생 클래스는 부모 클래스의 메소드를 같은 이름과 시그니처로 사용할 수 있지만, 다른 동작을 수행하도록 구현할 수 있습니다. 
오버라이딩을 사용하면 기반 클래스의 기본 기능을 변경하거나 확장해서, 더 구체적이고 맞춤화된 동작을 제공할 수 있습니다.

public class Animal
{
    public virtual void Speak()
    {
        Console.WriteLine("알 수 없음");
    }
}

public class Dog : Animal
{
    public override void Speak()
    {
        Console.WriteLine("멍멍");
    }
}

 

 

 

 

728x90
반응형

'입사후 공부한 내용' 카테고리의 다른 글

[C#] 기본 개념  (0) 2023.06.23
[React] 노마드코더 기초  (0) 2023.06.21
[MSSQL] 연결 에러 해결!  (0) 2023.06.16
[ASP.NET] MVC강의 기초 및 심화  (0) 2023.06.13
[ASP.NET] 개념과 역사  (0) 2023.06.13
728x90
반응형

React를 사용하기 위해 불러야 할 스크립트

  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>

 

React JS가 element를 생성하고 event listener를 더하는 것을 도와준다.

ReactDOM은 React element들을 가져다가 HTML로 바꿔준다. 

 

JSX(JavaScript XML)는 리액트와 같은 라이브러리에서 사용하는 문법입니다.

자바스크립트 내부에서 HTML과 유사한 구문을 사용하여 UI구조를 작성하는데 사용됩니다.

 

<JSX>

 

과거문법

function WelcomeMessage() {
  return React.createElement('h1', null, 'Hello, world!');
}

 

현재문법

function WelcomeMessage() {
  return <h1>Hello, world!</h1>;
}

 

그런데 JSX문법으로 그냥 작성하면 html에서는 알아듣지 못한다. 대신 Babel을 가져와서 사용한다.

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  //ReactJS
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  //ReactDOM
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  //Babel
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel"> //꼭 넣어줘야 정상작동
    const root = document.getElementById("root");
    const Title = (
      <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
        Hello~
      </h3>
    );
    const Button = (
      <button
        style={{
          backgroundColor: "tomato",
        }}
        onClick={() => console.log("im clicked")}
      >
        Click me!
      </button>
    );
    const contatiner = React.createElement("div", null, [Title, Button]);
    ReactDOM.render(contatiner, root);
  </script>
</html>

 

더 나은 형태로 변형하면 다음과 같다.

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    function Title() {
      return (
        <h3 id="title" onMouseEnter={() => console.log("mouse enter")}>
          Hello~
        </h3>
      );
    }
    const Button = () => (
      <button
        style={{
          backgroundColor: "tomato",
        }}
        onClick={() => console.log("im clicked")}
      >
        Click me!
      </button>
    );
    const Container = () => (
      <div>
        <Title /> <Button />
      </div>
    );
    ReactDOM.render(<Container />, root);
  </script>
</html>

 

<State>

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    const root = document.getElementById("root");
    function App() {
      let [counter, setCounter] = React.useState(0);
      const onClick = () => {
        setCounter(counter + 1);
      };
      return (
        <div>
          <h3>Total clicks: {counter}</h3>
          <button onClick={onClick}>Click me!</button>
        </div>
      );
    }
    ReactDOM.render(<App />, root);
  </script>
</html>

 

state를 세팅하는 데는 2가지 방법이 있다.
1) 직접 할당 :setState(state +1)
2 )함수 할당:setState(state => state +1) (함수의 첫번째 인자는 현재 state 이다)

현재 state랑 관련이 없는 값을 새로운 state로 하고싶은 경우에는 (1),
현재 state에 조금의 변화를 주어서 새로운 state를 주고 싶은 경우에는 (2)

최종적으로는 2번 함수할당이 더 안전하다.

 

      const [amount, setAmount] = React.useState(0);
      const [inverted, setInverted] = React.useState(false);

 

두번째로 들어가는 함수는 실행될때마다 화면이 새로 렌더링된다는 것이 중요!

 

시간과 분 단위 변환하는 코드

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <script type="text/babel">
    function MinutesToHours() {
      const [amount, setAmount] = React.useState(0);
      const [inverted, setInverted] = React.useState(false);
      const onChange = (event) => {
        setAmount(event.target.value);
      };
      const reset = () => setAmount(0);
      const onInvert = () => {
        reset();
        setInverted((current) => !current);
      };

      return (
        <div>
          <div>
            <label htmlFor="minutes">Minutes</label>
            <input
              value={inverted ? amount * 60 : amount}
              id="minutes"
              placeholder="Minutes"
              type="number"
              onChange={onChange}
              disabled={inverted}
            />
          </div>

          <div>
            <label htmlFor="hours">Hours</label>
            <input
              value={inverted ? amount : Math.round(amount / 60)}
              id="hours"
              placeholder="Hours"
              type="number"
              onChange={onChange}
              disabled={!inverted}
            />
          </div>
          <button onClick={reset}>Reset</button>
          <button onClick={onInvert}>
            {inverted ? "Turn back" : "Invert"}
          </button>
        </div>
      );
    }

    function KmToMiles() {
      const [distance, setDistance] = React.useState(0);
      const [flipped, setFlipped] = React.useState(false);
      const onChange = (event) => {
        setDistance(event.target.value);
      };
      const reset = () => setDistance(0);
      const onFlip = () => {
        reset();
        setFlipped((current) => !current);
      };
      return (
        <div>
          <div>
            <label htmlFor="km">KM</label>
            <input
              value={flipped ? Math.round(distance * 1.609344) : distance}
              id="km"
              placeholder="KM"
              type="number"
              onChange={onChange}
              disabled={flipped}
            />
          </div>
          <div>
            <label htmlFor="miles">Miles</label>
            <input
              value={flipped ? distance : Math.round(distance * 0.621371)}
              id="miles"
              placeholder="Miles"
              type="number"
              onChange={onChange}
              disabled={!flipped}
            />
          </div>
          <button onClick={reset}>Reset</button>
          <button onClick={onFlip}>{flipped ? "Turn back" : "Flip"}</button>
        </div>
      );
    }
    function App() {
      const [index, setIndex] = React.useState("XX");
      const onSelect = (event) => {
        setIndex(event.target.value);
      };
      return (
        <div>
          <h1>Super Converter</h1>
          <select value={index} onChange={onSelect}>
            <option value="XX">Select your units</option>
            <option value="0">Minutes & Hours</option>
            <option value="1">Km & Miles</option>
          </select>
          <hr />
          {index === "XX" ? "Please select your units" : null}
          {index === "0" ? <MinutesToHours /> : null}
          {index === "1" ? <KmToMiles /> : null}
          {/* 2개일 때는 이거도 가능?
          {index === "0" ? <MinutesToHours /> : <KmToMiles />}*/}
        </div>
      );
    }
    const root = document.getElementById("root");
    ReactDOM.render(<App />, root);
  </script>
</html>

 

 

 

<Props>

Props(속성)은 React에서 데이터를 부모 컴포넌트로부터 자식 컴포넌트로 전달하는 방법입니다. 

이렇게 props를 통해 컴포넌트 간에 데이터를 주고받을 수 있습니다. 

Props는 읽기 전용이며, 자식 컴포넌트에서 변경할 수 없습니다.

<!DOCTYPE html>
<html>
  <body>
    <div id="root"></div>
  </body>
  <script src="https://unpkg.com/react@17.0.2/umd/react.production.min.js"></script>
  <script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.production.min.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
  <!-- PropTypes -->
  <script src="https://unpkg.com/prop-types@15.7.2/prop-types.min.js"></script>

  <script type="text/babel">
    function Btn({ text, fontSize = 12 }) {
      return (
        <button
          style={{
            backgroundColor: "tomato",
            color: "white",
            padding: "10px 20px",
            border: 0,
            borderRadius: 10,
            fontSize,
          }}
        >
          {text}
        </button>
      );
    }
    Btn.propTypes = {
      text: PropTypes.string.isRequired,
      fontSize: PropTypes.number,
    };
    function App() {
      return (
        <div>
          <Btn text="Save Changes" fontSize={18} />
          <Btn text={"Continue"} />
        </div>
      );
    }
    const root = document.getElementById("root");
    ReactDOM.render(<App />, root);
  </script>
</html>

 

<Create React App>

새로운 폴더를 만들고 싶은 공간에서

우클릭 -> 터미널 열기 실행후 다음과 같은 명령어를 입력하자.

 

npx create-react-app my-app(폴더명)

 

그러면 중간에 질문이 나오고 y를 누르면 된다.

 

해당 명령어를 통해 새로 생성하는 이유는 다음과 같다.

 

<EFFECTS>

• 리액트를 사용하는 이유: 최소 단위의 렌더링을 위해
• useState(): 변수, 변수를 제어하는 함수로 구성되며 변하는 값을 제어, 해당 부분의 리렌더링을 위함
• props: 태그의 속성 값을 함수의 아규먼트 처럼 컴포넌트에 값을 전달해준다.
• useEffect(): 코드의 실행 시점을 관리할 수 있는 선택권을 얻는 방어막 같은 존재, 디펜던시가 없을 경우 최초 1회 실행, 있을 경우 해당 값이 변할 경우 실행한다. 이 때 디펜던시는 여러개 입력이 가능하다.


🏴 부모 컴포넌트에서 리렌더링이 일어날 경우 모든 자식들이 리렌더링이 된다.(wa can use memo)

🏴 propType을 설치하고 props의 타입을 지정해 줄 수 있다. 이 때 isRequired로 필수값을 지정 가능

 

useEffect()란?

더보기

useEffect는 state의 상태를 감지 변경이 있을 때란 해당 컴포넌트를 랜더링한다.
useState(function(), []) [] 로 3가지 경우의 수 존재 ex) a, b 스테이트
1. 빈 배열을 넣는 경우, 최초 1회 랜더링 될 때만 실행한다.
2. [a] 하나의 state만 넣는 경우 a가 변경될 경우만 랜더링한다.
3. [a, b] a나 b중 하나가 값이 변경 될 때 랜더링한다.

useEffect 왜 써?
렌더링이 계속 된다면, 특히 특정 api를 불러오게 되는 경우 계속해서 불러오는 문제가 생길 수 있다.
state를 변경할 때, 계속해서 렌더링 되는 문제점이 존재한다. 많은 state가 존재한다면 성능 저하 문제가 발생할 수 있다. 이런 문제를 해결하기 위해 사용한다.

 

 

import { useEffect, useState } from "react";

function App() {
  const [counter, setValue] = useState(0);
  const [keyword, setKeyword] = useState("");
  const onClick = () => setValue((prev) => prev + 1);
  const onChange = (event) => setKeyword(event.target.value);
  console.log("난 항상 실행중!");
  useEffect(() => {
    console.log("1번만 실행");
  }, []);
  useEffect(() => {
    if (keyword !== "" && keyword.length > 5) {
      console.log("키워드 변화에만 실행");
    }
  }, [keyword]);
  useEffect(() => {
    console.log("카운터 변화 실행");
  }, [counter]);
  return (
    <div>
      <input
        value={keyword}
        onChange={onChange}
        type="text"
        placeholder="Search here..."
      ></input>
      <h1>{counter}</h1>
      <button onClick={onClick}>Click me!</button>
    </div>
  );
}

export default App;

 

<To Do List>

import { useEffect, useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);
  const onChange = (event) => setToDo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo === "") {
      return;
    }
    //중요한 로직
    setToDos((currentArray) => [toDo, ...currentArray]); 
    setToDo("");
  };
  return (
    <div>
      <h1>My To Dos({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="write your to do..."
        />
        <button>Add To Do</button>
      </form>
    </div>
  );
}

export default App;

 

import { useEffect, useState } from "react";

function App() {
  const [toDo, setToDo] = useState("");
  const [toDos, setToDos] = useState([]);
  const onChange = (event) => setToDo(event.target.value);
  const onSubmit = (event) => {
    event.preventDefault();
    if (toDo === "") {
      return;
    }
    setToDos((currentArray) => [toDo, ...currentArray]);
    setToDo("");
  };
  return (
    <div>
      <h1>My To Dos({toDos.length})</h1>
      <form onSubmit={onSubmit}>
        <input
          onChange={onChange}
          value={toDo}
          type="text"
          placeholder="write your to do..."
        />
        <button>Add To Do</button>
      </form>
      <hr />
      <ul>
        {toDos.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

 

<Coin Tracker>

import { useEffect, useState } from "react";

function App() {
  const [loading, setLoading] = useState(true);
  const [coins, setCoins] = useState([]);
  useEffect(() => {
    fetch("https://api.coinpaprika.com/v1/tickers")
      .then((response) => response.json())
      .then((json) => {
        setCoins(json);
        setLoading(false);
      });
  }, []);
  return (
    <div>
      <h1>The COIN TRADE {coins.length}</h1>
      {loading ? <strong>Loading...</strong> : null}
      <ul>
        {coins.map((coin) => (
          <li>
            {coin.name} ({coin.symbol}): {coin.quotes.USD.price}
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;

 

<Movie App>

import { useState } from "react";
import Movie from "../components/Movie";

function Home() {
  const [loading, setLoding] = useState(true);
  const [movies, setMovies] = useState([]);
  const getMovies = async () => {
    const json = await (
      await fetch(
        `https://yts.mx/api/v2/list_movies.json?minimum_rating=9&sort_by=year`
      )
    ).json();
    setMovies(json.data.movies);
    setLoding(false);
  };

  useEffect(() => {
    getMovies();
  }, []);
  console.log(movies);
  return (
    <div>
      {loading ? (
        <h1>Loading...</h1>
      ) : (
        <div>
          {movies.map((movie) => (
            <Movie
              key={movie.id}
              medium_cover_image={movie.medium_cover_image}
              title={movie.title}
              summary={movie.summary}
              genres={movie.genres}
            />
          ))}
        </div>
      )}
    </div>
  );
}

export default Home;

npm i react-router-dom@5.3.0

 

 

 

 

 

 

 

 

728x90
반응형

'입사후 공부한 내용' 카테고리의 다른 글

[C#] 기본 개념  (0) 2023.06.23
[개념정리] 오버로딩, 오버라이딩  (0) 2023.06.22
[MSSQL] 연결 에러 해결!  (0) 2023.06.16
[ASP.NET] MVC강의 기초 및 심화  (0) 2023.06.13
[ASP.NET] 개념과 역사  (0) 2023.06.13
728x90
반응형

기존의 MSSQL 연결 코드

const config = {
user: process.env.MSSQL_USER,
password: process.env.MSSQL_PASSWORD,
server: process.env.MSSQL_SERVER,
database: process.env.MSSQL_DB,
options: {
encrypt: true,
cryptoCredentialsDetails: {
minVersion: "TLSv1.3",
},
},

 

해당 코드로 실행시에는 여러 에러코드가 발생했다.

 

< 에러 내용 >

더보기

(node:17836) [DEP0123] DeprecationWarning: Setting the TLS ServerName to an IP address is not permitted by RFC 6066. This will be ignored in a future version.
(Use `node --trace-deprecation ...` to show where the warning was created)
데이터베이스 연결에 실패했습니다.

originalError: ConnectionError: Failed to connect to 110.10.130.21:1433 - C84E0000:error:0A0000BF:SSL routines:tls_setup_handshake:no protocols available:c:\ws\deps\openssl\openssl\ssl\statem\statem_lib.c:124:

 

그리고 계속된 구글링을 통해 다음과 같이 코드를 수정하였다.

// 데이터베이스 연결 설정
const config = {
  type: "mssql",
  server: process.env.MSSQL_SERVER,
  database: process.env.MSSQL_DB,
  authentication: {
    type: "default",
    options: {
      userName: process.env.MSSQL_USER,
      password: process.env.MSSQL_PASSWORD,
    },
  },
  options: {
    encrypt: false,
    enableArithAbort: true,
    cryptoCredentialsDetails: {
      minVersion: "TLSv1",
    },
    trustServerCertificate: true,
  },
};

(async function () {
  try {
    // 데이터베이스 연결
    await sql.connect(config);
    console.log("데이터베이스에 연결되었습니다.");
  } catch (err) {
    console.error("데이터베이스 연결에 실패했습니다.", err);
  }
})();

자세히 읽어보기 보단 코드 한줄씩 붙여가며 계속 실행해본 것이라

성공한 이유가 궁금했다. 성공한 이유는 다음과 같다고 한다.

현재 코드에서 연결이 정상적으로 작동한 것은 다음과 같은 변경사항들 때문입니다:

encrypt: false로 변경함으로써 SSL/TLS 암호화를 사용하지 않게 되어 영향을 미칠 수 있습니다. 이것은 서버가 SSL/TLS 암호화를 지원하지 않을 때 문제를 해결할 수 있습니다. 하지만 보안상의 문제로 데이터 전송이 암호화되지 않게 됩니다.

trustServerCertificate
: true 옵션을 추가하여 서버의 인증서를 무조건 신뢰하도록 설정했습니다. 이 변경 사항으로 인해 클라이언트가 서버의 인증서를 확인하지 않고 연결을 수락하게 됩니다. 인증서가 올바르지 않거나, 자가 서명된 인증서를 사용하는 경우에도 연결에 성공할 수 있습니다. 그럼에도 불구하고 이 설정은 보안상 좋지 않은 선택이며 데이터 공격에 취약해질 수 있습니다.

cryptoCredentialsDetails 
옵션을 수정하여 최소 TLS 버전을 'TLSv1'로 변경했습니다. 이것은 이전에 발생한 TLS 버전 불일치 문제를 해결하는 데 도움이 되었을 수 있습니다.
변경된 코드는 연결 문제를 일시적으로 해결했지만, 중요한 것은 데이터베이스와 클라이언트 사이의 전송에 암호화된 연결을 사용하도록 설정하는 것입니다. SSL/TLS를 사용하여 데이터를 암호화하고, 유효한 서버 인증서를 사용하여 서버에 대한 신뢰를 높이는 것이 좋습니다. 이러한 설정을 적용하기 위해 데이터베이스 서버 관리자와 협력하는 것이 필요할 수 있습니다.

728x90
반응형
728x90
반응형

강의듣기 : https://www.youtube.com/playlist?list=PLtht1_et-35DI4cRVKEUUaQAuT3FW2jet 

 

비주얼 스튜디오는 커뮤니티(무료)버전으로 다운 받고,

.NET 프레임워크 를 검색해서 추가 다운 받아줘야 한다.

아래의 ASP.NET 웹 애플리케이션(.NET Framwork)와 ASP.NET 웹 응용프로그램이

새로운 프로젝트로 생성되지 않아 뻘짓을 많이 했다.

 

< 기초 >

비주얼 스튜디오에서 새로운 프로젝트를 만든다.

다음을 누르고 비어있음, MVC를 체크한다. (HTTPS에 대한 구성은 빼주는게 좋다)

만들어졌다면 컨트롤러 폴더에서 우클릭 - 추가 - 컨트롤러 - MVC 5 컨트롤러 비어있음을 추가해준다.

그리고 이름은 HomeController로 바꾼다.

 

이제 다음과 같은 컨트롤러 코드로 변경해주자.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller
    {
        // GET: Home
        public string Index()
        {
            return "My first Application!";
        }
    }
}

위 코드는 Home 컨트롤러에서 Index로 접속가능하게 해준다.

다음과 같은 url로 접속 가능한 이유는 App_start 폴더에 있는 Config에서 설정이 자동으로 되어 있기 때문이다.

 

< 컨트롤러 >

 

 

 

컨트롤러는 클래스,

액션은 메서드,

아이디는 매개변수라고 생각하면 된다.

 

새로운 컨트롤러 Board를 만들어보자.

컨트롤러 폴더에서 우클릭 + 추가를 통해 새로운 컨트롤러 생성.

 

namespace WebApplication1.Controllers
{
    public class BoardController : Controller
    {
        // GET: Board
        public string List(int? Id)
        {
            if (Id == null)
                return "Error Message #1";
            return "보드 리스트: " + Id.Value;
        }
    }
}

 

< 뷰 >

뷰를 사용하려면 메서드에서 string을 변경해야한다. (string -> ActionResult)

namespace WebApplication1.Controllers
{
    public class BoardController : Controller
    {
        // GET: Board
        public ActionResult List(int? Id)
        {
            if (Id == null)
                return HttpNotFound("에러메시지");
            return View();
        }
    }
}

 

현재 view폴더에 아무것도 없고, return View()에도 매개변수가 없기 때문에

아래와 같이 메서드가 있는 줄에서 우클릭+뷰추가를 통해 파일을 만들어준다.

 

List.cshtml 코드

body>
    <div> 
        <table>
            <thead>
                <tr>
                    <th>번호</th>
                    <th>제목</th>
                    <th>글쓴이</th>
                </tr>    
            </thead>
            <tbody>
                @for (int i = 0; i < 10; i++)
                {
                <tr>
                    <td>@(i+1)</td>
                    <td>제목입니다</td>
                    <td>홍길동</td>
                </tr>
                }
            </tbody>
        </table>
    </div>
</body>

실행시키면 다음과 같은 화면이 된다.

< 모델 >

모델은 데이터의 속성을 정의하고 데이터의 처리를 담당합니다.

 

모델 폴더에서 새 항목을 추가합니다.

클래스를 만들어줍니다.

이후 다음의 코드를 작성하면 데이터의 속성을 정의할 수 있습니다.

namespace WebApplication1.Models
{
    public class Document
    {
        // prop 쓰고 tab을 누르면 빠르게 작성가능
        public int Document_Number { get; set; }
        public string Title { get; set; }
        public string Writer { get; set; }
    }
}

데이터의 처리를 위해 새폴더를 만들고 새로운 클래스 파일을 만들어줍니다.

namespace WebApplication1.Data
{
    public class DocumentData
    {
        public List<Document> Documents
        {
            get
            {
                return new List<Document>
                {
                    new Document{ Document_Number = 1, Title="공지1", Writer="홍길동"},
                    new Document{ Document_Number = 2, Title="공지2", Writer="임꺽정"},
                    new Document{ Document_Number = 3, Title="공지3", Writer="변사또"},
                };
            }
        }
    }
}

모델폴더에 데이터 처리를 위한 클래스를 새로 만들어준다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using WebApplication1.Data;

namespace WebApplication1.Models
{
    public class DocumentActs
    {
        public List<Document> GetDocuments()
        {
            DocumentData documentData = new DocumentData();
            var documents = documentData.Documents;
            return documents;
        }
    }
}

 

그리고 보드컨트롤러로 가서 요청을 한다.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebApplication1.Models; //추가

namespace WebApplication1.Controllers
{
    public class BoardController : Controller
    {
        // GET: Board
        public ActionResult List(int? Id)
        {
            if (Id == null)
                return Content("Error Message #1");

            DocumentActs documentActs = new DocumentActs();
            var documents = documentActs.GetDocuments();

            return View(documents);
        }
    }
}

 

그다음 뷰로 가서 출력한다.

@model List<WebApplication1.Models.Document> //프로젝트명+모델+다큐먼트
@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>List</title>
</head>
<body>
    <div> 
        <table>
            <thead>
                <tr>
                    <th>번호</th>
                    <th>제목</th>
                    <th>글쓴이</th>
                </tr>    
            </thead>
            <tbody>
                @foreach (var item in Model)
            {
                <tr>
                    <td>@item.Document_Number</td>
                    <td>@item.Title</td>
                    <td>@item.Writer</td>
                </tr>
            }
            </tbody>
        </table>
    </div>
</body>
</html>

 

이 모든 과정을 설명하자면

먼저 컨트롤러가 모델에서 데이터를 처리하는 클래스를 부름(DocumentActs)

받아온 값을 객체에 담아서 뷰로 리턴합니다.

            DocumentActs documentActs = new DocumentActs();
            var documents = documentActs.GetDocuments();
            return View(documents);

 

< ViewBag & ViewData >

데이터를 전달하는 방법은 다음과 같습니다.

View(object model)

        public ActionResult List()
        {
            DocumentActs documentActs = new DocumentActs();
            var documents = documentActs.GetDocuments();
            return View(documents);
        }

이 경우 하나의 모델데이터만 전달할 수 있기 때문에 여러 데이터를 전달하려 한다면 한계가 있습니다.

그래서 ViewBag&ViewData가 필요합니다.

 

        public ActionResult List()
        {
            DocumentActs documentActs = new DocumentActs();
            MemberActs memberActs = new MemberActs();

            var documents = documentActs.GetDocuments();
            var member = memberActs.GetMember(1);

            ViewBag.Member = member;

            return View(documents);
        }

View()는 한개의 매개변수만 담을 수 있으니,

ViewBag을 통해 다른 매개변수를 저장하고 사용합니다.

        <p>
        @ViewBag.Member.Name 님 환영합니다.
        </p>

 

ViewData는 다음과 같이 사용할 수 있습니다.

ViewData["Members"] = member;

그리고 cshtml으로 갑니다.

@model List<WebApplication1.Models.Document>
@{
    Layout = null;
    var member = ViewData["Member"] as WebApplication1.Models.Member;
}

ViewData의 경우는 형변환을 한 후 사용합니다.

@member.Name 님 환영합니다.
@model List<WebApplication6.Models.Document>
    @foreach (var item in Model)
    {
        <tr>
            <td>@item.Document_Number</td>
            <td>@item.Title</td>
            <td>@item.Writer</td>
        </tr>
    }
////////////////////////////////////////////
    <tbody>
        @foreach (var member in ViewBag.Member)
        {
            <tr>
                <td>@member.Name</td>
                <td>@member.Age</td>
            </tr>
        }
    </tbody>
////////////////////////////////////////////
    <p>이름: @ViewBag.Member[0].Name</p>
    <p>나이: @ViewBag.Member[0].Age</p>
    <p>이름: @ViewBag.Member[1].Name</p>
    <p>나이: @ViewBag.Member[1].Age</p>

 

 

< Razor >

Razor는 렌더링이라는 역활을 담당합니다.

렌더링이란 어떠한 것을 사용자(클라이언트)에게 보여주는 것입니다.

ViewBag.Arr = new string[]
{
	"1",
    "2",
    "3",
}
@foreach(string s in ViewBag.Arr)
{
	<div>@s</div>
}

 

< Layout >

레이아웃을 우리말로 한다면 '배치'입니다.

프로그래밍적으로 레이아웃은 반복되는 코드, 중복되는 코드를 다시 사용할 일 없게끔 하는 것 입니다.

@RenderBody() 라는 것과 입력했던 값이 대체 된다.

<개념정리>

1. ViewBag & ViewData: 이들은 컨트롤러에서 뷰로 데이터를 전달하는 데 사용합니다.
ViewData: ViewData는 Key-Value 쌍의 딕셔너리로서, TempData와 유사하지만 요청이 끝날 때 소멸됩니다. ViewData는 동적 속성을 제공하지 않으며, 문자열을 키로 사용합니다. 데이터 형식을 지정해야 되기 때문에 형식 변환이 필요할 수 있습니다.
ViewBag: ViewBag은 ViewData의 래퍼이며, 동적 속성을 제공하는 데 사용됩니다. ViewBag을 이용하면 코드가 더 짧아지며, 지정된 속성에 동적으로 액세스할 수 있습니다. 형식 변환 필요성이 줄어들지만, 코드 작성 시 덜 엄격하게 체크한다는 단점이 있습니다.

 

2. Razor: Razor는 ASP.NET의 바인딩 구문 중 하나로, C# 또는 VB코드를 HTML 문서에 삽입하여 웹 페이지를 동적으로 생성합니다. Razor 구문은 '@' 기호로 시작하며, 다음과 같은 형식을 가집니다. '@(표현식)', '@{ ... }' 등입니다. Razor는 서버 측 코드와 클라이언트 측 코드를 명확하게 구분하여 개발자가 코드를 쉽게 작성하고 유지할 수 있도록 지원합니다.

 

3. Layout: Layout은 ASP.NET에서 마스터 페이지와 같은 개념으로, 공통되는 페이지 요소를 재사용하고 중복을 줄이기 위한 방법입니다. 여러 뷰에서 공유할 수 있는 베이스 페이지를 설정하고, 각 뷰에 필요한 내용만 추가하여 효율적으로 페이지 구성을 관리할 수 있습니다. Layout 페이지는 _Layout.cshtml 파일로 저장되며, 각 뷰에서 '@{ Layout = "_Layout"; }'와 같은 코드로 그것을 참조할 수 있습니다.

 

< 심화 >

1. Entity Framework 설치

 

새 프로젝트 만들기 -> ASP.NET 웹 응용 프로그램(Empty , MVC) ->

도구(NuGet 패키지 관리자) -> 솔루션용 NuGet 패키지 관리 -> EntityFramework 설치하기

 

 

2. CRUD Action & View생성

Model 폴더에 Book.cs 파일을 만들어준다.

using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace LibraryApplication.Models
{
    public class Book
    {
        [Key]
        public int Book_U { get; set; }
        [DisplayName("제목")]
        public string Title { get; set;}
        [DisplayName("저자")]
        public string Writer { get; set; }
        [DisplayName("요약")]
        public string Summary { get; set; }
        [DisplayName("출판사")]
        public string Publisher { get; set; }
        [DisplayName("출판일")]
        public int Published_date { get; set; }
    }
}

그후 Web.config에서 다음과 같은 코드를 추가한다.

<connectionStrings>
<add name ="DBCS" connectionString="server=MSSQL_SERVER_ID; database=Library; integrated security=SSPI" providerName="System.Data.SqlClient"/>
</connectionStrings>

 

그리고 Context라는 폴더 생성후 클래스 LibaryDb 생성

using LibraryApplication.Models;
using System.Data.Entity;

namespace LibraryApplication.Context
{
    public class LibaryDb : DbContext
    {
        public LibaryDb():base("name=DBCS") { }
        public DbSet<Book> Books { get; set; }
    }
}

컨트롤러 생성

 

생성후 컨트롤러에서 F5를 눌러 실행하면 화면이 발생한다.

생성 삭제 수정 등이 간단하게 구현되어 있다.

 

3. Action & View 설명

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형
728x90
반응형

참고사이트 : https://www.dotnetnote.com/docs/aspnet/aspnet-intro/

유튜브 재생목록 : https://www.youtube.com/playlist?list=PLO56HZSjrPTBblm3CbalLSf7Zv7IrwU7G 

ASP.NET 개념정리 : https://www.youtube.com/watch?v=idO_OsRcCYc&t=1s 

 

ASP.NET이란 마이크로소프트의 웹프레임워크이자 웹 기술의 집합체다.

Web Pages는 현재 안쓰고 MVC로 바뀌었다고 보면 됨. 현재는 MVC가 주류로 사용되고 있다.

 

 

 

 

728x90
반응형

+ Recent posts