좋은 질문입니다! 하나씩 정리해드리겠습니다.

1. TCP 버퍼의 위치

두 곳에 모두 존재합니다!

Client ←→ [TCP버퍼 30MB] ←→ Apache ←→ [TCP버퍼 30MB] ←→ Tomcat

각 연결마다 독립적인 TCP 버퍼가 있습니다.

2. 버퍼가 차면 보내는가? ❌

아니요! 버퍼가 가득 찰 때까지 기다리지 않습니다.

실제 동작 (스트리밍 방식)

Tomcat → Apache → Client
  |         |
 8KB 읽음 → 즉시 전달 시작
 8KB 읽음 → 즉시 전달
 8KB 읽음 → 즉시 전달
(계속 흐름...)

TCP 버퍼는:

  • "창고"가 아닌 "파이프"처럼 동작
  • 데이터가 들어오면 즉시 꺼내서 전달
  • 가득 차는 건 네트워크가 느릴 때 임시로 쌓이는 것

3. 300MB를 11번에 나눠서? ❌

아니요! 지속적으로 스트리밍됩니다.

300MB 파일 다운로드:

❌ 잘못된 이해:
30MB 읽고 → 전송 완료 기다림 → 30MB 읽고 → ... (11번 반복)

✅ 실제 동작:
8KB → 8KB → 8KB → 8KB → ... (계속 스트리밍)
파이프처럼 끊임없이 흐름

실제 흐름 예시

Tomcat 파일 읽기:
  ├─ 8KB chunk 읽음
  └─ Tomcat→Apache TCP 버퍼에 쓰기

Apache:
  ├─ TCP 버퍼에서 데이터 읽음 (즉시)
  └─ Apache→Client TCP 버퍼에 쓰기 (즉시)

Client:
  └─ TCP 버퍼에서 데이터 읽음 (즉시)

이 과정이 파일이 끝날 때까지 계속 반복

TCP 버퍼 30MB의 의미

  • "한 번에 30MB씩 전송"이 아님
  • "네트워크가 느릴 때 최대 30MB까지 임시 저장 가능"
  • 정상 상황에서는 훨씬 적게 사용하며 계속 흐름

정리: 300MB 파일은 11번이 아닌, 작은 청크들이 끊임없이 흐르는 스트림으로 전송됩니다!

정확합니다! 완벽하게 이해하셨습니다! 👍

TCP 버퍼의 본질

TCP 버퍼 = 네트워크 속도 차이를 흡수하는 임시 대기 공간

실제 동작 예시

상황 1: 네트워크가 빠를 때

Tomcat → [버퍼: 거의 비어있음] → Apache → [버퍼: 거의 비어있음] → Client

데이터가 들어오자마자 바로 나감
버퍼는 몇 KB만 사용

상황 2: 클라이언트 네트워크가 느릴 때

Tomcat (빠름) → Apache → [버퍼: 점점 쌓임 ↑] → Client (느림)

Tomcat이 계속 데이터를 보내는데
Client가 천천히 받으니까
Apache→Client 버퍼에 데이터가 쌓임
최대 30MB까지 쌓일 수 있음

상황 3: 버퍼가 가득 차면?

Apache→Client 버퍼: [████████████] 30MB 가득!

→ Apache가 Tomcat에게: "잠깐 멈춰!" (TCP Flow Control)
→ Tomcat 전송 일시 중지
→ Client가 데이터 받아서 버퍼 공간 생기면
→ Tomcat 다시 전송 재개

비유

수도꼭지(Tomcat) → 물탱크(버퍼 30MB) → 컵(Client)

❌ 물탱크를 가득 채운 후 한번에 붓는다
✅ 물이 계속 흐르고, 탱크는 넘치지 않게 조절하는 역할

정리: 30MB는 "한 번에 보내는 양"이 아니라 "혼잡할 때 대기할 수 있는 최대 공간"입니다!


