여기에서 web과 database는 각각 하나의 서비스. 이 경우, 각 서비스는 각각 하나의 컨테이너를 생성하지만, 필요에 따라 한 서비스에서 여러 컨테이너를 생성할 수도 있습니다 (예: 스케일링 목적으로).
결국, "서비스"는 Docker Compose에서 응용 프로그램의 한 부분 (예: 웹 서버, 데이터베이스)을 나타내며, 이 서비스를 구성하는 데 필요한 설정과 함께 도커 이미지 정보를 포함합니다.
사용방법
docker-compose build:
이 명령어는 docker-compose.yml 파일에 정의된 모든 서비스의 이미지를 빌드합니다. docker-compose.yml 파일에서 build: 섹션을 사용하여 Dockerfile의 위치나 빌드 컨텍스트 등을 지정한 서비스에 대해서만 이 명령어를 사용해야 합니다.
docker-compose up -d:
위에서 빌드한 이미지들의 실행 인스턴스인 컨테이너들을 만들어 실행 -d 옵션은 "detached mode"를 의미하며, 백그라운드에서 컨테이너를 실행하라는 것을 의미 이미지가 없다면 빌드도 시도하기 때문에 docker-compose build 없이 이것만 실행해도 되긴 하나,
코드 변경시 재빌드해주진 않기 때문에 코드 변경이 있었다면 build후 up해야 한다.
docker-compose down -v:
up과 반대로 컨테이너들 중단하고 없애준다.
-v하면 관련 데이터 볼륨도 제거해준다.
여기서 데이터 볼륨(Data Volume)은 Docker 컨테이너 파일 시스템의 일부를 호스트 시스템에 저장하는데 사용되는 매커니즘으로, 컨테이너간 데이터를 공유하는 공유폴더 개념으로 쓰이거나 데이터를 영구적으로 저장할수 있게 해준다.
그 예시로는 (DB, 로그, config file등이 있다)
docker-compose ps
docker-compose로 관리되는 컨테이너들의 현재 상태와 관련된 정보를 조회
다음내용 확인가능
서비스 상태 확인: docker-compose up 명령을 사용하여 여러 서비스를 시작한 후, 각 서비스의 컨테이너가 올바르게 실행 중인지, 혹은 중지된 상태인지를 확인하기 위해 사용됩니다.
문제 진단: 서비스에 문제가 발생했을 때, 어떤 컨테이너가 문제를 일으키고 있는지 확인하기 위해 사용될 수 있습니다. 예를 들어, 컨테이너가 계속 재시작되는 경우, docker-compose ps를 통해 해당 컨테이너의 상태를 확인할 수 있습니다.
포트 정보 확인: 각 컨테이너에서 어떤 포트가 호스트와 연결되었는지 확인하려 할 때 사용됩니다.
스케일링 확인: docker-compose up --scale 명령을 사용하여 서비스의 인스턴스 수를 조정한 경우, 현재 실행 중인 인스턴스 수를 확인하기 위해 사용됩니다.
컨테이너 이름 확인: docker-compose로 시작된 컨테이너들은 특정한 네이밍 규칙을 가지고 있습니다. 이 이름을 확인하기 위해 docker-compose ps를 사용할 수 있습니다.
아래는 예시
Name Command State Ports
--------------------------------------------------------------------------------------------------------------------------------------------------
table-walkthrough_data-generator_1 /docker-entrypoint.sh Up
table-walkthrough_grafana_1 /run.sh Up 0.0.0.0:3000->3000/tcp,:::3000->3000/tcp
table-walkthrough_jobmanager_1 /docker-entrypoint.sh stan ... Up 6123/tcp, 0.0.0.0:8082->8081/tcp,:::8082->8081/tcp
table-walkthrough_kafka_1 start-kafka.sh Up 0.0.0.0:9092->9092/tcp,:::9092->9092/tcp
table-walkthrough_mysql_1 docker-entrypoint.sh --def ... Up 3306/tcp, 33060/tcp
table-walkthrough_taskmanager_1 /docker-entrypoint.sh task ... Up 6121/tcp, 6122/tcp, 6123/tcp, 8081/tcp
table-walkthrough_zookeeper_1 /bin/sh -c /usr/sbin/sshd ... Up 0.0.0.0:2181->2181/tcp,:::2181->2181/tcp, 22/tcp, 2888/tcp, 3888/tcp
sevity@sevityubuntu:~/workspace/flink-playgrounds/table-walkthrough$
후자가 Resolver(리졸버)만 구현하면 스키마를 자동생성해주고 kotlin 타입과 연동되는등 kotlin을 사용한다면 더 편리한 측면이 있지만, 여기서는 전자를 사용한 기준으로 서술한다.
expediagroup 아티펙트의 경우, 내 경우엔 /graphql 404문제가 해결이 안돼서 springframework를 쓰기로 했다. 추가로 조사해보니 webmvc대신 webflux로 교체해야 호환되는 이슈도 있었다(여기) spring-boot-starter-web 대신 spring-boot-starter-webflux의존성으로 바꿔야 하는데 WebConfig.kt등 여러곳에서 코딩방식을 바꿔야 하는 걸로 보인다.
클라이언트 사이드(React/Next.js)
관련 library설치
npm install @apollo/client graphql
아폴로?
Apollo Client는 JavaScript 어플리케이션에서 GraphQL API와 통신할 수 있게 해주는 라이브러리입니다.
Facebook에서는 GraphQL을 발명했으며, Relay라는 GraphQL 클라이언트를 만들어 공개했습니다. 그러나 Apollo가 Relay보다 더 널리 사용되는 이유는 사용자 친화적: Apollo는 사용자 친화적이고, 초보자에게 친숙하며, 설정이 상대적으로 간단합니다. 문서화도 잘 되어 있어, 개발자들이 쉽게 접근하고 사용할 수 있습니다. 커뮤니티 지원: Apollo는 강력한 커뮤니티 지원을 받고 있으며, 다양한 추가 기능과 툴이 개발되고 있습니다. 또한 꾸준한 업데이트와 개선이 이루어지고 있어, 더 많은 개발자들이 Apollo를 선호하게 되었습니다.
src/main/resources/graphql/schema.graphqls 파일에 쿼리를 추가
type Query {
submissionCountByProblem(problemId: ID!): Int
}
2. 서비스 수정
SubmissionService에 getSubmissionCountByProblem매서드를 추가하여 문제별 제출 수를 가져옴
@Service
class SubmissionService(private val submissionRepository: SubmissionRepository) {
// 아래는 기존에 존재하던 매서드
fun submitProblem(userId: Long, problemId: Int, code: String): Submission {
val submission = Submission(
userId = userId,
problemId = problemId,
code = code,
status = "PENDING" // 초기 상태
)
return submissionRepository.save(submission)
}
// 아래 매서드 추가
fun getSubmissionCountByProblem(problemId: Int): Int {
return submissionRepository.countByProblemId(problemId)
}
}
3. 컨트롤러에 로직 추가
컨트롤러에@QueryMapping 어노테이션을 사용하여 submissionCountByProblem GraphQL쿼리를 처리하는 메서드를 추가(엔드포인트 추가는 아니지만 약간 유사)
package com.sevity.problemservice.controller
import ...
@RestController
class SubmissionController(private val submissionService: SubmissionService) {
// 기존 코드
// ...
@QueryMapping
fun submissionCountByProblem(@Argument problemId: Int): Int {
return submissionService.getSubmissionCountByProblem(problemId)
}
}
expediagroup 아티펙트의 경우, 위의 해결책을 적용해도 여전히 404가 떴고, 추가로 조사해보니 webmvc대신 webflux로 교체해야 하는 이슈가 있었다(여기) spring-boot-starter-web 대신 spring-boot-starter-webflux의존성으로 바꿔야 하는데 WebConfig.kt등 여러곳에서 코딩방식을 바꿔야 하는 걸로 보인다.
application.properties에서 포트설정해주고(이때 src/main/resources뿐 아니라 src/test/resources에 있는 파일도 해줘야함에 주의)
# in application.properties
grpc.server.port = 50051
다음처럼 gRPC서버 띄욱 listen작업도 해줘야 했다.
package com.sevity.authservice.config;
import ...
@Configuration
public class GrpcServerConfig {
private static final Logger logger = LoggerFactory.getLogger(GrpcServerConfig.class);
@Autowired
private SessionServiceImpl sessionService;
private Server server;
@Value("${grpc.server.port}")
private int port;
@PostConstruct
public void startServer() throws IOException {
server = ServerBuilder
.forPort(port)
.addService(sessionService) // Your gRPC service implementation
.build();
server.start();
logger.info("sevity gRPC server started on port {}", port);
logger.info("sevity gRPC service name: {}", sessionService.getClass().getSimpleName());
}
@PreDestroy
public void stopServer() {
if (server != null) {
server.shutdown();
}
logger.info("sevity gRPC server stopped");
}
}