데이터 네트워크의 2가지 형태
< 이더넷(Ethernet), 토큰링(TokenRing) >

    1.  이더넷이란?
  • 이더넷이란 네트워크를 구축하는 방식 중 하나로, 우리나라에서는 대부분이 이더넷 방식을 사용하고 있다.
  • 이더넷 방식의 가장 큰 특징은 CSMA/CD(Carrier Sense Multiple Access/Collision Detection) 방식으로 통신한다는 것인데, 이 방식은 컴퓨터가 네트워크를 살펴봐서 아무도 통신하고 있지 않으면 무조건 자기 데이터를 실어서 보낸 후 잘 갔는지 확인해보는 방식이다. 그런데 만약 동시에 2개의 컴퓨터에서 데이터를 실어 보내려고 하면 충돌이 발생하게 되는데, 이것을 '콜리전(Collision)'이라고 한다. 이렇게 콜리전이 발생하면 이 두 PC는 자신이 보내려던 데이터를 랜덤한 시간동안 기다렸다가 다시 보내게 된다.



    2. 토큰링이란?
  • 토큰링 방식은 네트워크에서 오직 한 PC, 즉 토큰을 가진 PC만이 네트워크에 데이터를 실어 보내는 방식이다.
  • 데이터를 보내고 나면 토큰을 옆 PC에 전달한다. 만약 전송할 데이터가 없다면 토큰을 다시 옆 PC에 전달한다.
  • 이렇게 토큰을 옆으로 전달하는 방식이 토큰링이다.
  • 장점 
    • 충돌(Collision)이 발생하지 않는다. 토큰을 가진 PC만이 데이터를 전송하므로
    • 네트워크에 대한 성능을 예측하기 쉽다.
  • 단점
    • 지금 바로 보내야 할 데이터가 있고, 다른 PC들은 보낼 데이터가 하나도 없더라도 토큰이 올 때까지 기다려야한다.
  • 토큰링 프로토콜은 IBM이 처음 개발. 지금은 이더넷의 발전으로 사라지고 있음.





  1.  싱글톤 패턴(Singleton pattern)이란?
  • 싱글톤은 단 하나의 객체만을 생성하게 강제하는 패턴이다. 즉, 클래스를 통해 생성할 수 있는 객체는 Only one. 
  • 하나의 프로그램 내에서 하나의 인스턴스만을 사용해야하는 상황에 주로 쓰임. 
  • 장점
    • 고정된 메모리 영역을 사용하도록 단 한번 인스턴스를 얻어오기 때문에 메모리의 낭비를 줄일 수 있다.
    • 공통된 객체를 사용해야하는 코딩에서 매번 객체를 생성하지 않고 같은 객체를 사용하도록 하면 성능면에서 좋아진다.


  1. Kotlin에서의 싱글톤 ( =java static 싱글톤)
  • java static 싱글톤과 개념은 같다.
  • 자바에서는 static 멤버를 만들고 생성자를 private로 처리하는 등이 필요하지만,
  코틀린에서는 object로 만들면 된다.
    

            

예제.)

 - 코드 -
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package Singleton
class FirstClass{
    companion object {
        init {
            println("FirstClass invoked")
        }
        fun print()= println("This is firstClass Function")
    }
}
class SecondClass{
    companion object {
        init {
            println("SecondClass invoked")
        }
        fun print()=println("This is secondClass Function")
    }
}

object firstSingleton{
    val instance=FirstClass()
}
object secondSingleton{
    val instance=SecondClass()
}
fun main(args: Array<String>) {
    val f1=firstSingleton.instance
    val f2=firstSingleton.instance
    println(f1==f2)
    println()
    println()
    val t1=secondSingleton.instance
    val t2=secondSingleton.instance
    println(t1==t2)
}
cs



- 결과 -
1
2
3
4
5
6
FirstClass invoked
true
 
 
SecondClass invoked
true
cs


FirstClass, secondClass에 대한 싱글톤 인스턴스를 각각 만들어 보았다.
main에서 firstSingleton 인스턴스를 2번 요청했지만 해당 인스턴스가 1개만 생성된다는 것을 결과를 통해 알 수 있다.
즉, 하나의 클래스를 통해 생성할 수 있는 객체는 하나라는 것이 확인가능하다.

    