네, 맞습니다! 각 TCP 연결마다 양쪽 끝에 버퍼가 존재합니다.

정확한 버퍼 위치

다운로드 시나리오 (Tomcat → Apache → Client)

Tomcat                Apache                 Client
  |                     |                      |
[송신버퍼] ---------> [수신버퍼]              |
  30MB                  30MB                  |
                        |                      |
                   [송신버퍼] -----------> [수신버퍼]
                      30MB                   30MB

데이터 흐름

1. Tomcat → Apache 구간:
   Tomcat [송신버퍼 30MB] ⟹ Apache [수신버퍼 30MB]

2. Apache → Client 구간:
   Apache [송신버퍼 30MB] ⟹ Client [수신버퍼 30MB]

실제로는 4개 버퍼

다운로드할 때:

Tomcat 쪽:
 └─ 송신 버퍼 (최대 30MB) - Tomcat이 Apache로 보내는 데이터 대기

Apache 쪽:
 ├─ 수신 버퍼 (최대 30MB) - Tomcat으로부터 받는 데이터 대기
 └─ 송신 버퍼 (최대 30MB) - Client로 보내는 데이터 대기

Client 쪽:
 └─ 수신 버퍼 (최대 30MB) - Apache로부터 받는 데이터 대기

혼잡 시나리오

Client가 매우 느릴 때:

Tomcat → Apache [수신: 거의 비어있음]
         Apache [송신: ████ 28MB 쌓임!] → Client (느림)

Apache→Client 구간이 병목

정리: 각 연결(Client↔Apache, Apache↔Tomcat)의 양쪽 끝에 각각 송신/수신 버퍼가 존재합니다!

좋은 질문입니다! 각 구간별로 정리해드리겠습니다.

1. OS 레벨 TCP 버퍼 (기본 설정)

Linux 시스템 전역 설정:

# 설정 파일 위치
/etc/sysctl.conf

# TCP 수신 버퍼 (최소/기본/최대)
net.ipv4.tcp_rmem = 4096    87380    6291456
                    4KB     85KB     6MB (기본)

# TCP 송신 버퍼 (최소/기본/최대)
net.ipv4.tcp_wmem = 4096    16384    4194304
                    4KB     16KB     4MB (기본)

확인 방법:

sysctl net.ipv4.tcp_rmem
sysctl net.ipv4.tcp_wmem

적용 방법:

# 즉시 적용
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 16384 16777216"

# 영구 적용
echo "net.ipv4.tcp_rmem = 4096 87380 16777216" >> /etc/sysctl.conf
echo "net.ipv4.tcp_wmem = 4096 16384 16777216" >> /etc/sysctl.conf
sysctl -p

2. Apache 설정

설정 파일 위치:

# httpd.conf 또는 apache2.conf

# Tomcat으로 프록시할 때 수신 버퍼 크기
ProxyReceiveBufferSize 0    # 0 = OS 기본값 사용 (권장)
ProxyReceiveBufferSize 131072  # 128KB로 명시 지정

# 송신은 OS 설정 따름

기본값: 0 (OS 설정 사용)

3. Tomcat 설정

설정 파일 위치:

<!-- server.xml -->

<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443"
           socket.rxBufSize="0"   <!-- 수신 버퍼, 0 = OS 기본값 -->
           socket.txBufSize="0"   <!-- 송신 버퍼, 0 = OS 기본값 -->
           />

기본값: 설정하지 않으면 OS 기본값 사용

4. Client (브라우저/다운로드 매니저)

Client의 TCP 버퍼도 OS 설정 따름

  • Windows: 레지스트리 설정
  • Linux: 위의 sysctl 설정
  • Mac: sysctl 설정

각 구간별 정리

┌─────────────────────────────────────────────────┐
│ Client 머신                                      │
│ TCP 버퍼: OS 설정 (tcp_rmem/tcp_wmem)           │
└─────────────────────────────────────────────────┘
                    ↕
┌─────────────────────────────────────────────────┐
│ Apache 서버                                      │
│ 수신: ProxyReceiveBufferSize (기본: 0=OS설정)    │
│ 송신: OS 설정 (tcp_wmem)                        │
└─────────────────────────────────────────────────┘
                    ↕
┌─────────────────────────────────────────────────┐
│ Tomcat 서버                                      │
│ TCP 버퍼: socket.rxBufSize/txBufSize (기본: OS) │
│ 또는 OS 설정 (tcp_rmem/tcp_wmem)                │
└─────────────────────────────────────────────────┘

일반적인 권장 설정

대부분의 경우:

  • Apache: ProxyReceiveBufferSize 0 (기본값 사용)
  • Tomcat: 별도 설정 안함 (기본값 사용)
  • OS: 기본값으로도 충분

고속 대용량 전송이 필요한 경우:

# OS 레벨에서만 조정
net.ipv4.tcp_rmem = 4096 87380 16777216  # 최대 16MB
net.ipv4.tcp_wmem = 4096 16384 16777216  # 최대 16MB

핵심: 대부분은 OS 레벨 설정을 따르며, 애플리케이션에서 명시적으로 지정하지 않는 한 OS 기본값을 사용합니다!


물리다운로드가 10초이상 걸리는경우에 scout 같은 apm 에서는 훨씬 빨리 끝난것처럼 보이는 착시?? 현상은 뭐야?

아주 좋은 질문입니다! 이건 APM이 "애플리케이션 처리 시간"만 측정하기 때문입니다.

APM이 측정하는 시점

@GetMapping("/download")
public void download(HttpServletResponse response) throws IOException {
    File file = new File("/path/to/300mb.zip");

    response.setContentType("application/zip");
    response.setHeader("Content-Length", String.valueOf(file.length()));

    // ← APM 측정 시작

    try (InputStream in = new FileInputStream(file);
         OutputStream out = response.getOutputStream()) {

        byte[] buffer = new byte[8192];
        int bytesRead;

        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
            out.flush();
        }
    }

    // ← APM 측정 종료 (여기서 끝난 것으로 기록!)
    // 하지만 실제로는...
}

// 실제 전송은 계속 진행 중:
// Tomcat → Apache → Client (10초 이상 소요)

실제 타임라인

시간 →

0초: [요청 도착]
     └─ APM 측정 시작

0.1초: [컨트롤러 로직 실행]
       └─ 파일 찾기, 헤더 설정

0.2초: [첫 데이터 청크를 response.getOutputStream()에 쓰기 시작]
       └─ APM "처리 완료!" (0.2초로 기록)
       └─ Scout: ✅ 200ms

       ⚠️ 하지만 실제로는...

0.3초: 데이터 계속 전송 중...
1초:   데이터 계속 전송 중...
5초:   데이터 계속 전송 중...
10초:  데이터 계속 전송 중...
12초: [전송 완료] ← 실제 다운로드 완료
      └─ 스레드 해제

Scout APM이 보는 것 vs 실제

Scout APM:

GET /download/file.zip
응답 시간: 200ms ✅
상태: 200 OK

실제 서버:

GET /download/file.zip
- 애플리케이션 처리: 200ms
- 네트워크 전송: 12초  ← APM이 측정 안 함!
- 스레드 점유: 12초    ← 진짜 문제는 여기!

왜 이런 차이가 발생하나?

APM은 애플리케이션 코드의 성능을 측정:

APM 측정 범위:
┌─────────────────────────────┐
│ 컨트롤러 진입                │
│ 비즈니스 로직 실행           │
│ response.write() 첫 호출     │ ← 여기서 끝
└─────────────────────────────┘

APM이 측정 안 하는 범위:
└─ 네트워크 전송 (12초)
└─ 클라이언트 수신 (느린 네트워크)