3. Spring의 Singleton ( 싱글톤 레지스트리 )

  • 자바의 기본적인 싱글톤 패턴의 구현 방식은 여러 가지 단점이 있기 때문에,
  스프링은 직접 싱글톤 형태의 오브젝트를 만들고 관리하는 기능을 제공한다. => 싱글톤 레지스트리
  • 싱글톤 레지스트리의 장점은 static method와 private 생성자를 사용해야 하는 비정상적인 클래스가 아니라 평범한 자바 클래스를 싱글톤으로 활용하게 해준다.
  • 스프링의 싱글톤 레지스트리 덕분에 싱글톤 방식으로 사용될 애플리케이션 클래스라도 public 생성자를 가질 수 있다.
  • 싱글톤과 오브젝트의 한계
    • 싱글톤은 멀티쓰레드 환경이라면 여러 쓰레드가 동시에 접근해서 사용할 수 있다.
     따라서 상태 관리에 주의를 기울여야 한다. 기본적으로 싱글톤이 멀티쓰레드 환경에서 서비스 형태의
     오브젝트로 사용되는 경우에는 상태정보를 내부에 갖고 있지 않은 무상태(stateless) 방식으로 만들어        져야한다.
    •  무상태(stateless) 방식으로 만들기 위해서는 매소드 안에서 생성되는 로컬 변수를 사용하면 된다. 
     로컬 변수는 매번 새로운 값을 저장할 독립적인 공간이 만들어지기 때문에 싱글톤이라 해도 여러 쓰레
 드 변수의 값을 덮어쓰지 않는다.
    • 따라서 스프링의 싱글톤 빈으로 사용되는 클래스를 만들 때는 개별적으로 바뀌는 정보는 로컬 변수로 정의하거나, 파라미터로 주고받으면서 사용하게 해야 한다.
    • 자신이 사용하는 다른 싱글톤 빈을 저장하려는 용도라면 인스턴스 변수를 사용해도 된다. 
    스프링이 한 번 초기화해주고 나면 이후에는 수정되지 않기 때문에, 멀티쓰레드 환경에서 사용해도 문제가 없다.





- 내용과 관련된 피드백은 언제나 환영합니다

'Spring Framework' 카테고리의 다른 글

Spring 기본 개념  (0) 2018.12.31

BOJ(백준) 1952번 달팽이2



문제 : M줄 N칸의 Matrix에 달팽이가 (0,0)부터 돌았을 때 몇 번 방향을 꺾는지 확인하는 문제다.


매우 쉬운 문제지만, 나의 코드의 1/3밖에 안되지만 속도도 더 빠른 BOJ id tncks0121님의 코드를 소개하고자 글을 쓴다.


 먼저 나의 코드는 아래와 같다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fun main(args: Array<String>) {
    val (r,c)= readLine()!!.split(' ').map { it.toInt() }
    val map=Array(r){IntArray(c)}
    val dx= arrayOf(0,1,0,-1)
    val dy= arrayOf(1,0,-1,0)
    var res=0
    var count=1

    fun go(x:Int,y:Int,dir:Int){
        map[x][y]=count++
        val bx=x+dx[dir]
        val by=y+dy[dir]
        if(bx in 0 until r && by in 0 until c && map[bx][by]==0){
            go(bx, by, dir)
        }
        else{
            res++
            if(map[x+dx[(dir+1)%4]][y+dy[(dir+1)%4]]==0)
               go(x+dx[(dir+1)%4],y+dy[(dir+1)%4],(dir+1)%4)
        }
    }
    map[0][0]=1
    go(0,0,0)
    println(res-1)
}
cs


 나의 코드 개념은 처음(0,0)부터 돌면서 matrix에 다 숫자를 써준다는 것이다. 

tncks님의 코드를 보고 감탄을 할 정도로 내 코드는 역겨웠다....



 다음은 tncks0121님의 코드이다.


1
2
3
4
5
6
7
8
9
10
11
12
fun main(args: Array<String>) {
  fun go(n: Int, m: Int): Int = when {
    n == 1 -> 0
    m == 1 -> 1
    n == 2 -> 2
    m == 2 -> 3
    else -> 4 + go(n - 2, m - 2
  }
  val (M, N) = readLine()!!.split(" ").map{ it.toInt() }
  println(go(M, N))
}
cs


  go 함수를 파헤쳐보자...

 go함수 내부의 when절 내부에 else문을 보면 4 + go(n-2, m-2) 로 되어있는데

이것은 한바퀴 돌았다는 것을 의미한다.  4 = 방향을 4번 바꿨다 = 한바퀴 돌았다. 

그리고 n과 m을 2씩 줄여서 재귀함수를 돌린다. 왜냐하면 한바퀴 돌면  Matrix의 행과 열의 양끝을 돈 것이므로...


이제 else위의 경우를 하나하나씩 살펴보자.

 n == 1 -> 0   : 이것은 row(행)가 1개밖에 없는 것으로  col(열)이 몇개가 되든 우측 방향으로 가기만 하면 끝난다는 생각이므로 , 0을 return하게 하였다.


 m == 1 -> 1    : 이것은 col이 1개밖에 없는 것으로 1을 return한다. 이유는 재귀를 돌고나면 우측방향으로 돌고있다고 생각하기 때문에(처음에 시작이 오른쪽 방향임), 그런데 현재 col이 1이므로 아래 방향으로 가야한다 = 한번 방향 전환을 해야함. 따라서 1을 return 한다.


 n == 2 -> 2   : 이 것은 row가 2인 상황이다. 위에 내용을 이해 했다면 왜 2를 return 하는지 알 수 있다.

한번 더 설명하자면, row가 2인 경우 col의 크기에 상관없이 방향 전환을  ( 우측 상단 끝, 우측 하단 끝) 이렇게 2번 하면 된다. 따라서 2를 return 한다.


 m == 2 -> 3 : 이 설명은 생략한다.



 

 결론 : 내 코드는 Matrix의 모든 Point를 다 돌아보도록 짰는데, 이 코드는 재귀를 몇번 돌지도 않는다.....



 

 일단 내가 판단하기에 잘 짰다고 생각해서 코드를 보고 퍼왔다. tncks님이 이 글을 보신다면 댓글좀요.

코틀린 좀 가르쳐줘요.

+ Recent posts