스레드 점유 시간을 제대로 보려면?

1. 서버 로그에 직접 기록

@GetMapping("/download")
public void download(HttpServletResponse response) {
    long startTime = System.currentTimeMillis();

    try {
        // ... 파일 전송
    } finally {
        long duration = System.currentTimeMillis() - startTime;
        log.info("실제 전송 시간: {}ms", duration);  // 12000ms
    }
}

2. Tomcat Access Log 확인

<!-- server.xml -->
<Valve className="org.apache.catalina.valves.AccessLogValve"
       pattern="%h %l %u %t &quot;%r&quot; %s %b %D"
       />
       <!-- %D = 응답 시간 (밀리초) -->
192.168.1.100 - - [14/Nov/2025:10:00:00 +0900] "GET /download/file.zip HTTP/1.1" 200 314572800 12543
                                                                                                ^^^^^ 
                                                                                            실제 12.5초

3. Apache Access Log

LogFormat "%h %l %u %t \"%r\" %>s %b %D" combined
# %D = 마이크로초 단위 응답 시간

정리

Scout APM: "컨트롤러가 200ms 만에 응답했어요!" ✅
실제 서버: "스레드를 12초간 점유했어요..." ⚠️

→ 착시 현상의 원인: APM은 애플리케이션 로직만 측정
→ 실제 문제: 네트워크 전송 시간 + 스레드 점유

대용량 파일 다운로드는 APM이 빠르다고 해도, 실제로는 스레드를 오래 점유하므로 Apache/Nginx 같은 웹 서버가 직접 서빙하는 게 훨씬 효율적입니다!

대부분 비공개다. 뭐... 전문가들에겐 전혀 전문적이지 않지만 일반인들에게는 전문적인 내용들이라 -_-;

회사에서는 웬만하면 여기에 쓸데없는 글을 적지 않는데 남겨본다. 뭐 우리회사? 전회사? 의 서비스니가 ... 괜찮겠지 -ㅅ-;?

 

입추가 지나고.. 어느새 무더위가 조금씩 사라지는 느낌이 들고 있다. 새벽에 덜 더워졌고, 아침에도 전보다 상쾌?? 하다. 

 

아..일해야지; 일하러 고! 

 

해야할건 너무 많지만 우리에게.. 시간은 유한하며, 그럼 뭘 포기해야하는지는 알지만 그러기엔 또 인생은 한번이고 짧다...

앞뒤가 안맞단 말이지... 

젠킨스 버전업이 이루어지면서 내부적으로 jdk 11 을 이용하게 되었다.

이때 젠킨스를 이용한 빌드시에 사용하는 remote 패키지가 11로 컴파일된거라 구버전의 젠킨스에서 빌드하던 jdk 8버전의 프로젝트들은 빌드시 remote.jar(jdk 11) 실행에 실패하면서 빌드가 실패나버린다.(내용은 버전 맞지 않음)

 

그럼 어떻게 해야할까?

 

우선 젠킨스자체의 메이븐 빌드 로 아이템을 만들지 말고, 프리스타일로 만든뒤

 

쉘로 직접 빌드하게 해주면되긴한다. 

 

쉘환경이 jdk 8 이면된다.

좀더 설명하면

 

1. jenkins build job 생성시 메이븐이아니라 프리스타일로 생성

2. 생성시 만들어진 이름으로, 빌드실행하면 젠킨스의 빌드노드 홈의, workspace 디렉토리 이하에 그 빌드아이템의 방이 생김

3. 해서... 우선 스크립트(execute shell) 는 비워두고 git 등의 정보를 입력하여 item 을 만들고, 그 item 을 빌드하면 생성한 item 이름으로 디렉토리가 생김. 

4. 그 디렉토리안에 보면 git 의 내용을 clone 해온걸 볼 수 있음

5. 여기서 단순히 jar 빌드이면 mvn 명령으로 빌드시킬수 있도록 직접 테스트 해보고 빌드 잘 되는 쉘 명령어를 item 의 execute shell 에 넣어주면됨.

6. 여기서 만약, 빌드 노드에 settings.xml 이 없다면 원래는 젠킨스의 아이템 생성시 메이븐 설정에 provided settings.xml 항목에 임의의 xml 을 정의해서 그걸 빌드에 사용하게 하는데, 우리는 쉘에서 하는거라 직접해줘야한다.

7. 해서 간단히, 해당 git 안에 그 프로젝트에 맞는 settingsl.xml 을 만들고 거기에 설정 넣어둔뒤 execute shell 실행시 실행될 mvn 옵션으로 -s settings.xml   처럼 맞는 xml 을 넣어주면된다.

 

 

전에는 maven 으로 kotlin , java 를 섞어서 프로젝트를 만들기도 했다. (최초에만 그랬고 그뒤부턴 코틀린만으로 된 프로젝트를 만들어왔긴했다)

 

다만 virtual thread 가 나온이후 java 21 에 대한 관심이 올라가면서... 그리고 테스트 목적으로 하나의 프로젝트만 만들어서 테스트해볼때 문법확인상  java, kotlin 둘다되는 프로젝트를 설정해보려고 찾아봤다  gradle , kotlin dsl  환경으로 했을때, ... 매우 간단했다;;

 

기본적은 springboot는 springboot init (kotlin, gradle kotlin dsl , jar )을 사용해서 만들었다. 거기에 한줄만 추가한 내용이다.

 

plugins 에 한줄만 추가하고  kotlin 과 동등한 패키지 레벨로 java 디렉토리(패키지)만 만들어주면되는거였다.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "3.2.3"
    id("io.spring.dependency-management") version "1.1.4"
    java
    kotlin("jvm") version "1.9.22"
    kotlin("plugin.spring") version "1.9.22"
    kotlin("plugin.jpa") version "1.9.22"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-batch")
    implementation("org.springframework.boot:spring-boot-starter-data-jpa")
//    implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
//    implementation("org.springframework.boot:spring-boot-starter-data-redis")
    implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("org.apache.kafka:kafka-streams")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3")
    implementation("org.springframework.kafka:spring-kafka")
    runtimeOnly("com.h2database:h2")
    runtimeOnly("com.mysql:mysql-connector-j")
    runtimeOnly("com.oracle.database.jdbc:ojdbc11")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3")
    testImplementation("org.springframework.batch:spring-batch-test")
    testImplementation("org.springframework.kafka:spring-kafka-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs += "-Xjsr305=strict"
        jvmTarget = "17"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

 

그래들이 지원되지 않아서 하이라이팅이 되진 않겠지만 최초 spring init 으로 생성후 한줄만 더해줬다. 위에서 언급한것 같이 plugins 에 java 한줄만 넣었다. 이게 다였다. 만약 java 의 버전 관련 수정이 필요하다면 java { ... 이하 부분에서 수정하면된다. 아무튼 매우.. 간단했다. 

 

tree 구조는 아래와 같다

➜  springbootdemo git:(main) tree -I build
.
├── HELP.md
├── build.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           └── springbootdemo
    │   │               └── controller
    │   │                   └── TestControllerJava.java
    │   ├── kotlin
    │   │   └── com
    │   │       └── example
    │   │           └── springbootdemo
    │   │               ├── SpringbootdemoApplication.kt
    │   │               └── controller
    │   │                   └── TestControllerKotlin.kt
    │   └── resources
    │       ├── application.properties
    │       ├── static
    │       └── templates
    │           └── hello.html
    └── test
        ├── java
        │   └── com
        │       └── example
        │           └── springbootdemo
        │               └── TestJava01.java
        └── kotlin
            └── com
                └── example
                    └── springbootdemo
                        ├── SpringbootdemoApplicationTests.kt
                        └── Test01.kt

아.. jenkins 의 파이프라인에서 환경변수 변경해서 ... 실행하는 방법이 있었는데;;;

 

바로 이럴때! chatgpt 에게 물어봤음  2024. 2. 27. 매우 간단하게 리마인드 가능했다.

 

 

Jenkins 파이프라인 스크립트에서 실행하는 콘솔의 환경 변수를 변경하려면, withEnv 스텝을 사용할 수 있습니다. withEnv 스텝은 특정 블록의 실행 동안 환경 변수를 임시로 설정하거나 수정할 수 있게 해줍니다. 이는 주로 steps 블록 내부에서 사용됩니다.

예를 들어, JAVA_HOME 환경 변수의 값을 변경하고 싶다면, 다음과 같이 withEnv 블록을 사용하여 해당 환경 변수에 새 값을 할당할 수 있습니다:

pipeline {
    agent any
    stages {
        stage('Set JAVA_HOME') {
            steps {
                // withEnv를 사용하여 JAVA_HOME 환경 변수 설정
                withEnv(["JAVA_HOME=/new/path/to/java"]) {
                    // 쉘 스크립트 또는 배치 스크립트를 실행하여 새 JAVA_HOME을 사용
                    sh 'echo $JAVA_HOME'
                    // 또는 Windows 배치 스크립트를 사용하는 경우
                    // bat 'echo %JAVA_HOME%'
                }
            }
        }
    }
}

 

이 예제에서, withEnv 블록 내부에서 JAVA_HOME 환경 변수는 /new/path/to/java로 설정됩니다. 이 변경은 withEnv 블록 내부에서만 유효하며, 블록을 벗어나면 원래 값(또는 설정되지 않은 경우)으로 복원됩니다.

sh 스텝은 Unix 기반 시스템(예: Linux, macOS)에서 쉘 스크립트를 실행할 때 사용되며, bat 스텝은 Windows 기반 시스템에서 배치 스크립트를 실행할 때 사용됩니다. 사용하는 Jenkins 노드의 운영 체제에 따라 적절한 스텝을 선택하세요.

withEnv를 사용하면 파이프라인의 특정 부분에서만 환경 변수를 변경할 수 있어, 파이프라인의 다른 부분에는 영향을 주지 않으면서 유연하게 환경을 제어할 수 있습니다.

docker 의 이미지를 실행할때 ... 몇가지 옵션을 줘야했다. 결과적으로만 말하자면

 

docker run -it -p 3301:3306 -e MYSQL_ROOT_PASSWORD=root mysql

-p 

아웃:인 포트값이다. 즉 mysql 이 3306을 열고 있고 host 머신은 3301로 접근하는거다. 해서 3301로 접근해서 도커의 3306으로 접속한다. 

 

-e 

환경변수를 주는거다. 그냥 mysql (여기서는 8.1) 을 실행하면 필수옵션이 없어서 실행 실패가 뜬다.

    You need to specify one of the following:
    - MYSQL_ROOT_PASSWORD
    - MYSQL_ALLOW_EMPTY_PASSWORD
    - MYSQL_RANDOM_ROOT_PASSWORD

이경우는 위와같이 암호를 그냥 설정했다. 아니면 두번째 암호를 비워둠을 허용하는걸로 퉁쳐도 될듯한데... 아무튼

 

-it

이건 컨테이너의 output 을 그대로 찍어주는거다. 전면에 뜨는데, 이걸 백그라운드로 (데몬) 처리하세 화면에 아무것도 안나오게 하려면 d 옵션도 함께 주면된다. 즉 -dit

 

 

여기까지는 도커의 실행이고 dbeaver 에서 접근시 에러가 난다. 내용은 without ssl 인경우 allow 해줘야 하는 옵션이 있는데 그걸 커넥션 설정에서 안해서 그렇다는거다.

 

이 화면에서 allowPublicKeyRetrieval 을 true 로 해주면된다. 

git 사용중에 갑자기 editor 연결시 저런 에러가 난다면???

editor 를 다시 설정하는데 정확히는

 

git config --global core.editor vim -f

 

-f 옵션으로 vim 을 사용해라; 

 

https://stackoverflow.com/questions/22699614/git-commit-messages-lost-by-vi

 

Git commit messages lost by vi

I'm a clumsy typist, and I don't use vi/vim very often, but I do use it for commit messages. However, if you type a wrong command while editing a commit message (:Wq, say, instead of :wq), when you

stackoverflow.com

 

series x 아니고 one x .. 이전 세대 게임기이다. ms 가 출시한 게임기(라고 쓰고 멀티미디어 기기라고 읽는...) 이다.

 

아니.. 시리즈 엑스도 아니고(현세대 기종) 갑자기 왜 이렇게 된거냐면? 그 의식의 흐름을 쫓아가보자...

 

읽기전 지식!

시리즈 엑스 == series x, 시리즈 에스 == series s   이들은 현세대 머신들

원 엑스 == one x , 원 에스 == one s, 이들은 전세대 머신들... 

x 가 더 상위기종이고 s 는 보급기 

그외 더 이전세대인 엑스박스 원 이 있다. (one s 와 사실상 성능은 비슷.. 한걸로 기억함;)

 

  1. 아이들이 마인크래프트의 매력을 느끼기 시작함
  2. 스위치가 집에 있어서 마인크래프트 스위치 사줌
  3. 사실 그와 별개로..난 이미 pc 와 안드로이드에 마인크래프트 구매한게 있음. 다만 pc 는 방에 있고, 타블렛을 주진 않으므로.. 스위치로 단결
  4. 그 와중에.. 난 게임패스 사용자이고(ms 의 게임 구독서비스) 마인크래프트 시리즈를 보다가 던전스를 해봄
  5. .... 재밌음... 이거 디아의 그 느낌이군. 당연하지.. 핵앤슬래시에 파밍이면.. 말 다했다;
  6. 우연히 둘째와 해봄 (첫째가 입원해 있는동안). 둘째도 재밌어함. 다만...
  7. 혼자 시키니 어려워한다. 그렇지.. 이게 순한맛 디아블로라고 해도 은근히 컨트롤 요구하더라. 안하면 죽음;
  8. 해서 게임패스를 쓰니까 클라우드로 2인용하려고 했는데... 안됨; 확인해보니 클라우드로는 다인용 게임들이 모두 다인용 지원해주는건 아닌데 이 게임이 지원해주지 않는게임임
  9. 이제 부터 방법을 찾기 시작함. 간단히 스위치용 던전스를 사면되겠지!?
  10. 실패... 주문까지 했으나.. 후기를 보니 못해먹겠다는 평과 이거하다가 게임기 다른거 사서한다는 글들이 있을정도임
  11. 주문 취소하고 pc 가 nvidia고 난 쉴드tv 도 있으니까 nvidia 의 스트리밍게임 기능을 이용하기로 함. 
  12. 사실상 실패. 곧 서비스 접을거라고 발표함; 그럼 각종 원격 툴을 이용해서 해야지 뭐... 하지만 귀찮음;;; 네이티브 지원이 아닌것들의 불편함은 익히 잘 알고 있음. 
  13. .... 그러다 갑자기 엑스박스  매물이 눈에 보임. 얼마전에 series s 가 20만원초반에 올라오던게 기억남. 
  14. 간간히 역시 있긴한데... 애매하다. 이거하려고 20만원중반을 지불해야하나;
  15. 그러다 엑스박스원 매물이 보이기 시작함. 확인해봄
  16. 오.. 싸다! 엑스박스 one s 알아보다가... one x  매물도 같이봄. 
  17. series s 는 광학드라이브가 없는데, one s one x 는 광학드라이브가 있음. 즉 ... 집에없는 dvd/블루레이 플레이가 생기는것임!!!!  해서 엑스박스 one s/x  를 알아보기 시작함
  18. 둘은... dvd/블루레이가 된다지만 사람들이 엑스쪽이 좀 더 낫다고 평함. 즉 플레이어 기기로 쓰기에 엑스를 추천. 드디어 집에 dvd/블루레이 블레이어가 생김!!!!! 이거 매우 크다!
  19. 성능도... 엑스박스 원 (not s, not x) 에서 던전스를 한 분들왈 버벅그림이 가끔 있다고 했다. one s 가 one 과 비등한 성능인걸 감안하면 one x 로 기울어짐
  20. 또하나의 큰 이유!!!!!.... 레드데드리뎀션 2 를 매우 재밌게 즐겼는데, 레데리 1은 엑박으로 할 경우 인헨스드라고 해서 4k 업 처리가 된다!!!!  레데리 1 이 pc 로 나온적이 없기에 즐길수 없음에도 불구하고 엑박용 레디리1을 미리 구입해놓을정도로 매력을 느낌게임이고 이번에 엑박 one x 를 구입하면 이걸 즐길수 있다!!!!
  21. ... 해서 샀다;

 

요약하자면

  1. 마인크래프트 던전을 여러명이서 하고 싶었다.
  2. 마땅한 대안이 없어서 고민하다가 엑박one x 가 10만원초반이라 구입
  3. 더불어 레디리 1을 즐길수도 있고  dvd/블루레이 플레이어도 덤으로 생겼다.
  4. 매우 잘 돌아감. 만족.
  5. kodi 도 설치됨!!! 즉  각종 OTT 이용가능!

 

xbox one x 장점은?

  1. 지금은 중고가가 매우 착한편이다. 10만원 초반 및 10만원 아래까지도 가능(컨트롤러 미동봉)
  2. AAA 급 타이틀이 아닌이상 그럭저럭 잘 돌아간다. 아직 현역기라는게 틀린말은 아닌듯. 1080p 로 고정하면 할만하다. 
  3. 게임패스를 통해서 매우 저렴하게 게임들을 즐길 수 있다. (이건 가입자에 한정된)
  4. 미디어기기로 훌륭하다. dvd/bluray(3d가능), 각종파일 재생 ( by kodi), OTT(역시 kodi) 등... 아! 디즈니나, 넷플릭스는 앱으로 존재한다.
  5. 기기도 작은편이다. 플레이어 정도의 크기임. (무게는 크기대비 무겁다. 쿨링성능이 괜찮으편임) 

 

nvidia 쉴드 대비 단점은?

  1. 아무래도 전용앱이 딸림. (쉴드는 안드로이드 tv 라 그런대로 많다)
  2. 에뮬돌리는게 좀 애매함. (사실상 어렵다)
    레트로아크가 지원되기 시작하는것 같은데 제대로 지원을 안해서 스펙대비 성능이 안나옴
  3. 부팅이 좀 오래걸림.

 

xbox on x VS nvidia shield ?

글쎄다... 게임에 관심이 없다면 쉴드가 더 나을수 있다. 그리고 쉴드는 하이퍼스핀이라는 에뮬을 통해서 편하게 고전게임을 즐길 수 있다. 그리고 OTT 전용앱이 많아서 편하게 시청가능함. kodi 는 당근이고!  다만 게임이 된다는거지, 각종설정등은 엑박에 비해서 딸린다. 불편함. 

 

다만 게임에도 관심이 있고, player 가 필요하면 엑박이 더 낫다. 다되거든... 다만 상대적으로 불편하다. 전용앱도 적고... kodi 를 통해서 그나마 가능하다. 게임에 있어서 컨트롤러의 연결이나 지원등이 훨 낫다. 편의성에서는 비교가 안된다고 본다. 

 

 

 

+ Recent posts